Browse Source

Bugfix/harden authentication with OIDC (#7797)

* Harden authentication with OIDC

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
pull/7878/head
Shreya 2 days ago
committed by GitHub
parent
commit
a0daa3b309
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 20
      apps/api/src/app/auth/oidc-state.store.ts
  3. 10
      apps/api/src/guards/oauth-callback.guard.ts

4
CHANGELOG.md

@ -25,6 +25,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Upgraded `papaparse` from version `5.5.3` to `5.7.0`
- Upgraded `zone.js` from version `0.16.2` to `0.16.3`
### Fixed
- Hardened the authentication with _OpenID Connect_ (`OIDC`) (experimental)
## 3.69.0 - 2026-09-07
### Changed

20
apps/api/src/app/auth/oidc-state.store.ts

@ -1,5 +1,6 @@
import type { Request } from 'express';
import ms from 'ms';
import { randomBytes } from 'node:crypto';
import type {
SessionStore,
SessionStoreCallback,
@ -66,13 +67,20 @@ export class OidcStateStore implements SessionStore {
const data = this.stateMap.get(handle);
if (!data) {
return callback(null, undefined, undefined);
return callback(
new Error('Invalid OIDC state parameter'),
undefined,
undefined
);
}
if (Date.now() - data.timestamp > this.STATE_EXPIRY_MS) {
// State has expired
this.stateMap.delete(handle);
return callback(null, undefined, undefined);
return callback(
new Error('OIDC state has expired, please try again'),
undefined,
undefined
);
}
// Remove state after verification (one-time use)
@ -106,10 +114,6 @@ export class OidcStateStore implements SessionStore {
* Generate a cryptographically secure random handle
*/
private generateHandle() {
return (
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15) +
Date.now().toString(36)
);
return randomBytes(32).toString('hex');
}
}

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

@ -5,11 +5,19 @@ 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) {
public override handleRequest(
error: Error | null,
user: any,
info?: { message?: string }
) {
if (error) {
this.logger.error(
`Authentication with the ${strategy} strategy has failed: ${error.message}`
);
} else if (!user && info?.message) {
this.logger.warn(
`Authentication with the ${strategy} strategy was rejected: ${info.message}`
);
}
// Do not throw, the callback handler redirects to the login page instead

Loading…
Cancel
Save