feat: Create WWW-Authenticate metadata writer

This commit is contained in:
Joachim Van Herwegen 2021-06-04 11:59:34 +02:00
parent b604dd8331
commit e3c5b39752
8 changed files with 90 additions and 3 deletions

View File

@ -41,6 +41,7 @@ module.exports = {
'@typescript-eslint/no-invalid-void-type': 'off',
// Problems with optional parameters
'@typescript-eslint/no-unnecessary-condition': 'off',
'@typescript-eslint/prefer-optional-chain': 'error',
'@typescript-eslint/space-before-function-paren': [ 'error', 'never' ],
'@typescript-eslint/unbound-method': 'off',
'@typescript-eslint/unified-signatures': 'off',

View File

@ -4,7 +4,8 @@
"files-scs:config/ldp/metadata-writer/writers/constant.json",
"files-scs:config/ldp/metadata-writer/writers/link-rel.json",
"files-scs:config/ldp/metadata-writer/writers/mapped.json",
"files-scs:config/ldp/metadata-writer/writers/wac-allow.json"
"files-scs:config/ldp/metadata-writer/writers/wac-allow.json",
"files-scs:config/ldp/metadata-writer/writers/www-auth.json"
],
"@graph": [
{
@ -15,7 +16,8 @@
{ "@id": "urn:solid-server:default:MetadataWriter_Constant" },
{ "@id": "urn:solid-server:default:MetadataWriter_Mapped" },
{ "@id": "urn:solid-server:default:MetadataWriter_LinkRel" },
{ "@id": "urn:solid-server:default:MetadataWriter_WacAllow" }
{ "@id": "urn:solid-server:default:MetadataWriter_WacAllow" },
{ "@id": "urn:solid-server:default:MetadataWriter_WwwAuth" }
]
}
]

View File

@ -0,0 +1,11 @@
{
"@context": "https://linkedsoftwaredependencies.org/bundles/npm/@solid/community-server/^0.0.0/components/context.jsonld",
"@graph": [
{
"comment": "Adds the WWW-Authenticate header on 401 responses. The current auth value is required for the legacy solid-auth-client.",
"@id": "urn:solid-server:default:MetadataWriter_WwwAuth",
"@type": "WwwAuthMetadataWriter",
"auth": "Bearer scope=\"openid webid\""
}
]
}

View File

@ -97,6 +97,7 @@ export * from './ldp/http/metadata/MetadataParser';
export * from './ldp/http/metadata/MetadataWriter';
export * from './ldp/http/metadata/SlugParser';
export * from './ldp/http/metadata/WacAllowMetadataWriter';
export * from './ldp/http/metadata/WwwAuthMetadataWriter';
// LDP/HTTP/Response
export * from './ldp/http/response/CreatedResponseDescription';

View File

@ -0,0 +1,24 @@
import type { HttpResponse } from '../../../server/HttpResponse';
import { addHeader } from '../../../util/HeaderUtil';
import { HTTP } from '../../../util/Vocabularies';
import type { RepresentationMetadata } from '../../representation/RepresentationMetadata';
import { MetadataWriter } from './MetadataWriter';
/**
* Adds the `WWW-Authenticate` header with the injected value in case the response status code is 401.
*/
export class WwwAuthMetadataWriter extends MetadataWriter {
private readonly auth: string;
public constructor(auth: string) {
super();
this.auth = auth;
}
public async handle(input: { response: HttpResponse; metadata: RepresentationMetadata }): Promise<void> {
const statusLiteral = input.metadata.get(HTTP.terms.statusCodeNumber);
if (statusLiteral?.value === '401') {
addHeader(input.response, 'WWW-Authenticate', this.auth);
}
}
}

View File

@ -188,4 +188,16 @@ describe.each(stores)('An LDP handler with auth using %s', (name, { storeConfig,
// Close response
await response.text();
});
it('returns the legacy WWW-Authenticate header on 401 requests.', async(): Promise<void> => {
await aclHelper.setSimpleAcl(baseUrl, {
permissions: {},
agentClass: 'agent',
accessTo: true,
});
const response = await fetch(`${baseUrl}.acl`);
expect(response.status).toBe(401);
expect(response.headers.get('www-authenticate')).toBe('Bearer scope="openid webid"');
});
});

View File

@ -4,7 +4,7 @@ import { RepresentationMetadata } from '../../../../../src/ldp/representation/Re
import type { HttpResponse } from '../../../../../src/server/HttpResponse';
import { ACL, AUTH } from '../../../../../src/util/Vocabularies';
describe('WacAllowMetadataWriter', (): void => {
describe('A WacAllowMetadataWriter', (): void => {
const writer = new WacAllowMetadataWriter();
let response: HttpResponse;

View File

@ -0,0 +1,36 @@
import { createResponse } from 'node-mocks-http';
import { WwwAuthMetadataWriter } from '../../../../../src/ldp/http/metadata/WwwAuthMetadataWriter';
import { RepresentationMetadata } from '../../../../../src/ldp/representation/RepresentationMetadata';
import type { HttpResponse } from '../../../../../src/server/HttpResponse';
import { HTTP } from '../../../../../src/util/Vocabularies';
describe('A WwwAuthMetadataWriter', (): void => {
const auth = 'Bearer scope="openid webid"';
const writer = new WwwAuthMetadataWriter(auth);
let response: HttpResponse;
beforeEach(async(): Promise<void> => {
response = createResponse();
});
it('adds no header if there is no relevant metadata.', async(): Promise<void> => {
const metadata = new RepresentationMetadata();
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({ });
});
it('adds no header if the status code is not 401.', async(): Promise<void> => {
const metadata = new RepresentationMetadata({ [HTTP.statusCodeNumber]: '403' });
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({ });
});
it('adds a WWW-Authenticate header if the status code is 401.', async(): Promise<void> => {
const metadata = new RepresentationMetadata({ [HTTP.statusCodeNumber]: '401' });
await expect(writer.handle({ response, metadata })).resolves.toBeUndefined();
expect(response.getHeaders()).toEqual({
'www-authenticate': auth,
});
});
});