mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-02 08:15:55 +00:00
fix: refuse a pairing re-auth the identity provider did not make fresh
The step-up for SSO accounts asks the provider for a new login with `prompt=login`, but a provider that ignores it answers from its existing session, so anyone at an unlocked desktop could link a phone. When the ID token's `auth_time` is older than the step-up, the re-auth is now refused.
This commit is contained in:
@@ -314,3 +314,27 @@ describe('reauth/sso/complete', () => {
|
||||
expect(redeemPairingCode(firstCode.code)).toEqual({ ok: false, reason: 'expired' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('reauth/sso/complete freshness', () => {
|
||||
const idToken = (claims: Record<string, unknown>) =>
|
||||
`h.${Buffer.from(JSON.stringify(claims)).toString('base64url')}.s`;
|
||||
|
||||
it('refuses a login the provider did not make fresh (old auth_time)', async () => {
|
||||
signIn(0);
|
||||
pending({ created_at: Date.now() });
|
||||
exchangeCodeForTokens.mockResolvedValue({ ...FRESH, id_token: idToken({ auth_time: Math.floor(Date.now() / 1000) - 3600 }) });
|
||||
const res = await complete();
|
||||
expect(res).toEqual({ status: 401, body: { error: 'reauth_not_fresh' } });
|
||||
expect(readPairReauthFromStore(cookieStore as never)).toBeNull();
|
||||
});
|
||||
|
||||
it('accepts a fresh auth_time, and an ID token without one', async () => {
|
||||
signIn(0);
|
||||
pending({ created_at: Date.now() });
|
||||
exchangeCodeForTokens.mockResolvedValue({ ...FRESH, id_token: idToken({ auth_time: Math.floor(Date.now() / 1000) }) });
|
||||
expect((await complete()).status).toBe(200);
|
||||
pending({ created_at: Date.now() });
|
||||
exchangeCodeForTokens.mockResolvedValue({ ...FRESH, id_token: idToken({ sub: 'x' }) });
|
||||
expect((await complete()).status).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user