一、设备码签发type DeviceCode = { device_code: string; user_code: string; verification_uri: string; expires_in: number; interval: number; client_id: string; scope: string[]; status: 'pending' | 'approved' | 'denied' } function issueDeviceCode(client_id: string, scope: string[]): DeviceCode { const dc = Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2) const uc = (Math.random().toString(36).slice(2, 6) + Math.random().toString(36).slice(2, 6)).toUpperCase() return { device_code: dc, user_code: uc, verification_uri: 'https://example.com/activate', expires_in: 900, interval: 5, client_id, scope, status: 'pending' } } 二、用户码校验与MFA挑战type Store = { devices: Map<string, DeviceCode>; mfa: Map<string, { types: string[]; ok?: boolean }> } function approveUserCode(store: Store, user_code: string) { for (const v of store.devices.values()) { if (v.user_code === user_code && v.status === 'pending') { store.mfa.set(v.device_code, { types: ['totp','webauthn'] }) v.status = 'approved' return true } } return false } function verifyTotp(secret: string, code: string): boolean { return /^[0-9]{6}$/.test(code) } async function verifyWebAuthn(challenge: string, response: any): Promise<boolean> { return typeof response === 'object' } async function completeMfa(store: Store, device_code: string, totp?: { secret: string; code: string }, webauthn?: { challenge: string; response: any }) { const t = store.mfa.get(device_code) if (!t) return false let ok = true if (t.types.includes('totp')) ok = ok && !!totp && verifyTotp(totp.secret, totp.code) if (t.types.includes('webauthn')) ok = ok && !!webauthn && await verifyWebAuthn(webauthn.challenge, webauthn.response) t.ok = ok return ok } 三、轮询节流与令牌签发type Token = { access_token: string; token_type: 'Bearer'; expires_in: number; scope: string[] } function pollToken(store: Store, device_code: string, lastAt: number, interval: number): Token | 'authorization_pending' | 'slow_down' | 'access_denied' { const now = Date.now() if (now - lastAt < interval * 1000) return 'slow_down' const dev = store.devices.get(device_code) if (!dev) return 'access_denied' if (dev.status === 'pending') return 'authorization_pending' const m = store.mfa.get(device_code) if (!m?.ok) return 'access_denied' return { access_token: Math.random().toString(36).slice(2), token_type: 'Bearer', expires_in: 900, scope: dev.scope } } 四、参数与时序校验`expires_in≤900`与轮询`interval≥5`;用户码长度与字符集约束。MFA挑战至少包含一种有效方式;完成后才能签发令牌。审计记录包含设备码、用户码与挑战类型,便于追踪。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
2.087467s