Next.js + Mantine mock SSO service providing account/password, phone verify-code, and Feishu QR login. Issues a one-time sso_code that the external app exchanges for user info. Includes: - Feishu callback fix: guard against duplicate/concurrent /api/login submissions of the same single-use authorization code (feishuLogin once-guard + memoized onLoginSuccess to stop effect re-fire). - ADAPTATION_GUIDE.md: how to switch from the in-memory code store to the real backend auth/index + inner_get_user_info endpoints. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
import { NextResponse } from 'next/server'
|
||
import { codeStore } from '@/utils/code-store'
|
||
|
||
/**
|
||
* SSO Code 验证接口
|
||
*
|
||
* 外部应用拿到 sso_code 后,调用此接口换取用户信息。
|
||
* POST /api/auth/verify
|
||
* Body: { code: string }
|
||
*/
|
||
export async function POST(req: Request) {
|
||
try {
|
||
const { code } = await req.json()
|
||
|
||
if (!code) {
|
||
return NextResponse.json({ error: 'code 不能为空' }, { status: 400 })
|
||
}
|
||
|
||
const entry = codeStore.get(code)
|
||
if (!entry) {
|
||
return NextResponse.json({ error: 'code 无效或已过期' }, { status: 401 })
|
||
}
|
||
|
||
if (entry.expires < Date.now()) {
|
||
codeStore.delete(code)
|
||
return NextResponse.json({ error: 'code 已过期' }, { status: 401 })
|
||
}
|
||
|
||
// 验证通过,删除已使用的 code(一次性)
|
||
codeStore.delete(code)
|
||
|
||
// 返回用户信息和 token
|
||
const token =
|
||
'mock_token_' +
|
||
Math.random().toString(36).substring(2) +
|
||
'_' +
|
||
Date.now()
|
||
|
||
return NextResponse.json({
|
||
token,
|
||
refresh_token: 'mock_refresh_' + Date.now(),
|
||
user: entry.user,
|
||
permissions: [
|
||
{ object: '/dashboard', action: 'view' },
|
||
{ object: '/settings', action: 'view' },
|
||
],
|
||
})
|
||
} catch (err: any) {
|
||
return NextResponse.json(
|
||
{ error: err?.message || '验证失败' },
|
||
{ status: 500 }
|
||
)
|
||
}
|
||
}
|