change: Make credential extractors specialized.

This commit is contained in:
Ruben Verborgh
2020-11-27 00:17:40 +01:00
committed by Joachim Van Herwegen
parent 0407a36490
commit b0c50b8a7b
14 changed files with 164 additions and 68 deletions

View File

@@ -2,6 +2,8 @@ import { verify } from 'ts-dpop';
import type { TargetExtractor } from '../ldp/http/TargetExtractor';
import { getLoggerFor } from '../logging/LogUtil';
import type { HttpRequest } from '../server/HttpRequest';
import { BadRequestHttpError } from '../util/errors/BadRequestHttpError';
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
import type { Credentials } from './Credentials';
import { CredentialsExtractor } from './CredentialsExtractor';
@@ -17,20 +19,27 @@ export class DPoPWebIdExtractor extends CredentialsExtractor {
this.targetExtractor = targetExtractor;
}
public async handle(request: HttpRequest): Promise<Credentials> {
let webID: string | undefined;
const authorizationHeader = request.headers.authorization;
const dpopHeader = request.headers.dpop as string;
if (authorizationHeader && dpopHeader) {
const method = request.method as any;
const resource = await this.targetExtractor.handleSafe(request);
try {
webID = await verify(authorizationHeader, dpopHeader, method, resource.path);
this.logger.info(`Extracted WebID via DPoP token: ${webID}`);
} catch (error: unknown) {
this.logger.warn(`Error verifying WebID via DPoP token: ${(error as Error).message}`);
}
public async canHandle({ headers }: HttpRequest): Promise<void> {
const { authorization } = headers;
if (!authorization || !authorization.startsWith('DPoP ')) {
throw new NotImplementedHttpError('No DPoP Authorization header specified.');
}
}
public async handle(request: HttpRequest): Promise<Credentials> {
const { headers: { authorization, dpop }, method } = request;
if (!dpop) {
throw new BadRequestHttpError('No DPoP token specified.');
}
const resource = await this.targetExtractor.handleSafe(request);
try {
const webID = await verify(authorization as string, dpop as string, method as any, resource.path);
this.logger.info(`Verified WebID via DPoP token: ${webID}`);
return { webID };
} catch (error: unknown) {
const message = `Error verifying WebID via DPoP token: ${(error as Error).message}`;
this.logger.warn(message);
throw new BadRequestHttpError(message);
}
return { webID };
}
}

View File

@@ -0,0 +1,20 @@
import type { HttpRequest } from '../server/HttpRequest';
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
import type { Credentials } from './Credentials';
import { CredentialsExtractor } from './CredentialsExtractor';
/**
* Extracts the empty credentials, indicating an unauthenticated agent.
*/
export class EmptyCredentialsExtractor extends CredentialsExtractor {
public async canHandle({ headers }: HttpRequest): Promise<void> {
const { authorization } = headers;
if (authorization) {
throw new NotImplementedHttpError('Unexpected Authorization scheme.');
}
}
public async handle(): Promise<Credentials> {
return {};
}
}

View File

@@ -1,4 +1,6 @@
import { getLoggerFor } from '../logging/LogUtil';
import type { HttpRequest } from '../server/HttpRequest';
import { NotImplementedHttpError } from '../util/errors/NotImplementedHttpError';
import type { Credentials } from './Credentials';
import { CredentialsExtractor } from './CredentialsExtractor';
@@ -6,7 +8,18 @@ import { CredentialsExtractor } from './CredentialsExtractor';
* Credentials extractor which simply interprets the contents of the Authorization header as a webID.
*/
export class UnsecureWebIdExtractor extends CredentialsExtractor {
public async handle(input: HttpRequest): Promise<Credentials> {
return { webID: input.headers.authorization };
protected readonly logger = getLoggerFor(this);
public async canHandle({ headers }: HttpRequest): Promise<void> {
const { authorization } = headers;
if (!authorization || !authorization.startsWith('WebID ')) {
throw new NotImplementedHttpError('No WebID Authorization header specified.');
}
}
public async handle({ headers }: HttpRequest): Promise<Credentials> {
const webID = /^WebID\s+(.*)/u.exec(headers.authorization as string)![1];
this.logger.info(`Agent unsecurely claims to be ${webID}`);
return { webID };
}
}