diff --git a/src/identity/OidcHttpHandler.ts b/src/identity/OidcHttpHandler.ts index 03fb340d6..83bfffdc3 100644 --- a/src/identity/OidcHttpHandler.ts +++ b/src/identity/OidcHttpHandler.ts @@ -18,6 +18,13 @@ export class OidcHttpHandler extends HttpHandler { public async handle({ request, response }: HttpHandlerInput): Promise { const provider = await this.providerFactory.getProvider(); + + // Rewrite requests to allow hosting on root paths + const path = new URL(provider.issuer).pathname; + if (path.length > 1 && request.url!.startsWith(`${path}.well-known/openid-configuration`)) { + request.url = request.url!.replace(path, '/'); + } + this.logger.debug(`Sending request to oidc-provider: ${request.url}`); // Even though the typings do not indicate this, this is a Promise that needs to be awaited. // Otherwise, the `BaseHttpServerFactory` will write a 404 before the OIDC library could handle the response. diff --git a/templates/root/prefilled/index.html b/templates/root/prefilled/index.html index fd8776909..90b43b336 100644 --- a/templates/root/prefilled/index.html +++ b/templates/root/prefilled/index.html @@ -8,7 +8,7 @@
- [Solid logo] + [Solid logo]

Community Solid Server

@@ -22,7 +22,7 @@

Getting started as a user

- Sign up for an account + Sign up for an account to get started with your own Pod and WebID.

diff --git a/test/unit/identity/OidcHttpHandler.test.ts b/test/unit/identity/OidcHttpHandler.test.ts index 7ceba4473..e01a5cc2a 100644 --- a/test/unit/identity/OidcHttpHandler.test.ts +++ b/test/unit/identity/OidcHttpHandler.test.ts @@ -5,7 +5,9 @@ import type { HttpRequest } from '../../../src/server/HttpRequest'; import type { HttpResponse } from '../../../src/server/HttpResponse'; describe('An OidcHttpHandler', (): void => { - const request: HttpRequest = {} as any; + const request: HttpRequest = { + url: '/.well-known/openid-configuration', + } as any; const response: HttpResponse = {} as any; let provider: jest.Mocked; let providerFactory: jest.Mocked; @@ -14,11 +16,12 @@ describe('An OidcHttpHandler', (): void => { beforeEach(async(): Promise => { provider = { callback: jest.fn().mockReturnValue(jest.fn()), + issuer: 'http://localhost:3000/', } as any; providerFactory = { getProvider: jest.fn().mockResolvedValue(provider), - }; + } as any; handler = new OidcHttpHandler(providerFactory); }); @@ -29,4 +32,24 @@ describe('An OidcHttpHandler', (): void => { expect(provider.callback.mock.results[0].value).toHaveBeenCalledTimes(1); expect(provider.callback.mock.results[0].value).toHaveBeenLastCalledWith(request, response); }); + + it('rewrites the request when using base URL with root path.', async(): Promise => { + Object.assign(provider, { issuer: 'http://localhost:3000/path/' }); + request.url = '/path/.well-known/openid-configuration'; + await expect(handler.handle({ request, response })).resolves.toBeUndefined(); + expect(request.url).toBe('/.well-known/openid-configuration'); + expect(provider.callback).toHaveBeenCalledTimes(1); + expect(provider.callback.mock.results[0].value).toHaveBeenCalledTimes(1); + expect(provider.callback.mock.results[0].value).toHaveBeenLastCalledWith(request, response); + }); + + it('respects query parameters when rewriting requests.', async(): Promise => { + Object.assign(provider, { issuer: 'http://localhost:3000/path/' }); + request.url = '/path/.well-known/openid-configuration?param1=value1'; + await expect(handler.handle({ request, response })).resolves.toBeUndefined(); + expect(request.url).toBe('/.well-known/openid-configuration?param1=value1'); + expect(provider.callback).toHaveBeenCalledTimes(1); + expect(provider.callback.mock.results[0].value).toHaveBeenCalledTimes(1); + expect(provider.callback.mock.results[0].value).toHaveBeenLastCalledWith(request, response); + }); });