fix(api): tighter public lot endpoint, SSO callback from config, mapped 4xx errors

- Public lot lookup: 30 requests/min per IP and only well-formed lot
  numbers (1-64 chars) reach the database.
- SSO callback URL is built from OIDC_REDIRECT_URI instead of the Host
  header; SSO cookies are cleared with the attributes they were set with.
- Logout is rate-limited like the other auth endpoints.
- Middleware errors with a 4xx status (body too large, malformed JSON)
  answer with that status instead of a 500; error log lines carry the
  path without query string.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Opus 5.5 committed 2026-10-01 07:20:33 +02:00
1 parent eafe925d60
commit 0899576262
4 files changed
+49 -9

No files matched your search

@@ -82,6 +82,7 @@ export class AuthController {
}
@Public()
@Throttle(SENSITIVE_ACTION_THROTTLE)
@Post('logout')
@HttpCode(HttpStatus.NO_CONTENT)
async logout(
@@ -82,7 +82,7 @@ export class SsoController {
const rawCookie = (req.cookies as Record<string, string> | undefined)?.[
PKCE_COOKIE
];
res.clearCookie(PKCE_COOKIE, { path: PKCE_COOKIE_PATH });
res.clearCookie(PKCE_COOKIE, this.cookieOptions(PKCE_COOKIE_PATH, 0));
const pkce = this.parsePkceCookie(rawCookie);
if (!pkce) {
@@ -90,10 +90,10 @@ export class SsoController {
return;
}
const callbackUrl = new URL(
req.originalUrl,
`${req.protocol}://${req.get('host')}`,
);
// Built from the configured redirect URI, not from the Host header a
// client sends; only the query (code, state, iss) comes from the request.
const callbackUrl = new URL(process.env.OIDC_REDIRECT_URI as string);
callbackUrl.search = new URL(req.originalUrl, 'http://placeholder').search;
const result = await this.ssoService.handleCallback(
callbackUrl,
pkce.codeVerifier,
@@ -126,7 +126,10 @@ export class SsoController {
const ssoCode = (req.cookies as Record<string, string> | undefined)?.[
SSO_CODE_COOKIE
];
res.clearCookie(SSO_CODE_COOKIE, { path: SSO_CODE_COOKIE_PATH });
res.clearCookie(
SSO_CODE_COOKIE,
this.cookieOptions(SSO_CODE_COOKIE_PATH, 0),
);
if (!ssoCode) {
throw new UnauthorizedException(
'SSO-Anmeldung abgelaufen, bitte erneut versuchen',