import { z } from 'zod' import { getClientById, validateRedirectUri, validateScope } from '../../modules/oauth' import { createAuthorizationCode } from '../../modules/oauth' const authorizeSchema = z.object({ response_type: z.enum(['code', 'token']), client_id: z.string().min(1), redirect_uri: z.string().min(1), scope: z.string().optional(), state: z.string().optional(), code_challenge: z.string().optional(), code_challenge_method: z.enum(['S256', 'plain']).optional() }) export default defineEventHandler(async (event) => { const query = getQuery(event) as Record const result = authorizeSchema.safeParse({ response_type: query.response_type, client_id: query.client_id, redirect_uri: query.redirect_uri, scope: query.scope, state: query.state, code_challenge: query.code_challenge, code_challenge_method: query.code_challenge_method }) if (!result.success) { throw createError({ statusCode: 400, message: result.error.errors[0].message }) } const { response_type, client_id, redirect_uri, scope, state, code_challenge, code_challenge_method } = result.data const client = getClientById(client_id) if (!client) { throw createError({ statusCode: 400, message: '无效的客户端' }) } if (!client.is_active) { throw createError({ statusCode: 400, message: '客户端已被禁用' }) } if (!validateRedirectUri(client, redirect_uri)) { throw createError({ statusCode: 400, message: '无效的重定向地址' }) } if (scope && !validateScope(client, scope)) { throw createError({ statusCode: 400, message: '无效的授权范围' }) } if (!client.grant_types.includes('authorization_code') && response_type === 'code') { throw createError({ statusCode: 400, message: '客户端不支持授权码模式' }) } if (!client.grant_types.includes('implicit') && response_type === 'token') { throw createError({ statusCode: 400, message: '客户端不支持隐式授权模式' }) } const authHeader = getHeader(event, 'authorization') if (!authHeader || !authHeader.startsWith('Bearer ')) { throw createError({ statusCode: 401, message: '请先登录' }) } const { verifyToken } = await import('../../utils/jwt') const token = authHeader.substring(7) const payload = verifyToken(token) if (!payload || payload.type !== 'access') { throw createError({ statusCode: 401, message: '无效的访问令牌' }) } if (response_type === 'code') { const code = createAuthorizationCode( payload.userId, client_id, redirect_uri, scope, code_challenge, code_challenge_method ) const params = new URLSearchParams({ code }) if (state) params.append('state', state) return sendRedirect(event, `${redirect_uri}?${params.toString()}`) } else { const { createTokenWithoutRefresh } = await import('../../modules/oauth') const { accessToken, expiresAt } = createTokenWithoutRefresh(payload.userId, client_id, scope) const fragmentParams = new URLSearchParams({ access_token: accessToken, token_type: 'Bearer', expires_in: String(Math.floor((expiresAt.getTime() - Date.now()) / 1000)) }) if (state) fragmentParams.append('state', state) return sendRedirect(event, `${redirect_uri}#${fragmentParams.toString()}`) } })