fix(server): only set OAuth cookies for server-generated state (#32600)

(cherry picked from commit d468c468867edcbafd4d934d3ba97bee2414050f)
This commit is contained in:
bo0tzz
2026-10-22 05:23:22 +03:00
committed by Codex
parent b12be9119f
commit 1756d70fda
3 changed files with 30 additions and 1 deletions
@@ -30,6 +30,32 @@ describe(OAuthController.name, () => {
);
expect(service.authorize).not.toHaveBeenCalled();
});
it('should set the state and code verifier cookies when the server generates them', async () => {
service.authorize.mockResolvedValue({ url: 'http://idp/auth', state: 'server-state', codeVerifier: 'verifier' });
const { status, headers } = await request(ctx.getHttpServer())
.post('/oauth/authorize')
.send({ redirectUri: 'http://immich/auth/login' });
expect(status).toBe(201);
const cookies = (headers['set-cookie'] as unknown as string[]) ?? [];
expect(cookies).toEqual([
expect.stringContaining('immich_oauth_state=server-state'),
expect.stringContaining('immich_oauth_code_verifier=verifier'),
]);
});
it('should not set cookies for client supplied state and code challenge', async () => {
service.authorize.mockResolvedValue({ url: 'http://idp/auth', state: 'client-state', codeVerifier: null });
const { status, headers } = await request(ctx.getHttpServer())
.post('/oauth/authorize')
.send({ redirectUri: 'http://immich/auth/login', state: 'client-state', codeChallenge: 'challenge' });
expect(status).toBe(201);
expect(headers['set-cookie']).toBeUndefined();
});
});
describe('POST /oauth/callback', () => {
+1 -1
View File
@@ -56,7 +56,7 @@ export class OAuthController {
{
isSecure: loginDetails.isSecure,
values: [
{ key: ImmichCookie.OAuthState, value: state },
{ key: ImmichCookie.OAuthState, value: dto.state ? null : state },
{ key: ImmichCookie.OAuthCodeVerifier, value: codeVerifier },
],
},
+3
View File
@@ -60,6 +60,9 @@ export const respondWithCookie = <T>(res: Response, body: T, { isSecure, values
};
for (const { key, value } of values) {
if (value === null) {
continue;
}
const options = cookieOptions[key];
res.cookie(key, value, options);
}