Files
paperlessmanager/paperless-backend/src/auth/api-key.guard.ts
T
bjoernpoettker dad0136365
Build and Push Multi-Platform Images / build-and-push (push) Successful in 41s
chore: apply ESLint auto-fix across entire backend
Reformats code style (line breaks, indentation, type annotations)
without changing logic. Also includes minor feature additions bundled
in the same lint run (stats service, user-settings groups, agrarmonitor
polling improvements).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-08 09:02:02 +02:00

66 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import {
CanActivate,
ExecutionContext,
Injectable,
Logger,
UnauthorizedException,
} from '@nestjs/common';
import { ApiKeysService } from './api-keys.service';
@Injectable()
export class ApiKeyGuard implements CanActivate {
private readonly logger = new Logger(ApiKeyGuard.name);
constructor(private readonly apiKeysService: ApiKeysService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const method: string = request.method;
const url: string = request.url;
// Check header (X-API-Key)
let apiKey = request.headers['x-api-key'] || request.headers['X-API-Key'];
let source = 'X-API-Key header';
// Fallback to query parameter (apiKey)
if (!apiKey) {
apiKey = request.query['apiKey'];
if (apiKey) source = 'apiKey query param';
}
// Fallback to Authorization: Bearer (used by SSE clients that can't set X-API-Key)
if (!apiKey) {
const auth: string | undefined = request.headers['authorization'];
if (auth?.startsWith('Bearer ')) {
apiKey = auth.slice(7);
source = 'Authorization: Bearer';
}
}
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'}`,
);
if (!apiKey) {
this.logger.warn(`[${method} ${url}] rejected no API key found`);
throw new UnauthorizedException('API Key missing');
}
try {
const keyEntry = await this.apiKeysService.validateKey(apiKey as string);
this.logger.log(
`[${method} ${url}] accepted key "${keyEntry.name}" (id=${keyEntry.id})`,
);
request.apiKeyMetadata = { id: keyEntry.id, name: keyEntry.name };
return true;
} catch (err) {
this.logger.warn(
`[${method} ${url}] rejected validation failed: ${err.message}`,
);
throw new UnauthorizedException(err.message || 'Invalid API Key');
}
}
}