lorenzozane 2 days ago
committed by GitHub
parent
commit
c0a2cc7035
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 100
      apps/api/src/guards/oauth-callback.guard.spec.ts
  2. 23
      apps/api/src/guards/oauth-callback.guard.ts

100
apps/api/src/guards/oauth-callback.guard.spec.ts

@ -0,0 +1,100 @@
import { Logger } from '@nestjs/common';
import { OAuthCallbackGuard } from './oauth-callback.guard';
describe('OAuthCallbackGuard', () => {
let warnSpy: jest.SpyInstance;
let errorSpy: jest.SpyInstance;
beforeEach(() => {
warnSpy = jest.spyOn(Logger.prototype, 'warn').mockImplementation(() => undefined as any);
errorSpy = jest.spyOn(Logger.prototype, 'error').mockImplementation(() => undefined as any);
});
afterEach(() => {
jest.restoreAllMocks();
});
function getGuardInstance(strategy = 'oidc') {
const Guard = OAuthCallbackGuard(strategy);
return new (Guard as any)();
}
it('should return user when authentication succeeds', () => {
const guard = getGuardInstance('oidc');
const user = { jwt: 'token' };
const result = guard.handleRequest(null, user, null, null, null);
expect(result).toBe(user);
expect(errorSpy).not.toHaveBeenCalled();
expect(warnSpy).not.toHaveBeenCalled();
});
it('should log error when err is provided', () => {
const guard = getGuardInstance('oidc');
const err = new Error('token exchange failed');
const result = guard.handleRequest(err, false, null, null, null);
expect(result).toBe(false);
expect(errorSpy).toHaveBeenCalledWith(
expect.stringContaining('Authentication with the oidc strategy has failed')
);
});
it('should log warn when user is falsy and info is provided (silent failure case)', () => {
const guard = getGuardInstance('oidc');
const info = new Error('Invalid state');
const result = guard.handleRequest(null, undefined, info, null, null);
expect(result).toBeUndefined();
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('Authentication with the oidc strategy has failed')
);
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('Invalid state'));
});
it('should log warn when user is falsy without info (OidcStateStore verify failure)', () => {
const guard = getGuardInstance('oidc');
const result = guard.handleRequest(null, null, null, null, null);
expect(result).toBeNull();
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('Authentication with the oidc strategy has failed')
);
});
it('should log both error and warn when err and !user with info', () => {
const guard = getGuardInstance('oidc');
const err = new Error('exchange error');
const info = 'State mismatch';
const result = guard.handleRequest(err, undefined, info, null, null);
expect(result).toBeUndefined();
expect(errorSpy).toHaveBeenCalled();
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('State mismatch'));
});
it('should log warn with stringified info when info is object', () => {
const guard = getGuardInstance('oidc');
const info = { message: 'invalid_token' };
guard.handleRequest(null, undefined, info, null, null);
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('invalid_token')
);
});
it('should keep generic strategy name in log', () => {
const guard = getGuardInstance('google');
guard.handleRequest(null, undefined, 'some info', null, null);
expect(warnSpy).toHaveBeenCalledWith(
expect.stringContaining('google')
);
});
});

23
apps/api/src/guards/oauth-callback.guard.ts

@ -5,10 +5,27 @@ export function OAuthCallbackGuard(strategy: string): Type<IAuthGuard> {
class OAuthCallbackGuardMixin extends AuthGuard(strategy) {
private readonly logger = new Logger(OAuthCallbackGuard.name);
public override handleRequest(error: Error, user: any) {
if (error) {
public override handleRequest(
err: unknown,
user: any,
info: unknown,
context: unknown,
status?: unknown
) {
if (err) {
this.logger.error(
`Authentication with the ${strategy} strategy has failed: ${error.message}`
`Authentication with the ${strategy} strategy has failed: ${(err as Error)?.message ?? err}`
);
}
if (!user) {
const infoMessage =
info !== undefined && info !== null
? `: ${info instanceof Error ? info.message : typeof info === 'string' ? info : JSON.stringify(info)}`
: ': no user returned';
this.logger.warn(
`Authentication with the ${strategy} strategy has failed${infoMessage}`
);
}

Loading…
Cancel
Save