mail und logging

This commit is contained in:
Bastian Wagner
2026-07-17 11:50:12 +02:00
parent 201c4e03f8
commit edd88acd98
45 changed files with 1413 additions and 42 deletions

View File

@@ -6,7 +6,10 @@ import { Request, Response } from 'express';
import type Provider from 'oidc-provider';
import type { AccountClaims, Adapter, Configuration, Interaction } from 'oidc-provider';
import { Repository } from 'typeorm';
import { ApplicationErrorCategory, ApplicationErrorCode } from '../application-error-log/application-error-codes';
import { ApplicationErrorLoggerService } from '../application-error-log/application-error-logger.service';
import { AuditService } from '../audit/audit.service';
import { RequestContextService } from '../common/request-context.service';
import { LdapAuthService } from '../lldap/ldap-auth.service';
import { LldapService } from '../lldap/lldap.service';
import { OidcProviderStorageEntity } from './entities/oidc-provider-storage.entity';
@@ -35,6 +38,8 @@ export class OidcProviderService implements OnModuleInit {
private readonly ldapAuth: LdapAuthService,
private readonly lldap: LldapService,
private readonly audit: AuditService,
private readonly applicationErrorLogger: ApplicationErrorLoggerService,
private readonly requestContext: RequestContextService,
) {}
async onModuleInit(): Promise<void> {
@@ -45,6 +50,7 @@ export class OidcProviderService implements OnModuleInit {
this.provider = new oidc.default(issuer, this.buildConfiguration(jwks));
this.provider.proxy = this.config.get('OIDC_TRUST_PROXY') === 'true';
this.registerAuditEvents(this.provider);
this.registerErrorEvents(this.provider);
const expressApp = this.httpAdapterHost.httpAdapter.getInstance();
expressApp.use(this.provider.callback());
@@ -279,6 +285,91 @@ export class OidcProviderService implements OnModuleInit {
});
}
private registerErrorEvents(provider: Provider): void {
const eventSource = provider as unknown as {
on(eventName: string, listener: (ctx: unknown, error: unknown) => void): void;
};
const errorEvents = [
'authorization.error',
'server_error',
'grant.error',
'userinfo.error',
'jwks.error',
'discovery.error',
'end_session.error',
'revocation.error',
'introspection.error',
];
for (const eventName of errorEvents) {
eventSource.on(eventName, (ctx, error) => {
void this.logOidcProviderError(eventName, ctx, error);
});
}
}
private async logOidcProviderError(eventName: string, ctx: unknown, error: unknown): Promise<void> {
const oidcContext = ctx as {
method?: string;
path?: string;
status?: number;
query?: Record<string, unknown>;
req?: { headers?: Record<string, string | string[] | undefined> };
oidc?: {
route?: string;
client?: { clientId?: string };
params?: Record<string, unknown>;
body?: Record<string, unknown>;
};
};
const params = oidcContext.oidc?.params ?? oidcContext.query ?? {};
const currentRequestContext = this.requestContext.get();
const correlationHeader = oidcContext.req?.headers?.['x-correlation-id'];
const correlationId =
currentRequestContext.correlationId ??
(Array.isArray(correlationHeader) ? correlationHeader[0] : correlationHeader);
await this.applicationErrorLogger.log({
error,
category: ApplicationErrorCategory.OIDC,
code:
eventName === 'server_error'
? ApplicationErrorCode.OIDC_PROVIDER_ERROR
: ApplicationErrorCode.OIDC_AUTHORIZATION_ERROR,
module: 'OidcModule',
service: OidcProviderService.name,
operation: eventName,
requestContext: {
correlationId,
method: oidcContext.method,
path: oidcContext.path,
statusCode: oidcContext.status,
},
context: {
eventName,
route: oidcContext.oidc?.route,
clientId: oidcContext.oidc?.client?.clientId ?? params.client_id,
redirectUri: params.redirect_uri,
responseType: params.response_type,
responseMode: params.response_mode,
scope: params.scope,
prompt: params.prompt,
error: this.errorProperty(error, 'error'),
errorDescription: this.errorProperty(error, 'error_description'),
errorDetail: this.errorProperty(error, 'error_detail'),
},
handled: true,
});
}
private errorProperty(error: unknown, property: string): unknown {
if (!error || typeof error !== 'object' || !(property in error)) {
return undefined;
}
return (error as Record<string, unknown>)[property];
}
private getProvider(): Provider {
if (!this.provider) {
throw new InternalServerErrorException('OIDC provider is not initialized');