From 86d3c062d6f6d3c97ae7ec14d0b10f86a1bf082d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20P=C3=B6ttker?= Date: Sat, 9 May 2026 10:03:34 +0200 Subject: [PATCH] feat: implement public route support and elevate auth guard log levels to info --- paperless-backend/src/auth/api-key.guard.ts | 4 ++-- paperless-backend/src/auth/auth.module.ts | 2 +- paperless-backend/src/auth/jwt-or-apikey.guard.ts | 13 +++++++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/paperless-backend/src/auth/api-key.guard.ts b/paperless-backend/src/auth/api-key.guard.ts index d9ef63b..9fe9507 100644 --- a/paperless-backend/src/auth/api-key.guard.ts +++ b/paperless-backend/src/auth/api-key.guard.ts @@ -31,7 +31,7 @@ export class ApiKeyGuard implements CanActivate { } } - this.logger.debug( + this.logger.log( `[${method} ${url}] key source: ${apiKey ? source : 'NONE'} | ` + `headers: ${JSON.stringify(Object.keys(request.headers))} | ` + `key prefix: ${apiKey ? String(apiKey).slice(0, 8) + '…' : 'n/a'}`, @@ -44,7 +44,7 @@ export class ApiKeyGuard implements CanActivate { try { const keyEntry = await this.apiKeysService.validateKey(apiKey as string); - this.logger.debug(`[${method} ${url}] accepted – key "${keyEntry.name}" (id=${keyEntry.id})`); + this.logger.log(`[${method} ${url}] accepted – key "${keyEntry.name}" (id=${keyEntry.id})`); request.apiKeyMetadata = { id: keyEntry.id, name: keyEntry.name }; return true; } catch (err) { diff --git a/paperless-backend/src/auth/auth.module.ts b/paperless-backend/src/auth/auth.module.ts index b03e145..5a89319 100644 --- a/paperless-backend/src/auth/auth.module.ts +++ b/paperless-backend/src/auth/auth.module.ts @@ -26,7 +26,7 @@ import { PermissionsGuard } from './permissions.guard'; PermissionsGuard, { provide: APP_GUARD, - useClass: JwtAuthGuard, + useClass: JwtOrApiKeyGuard, }, { provide: APP_GUARD, diff --git a/paperless-backend/src/auth/jwt-or-apikey.guard.ts b/paperless-backend/src/auth/jwt-or-apikey.guard.ts index 657c5c2..ab06c16 100644 --- a/paperless-backend/src/auth/jwt-or-apikey.guard.ts +++ b/paperless-backend/src/auth/jwt-or-apikey.guard.ts @@ -1,6 +1,8 @@ import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common'; +import { Reflector } from '@nestjs/core'; import { JwtAuthGuard } from './jwt-auth.guard'; import { ApiKeyGuard } from './api-key.guard'; +import { IS_PUBLIC_KEY } from './public.decorator'; import { lastValueFrom, isObservable } from 'rxjs'; @Injectable() @@ -10,9 +12,16 @@ export class JwtOrApiKeyGuard implements CanActivate { constructor( private readonly jwtGuard: JwtAuthGuard, private readonly apiKeyGuard: ApiKeyGuard, + private readonly reflector: Reflector, ) {} async canActivate(context: ExecutionContext): Promise { + const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ + context.getHandler(), + context.getClass(), + ]); + if (isPublic) return true; + const req = context.switchToHttp().getRequest(); const tag = `[${req.method} ${req.url}]`; @@ -21,11 +30,11 @@ export class JwtOrApiKeyGuard implements CanActivate { const result = this.jwtGuard.canActivate(context); const jwtOk = isObservable(result) ? await lastValueFrom(result) : await result; if (jwtOk) { - this.logger.debug(`${tag} authenticated via JWT`); + this.logger.log(`${tag} authenticated via JWT`); return true; } } catch (err) { - this.logger.debug(`${tag} JWT failed (${err.message}), trying API key…`); + this.logger.log(`${tag} JWT failed (${err.message}), trying API key…`); } // Fall back to API key