change oidc behavior with remember me on by default when oidc only enabled (#2397)

This commit is contained in:
jubnl
2026-09-19 09:12:15 +02:00
committed by GitHub
parent 902dbbf84c
commit ac47066a93
8 changed files with 30 additions and 13 deletions
+4 -1
View File
@@ -166,7 +166,10 @@ export class OidcController {
if ('error' in result) return f('/login?oidc_error=' + result.error);
this.oidc.touchLastLogin(result.user.id);
const jwtToken = this.oidc.generateToken(result.user, pending.remember === true);
// Pass the flag through untouched: `undefined` must reach the token as
// "absent", not `false`, or the sliding renewal would later downgrade the
// default persistent cookie to a browser-session one (remember-me, #1927).
const jwtToken = this.oidc.generateToken(result.user, pending.remember);
const { code: authCode, binding } = this.oidc.createAuthCode(jwtToken, pending.remember);
// Bind the code to THIS browser, the way the state cookie binds the callback.
// The code rides home in a URL, so it is readable from history, from a
+6
View File
@@ -429,6 +429,12 @@ describe('OIDC remember-me (#1927)', () => {
const res = await runFlow('', 'sub-rm-abs', 'rmabs@example.com');
expect(res.status).toBe(200);
expect(sessionCookie(res)).toContain('Max-Age=86400');
// The JWT must not carry `remember: false` either — the sliding renewal
// re-issues the cookie from that claim, and `false` would turn the
// persistent default into a browser-session cookie half a day later.
const jwt = require('jsonwebtoken');
const decoded = jwt.decode(res.body.token) as { remember?: boolean };
expect(decoded.remember).toBeUndefined();
});
});
@@ -358,12 +358,11 @@ describe('OidcController /callback', () => {
expect(res.redirectedTo).toBe('https://app/login?oidc_error=server_error');
});
it('threads the pending remember flag into generateToken and createAuthCode', async () => {
for (const [remember, expectedGenerate] of [
[true, true],
[false, false],
[undefined, false],
] as const) {
it('threads the pending remember flag unchanged into generateToken and createAuthCode', async () => {
// An absent flag must stay absent in the token: coercing it to `false`
// would let the sliding renewal downgrade the default persistent cookie
// to a browser-session cookie half a lifetime later.
for (const remember of [true, false, undefined] as const) {
const generateToken = vi.fn().mockReturnValue('jwt');
const createAuthCode = vi.fn().mockReturnValue({ code: 'ac', binding: 'bnd' });
const res = makeRes();
@@ -376,7 +375,7 @@ describe('OidcController /callback', () => {
generateToken,
createAuthCode,
})).callback('c', 's', undefined, reqCb('s'), res);
expect(generateToken).toHaveBeenCalledWith({ id: 1 }, expectedGenerate);
expect(generateToken).toHaveBeenCalledWith({ id: 1 }, remember);
expect(createAuthCode).toHaveBeenCalledWith('jwt', remember);
}
});