diff --git a/backend/src/middlewares/auth.ts b/backend/src/middlewares/auth.ts index de789ed..85e2949 100644 --- a/backend/src/middlewares/auth.ts +++ b/backend/src/middlewares/auth.ts @@ -1,17 +1,7 @@ import { Context, Next } from 'hono'; -import jwt from 'jsonwebtoken'; -import config from '../config'; import supabase from '../utils/supabase'; -// Interface for JWT payload -interface JwtPayload { - sub: string; - email: string; - iat: number; - exp: number; -} - -// Middleware to verify JWT token +// Middleware to verify Supabase token export const authMiddleware = async (c: Context, next: Next) => { try { // Get authorization header @@ -25,41 +15,24 @@ export const authMiddleware = async (c: Context, next: Next) => { const token = authHeader.split(' ')[1]; try { - // 验证 JWT token - const decoded = jwt.verify(token, config.jwt.secret) as JwtPayload; + // 验证 Supabase token + const { data, error } = await supabase.auth.getUser(token); - // 特殊处理 Swagger 测试 token - if (decoded.sub === 'swagger-test-user' && decoded.email === 'swagger@test.com') { - // 为 Swagger 测试设置一个模拟用户 - c.set('user', { - id: 'swagger-test-user', - email: 'swagger@test.com', - name: 'Swagger Test User' - }); - - // 继续到下一个中间件或路由处理器 - await next(); - return; + if (error || !data.user) { + return c.json({ error: 'Unauthorized: Invalid token' }, 401); } // 设置用户信息到上下文 c.set('user', { - id: decoded.sub, - email: decoded.email + id: data.user.id, + email: data.user.email || '' }); // 继续到下一个中间件或路由处理器 await next(); - } catch (jwtError) { - if (jwtError instanceof jwt.JsonWebTokenError) { - return c.json({ error: 'Unauthorized: Invalid token' }, 401); - } - - if (jwtError instanceof jwt.TokenExpiredError) { - return c.json({ error: 'Unauthorized: Token expired' }, 401); - } - - throw jwtError; + } catch (error) { + console.error('Token verification error:', error); + return c.json({ error: 'Unauthorized: Invalid token' }, 401); } } catch (error) { console.error('Auth middleware error:', error); @@ -67,21 +40,23 @@ export const authMiddleware = async (c: Context, next: Next) => { } }; -// Generate JWT token -export const generateToken = (userId: string, email: string): string => { - const secret = config.jwt.secret; - const expiresIn = config.jwt.expiresIn; - - return jwt.sign( - { - sub: userId, +// Get Supabase token +export const getSupabaseToken = async (email: string, password: string) => { + try { + const { data, error } = await supabase.auth.signInWithPassword({ email, - }, - secret, - { - expiresIn, + password + }); + + if (error || !data.session) { + return null; } - ); + + return data.session.access_token; + } catch (error) { + console.error('Error getting Supabase token:', error); + return null; + } }; // Verify Supabase token diff --git a/backend/src/routes/auth.ts b/backend/src/routes/auth.ts index 56314a4..836cd79 100644 --- a/backend/src/routes/auth.ts +++ b/backend/src/routes/auth.ts @@ -1,7 +1,6 @@ import { Hono } from 'hono'; -import { generateToken, verifySupabaseToken } from '../middlewares/auth'; +import { verifySupabaseToken, getSupabaseToken } from '../middlewares/auth'; import supabase from '../utils/supabase'; -import jwt from 'jsonwebtoken'; const authRouter = new Hono(); @@ -45,8 +44,12 @@ authRouter.post('/register', async (c) => { return c.json({ error: profileError.message }, 500); } - // Generate JWT token - const token = generateToken(authData.user.id, authData.user.email!); + // 直接使用 Supabase 的 session token + const sessionToken = authData.session?.access_token; + + if (!sessionToken) { + return c.json({ error: 'Failed to generate token' }, 500); + } return c.json({ message: 'User registered successfully', @@ -55,7 +58,7 @@ authRouter.post('/register', async (c) => { email: authData.user.email, name, }, - token, + token: sessionToken, }, 201); } catch (error) { console.error('Registration error:', error); @@ -77,8 +80,12 @@ authRouter.post('/login', async (c) => { return c.json({ error: error.message }, 400); } - // 使用与 authMiddleware 一致的方式创建 JWT - const token = generateToken(data.user.id, data.user.email || ''); + if (!data.session) { + return c.json({ error: 'Failed to login' }, 500); + } + + // 直接使用 Supabase 的 session token + const token = data.session.access_token; // 只返回必要的用户信息和令牌 return c.json({ @@ -132,22 +139,21 @@ authRouter.post('/refresh-token', async (c) => { return c.json({ error: 'No token provided' }, 401); } - // 验证当前token - const user = await verifySupabaseToken(token); + // 使用 Supabase 刷新 token + const { data, error } = await supabase.auth.refreshSession({ + refresh_token: token + }); - if (!user) { + if (error || !data.session || !data.user) { return c.json({ error: 'Invalid token' }, 401); } - // 生成新token - const newToken = generateToken(user.id, user.email || ''); - return c.json({ message: 'Token refreshed successfully', - token: newToken, + token: data.session.access_token, user: { - id: user.id, - email: user.email, + id: data.user.id, + email: data.user.email, }, }); } catch (error) { diff --git a/backend/src/swagger/index.ts b/backend/src/swagger/index.ts index ee6db8a..bf92400 100644 --- a/backend/src/swagger/index.ts +++ b/backend/src/swagger/index.ts @@ -1,7 +1,6 @@ import { swaggerUI } from '@hono/swagger-ui' import { Hono } from 'hono' -import jwt from 'jsonwebtoken' -import config from '../config' +import supabase from '../utils/supabase' // 创建 OpenAPI 规范 export const openAPISpec = { @@ -1839,26 +1838,52 @@ export const createSwaggerUI = () => { // 添加临时的 token 生成端点,仅用于 Swagger 测试 app.get('/api/swagger/token', async (c) => { try { - // 创建一个临时 token,与 authMiddleware 中的验证方式一致 - const token = jwt.sign( - { - sub: 'swagger-test-user', - email: 'swagger@test.com', - }, - config.jwt.secret, - { - expiresIn: '1h', + // Swagger 测试用户的凭据 + const email = 'swagger@test.com'; + const password = 'swagger-test-password'; + + // 尝试使用 Supabase 认证 + const { data, error } = await supabase.auth.signInWithPassword({ + email, + password + }); + + if (error || !data.session) { + // 如果登录失败,可能需要先创建测试用户 + console.log('尝试创建 Swagger 测试用户...'); + + // 尝试创建测试用户 + await supabase.auth.admin.createUser({ + email, + password, + email_confirm: true, + }); + + // 再次尝试登录 + const loginResult = await supabase.auth.signInWithPassword({ + email, + password + }); + + if (loginResult.error || !loginResult.data.session) { + return c.json({ error: '无法创建测试用户凭据', details: loginResult.error?.message }, 500); } - ); + + return c.json({ + message: '已创建 Swagger 测试用户并生成 token', + token: loginResult.data.session.access_token, + usage: '在 Authorize 对话框中输入: Bearer [token]' + }); + } return c.json({ message: '此 token 仅用于 Swagger UI 测试', - token, + token: data.session.access_token, usage: '在 Authorize 对话框中输入: Bearer [token]' }); } catch (error) { console.error('Error generating swagger token:', error); - return c.json({ error: 'Failed to generate token' }, 500); + return c.json({ error: '生成 token 失败', details: error instanceof Error ? error.message : String(error) }, 500); } });