fix: Allow clients to be remembered in the SessionHttpHandler

This commit is contained in:
Joachim Van Herwegen 2021-08-17 15:55:03 +02:00
parent 1173f98b5d
commit 47b3a2d77f
7 changed files with 28 additions and 13 deletions

View File

@ -1,18 +1,21 @@
import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError';
import { InteractionHandler } from './email-password/handler/InteractionHandler';
import type { InteractionCompleteResult, InteractionHandlerInput } from './email-password/handler/InteractionHandler';
import { getFormDataRequestBody } from './util/FormDataUtil';
/**
* Simple InteractionHttpHandler that sends the session accountId to the InteractionCompleter as webId.
*/
export class SessionHttpHandler extends InteractionHandler {
public async handle({ oidcInteraction }: InteractionHandlerInput): Promise<InteractionCompleteResult> {
public async handle({ request, oidcInteraction }: InteractionHandlerInput): Promise<InteractionCompleteResult> {
if (!oidcInteraction?.session) {
throw new NotImplementedHttpError('Only interactions with a valid session are supported.');
}
const { remember } = await getFormDataRequestBody(request);
return {
type: 'complete',
details: { webId: oidcInteraction.session.accountId },
details: { webId: oidcInteraction.session.accountId, shouldRemember: Boolean(remember) },
};
}
}

View File

@ -1,4 +1,17 @@
<h1>Authorize</h1>
<p>You are authorizing an application to access your Pod.</p>
<form action="/idp/confirm" method="post">
<p class="actions"><button autofocus type="submit" name="submit" class="ids-link-filled">Continue</button></p>
<% if (errorMessage) { %>
<p class="error"><%= errorMessage %></p>
<% } %>
<fieldset>
<ol>
<li class="checkbox">
<label><input type="checkbox" name="remember" value="yes" checked>Stay logged in</label>
</li>
</ol>
</fieldset>
<p class="actions"><button autofocus type="submit" name="submit">Continue</button></p>
</form>

View File

@ -1,6 +1,6 @@
<h1>Forgot password</h1>
<form action="/idp/forgotpassword" method="post">
<%if (errorMessage) { %>
<% if (errorMessage) { %>
<p class="error"><%= errorMessage %></p>
<% } %>

View File

@ -1,6 +1,6 @@
<h1>Log in</h1>
<form action="/idp/login" method="post">
<%if (errorMessage) { %>
<% if (errorMessage) { %>
<p class="error"><%= errorMessage %></p>
<% } %>

View File

@ -1,6 +1,6 @@
<h1>Reset password</h1>
<form method="post">
<%if (errorMessage) { %>
<% if (errorMessage) { %>
<p class="error"><%= errorMessage %></p>
<% } %>

View File

@ -168,11 +168,10 @@ describe('A Solid server with IDP', (): void => {
it('can log in again.', async(): Promise<void> => {
const url = await state.startSession();
// For the following part it is debatable if this is correct but this might be a consequence of the authn client
const form = await state.extractFormUrl(url);
expect(form.url.endsWith('/confirm')).toBe(true);
const res = await state.fetchIdp(form.url, 'POST');
const res = await state.fetchIdp(form.url, 'POST', '', APPLICATION_X_WWW_FORM_URLENCODED);
const nextUrl = res.headers.get('location');
expect(typeof nextUrl).toBe('string');

View File

@ -1,10 +1,9 @@
import type { Interaction } from '../../../../src/identity/interaction/email-password/handler/InteractionHandler';
import { SessionHttpHandler } from '../../../../src/identity/interaction/SessionHttpHandler';
import type { HttpRequest } from '../../../../src/server/HttpRequest';
import { NotImplementedHttpError } from '../../../../src/util/errors/NotImplementedHttpError';
import { createPostFormRequest } from './email-password/handler/Util';
describe('A SessionHttpHandler', (): void => {
const request: HttpRequest = {} as any;
const webId = 'http://test.com/id#me';
let oidcInteraction: Interaction;
let handler: SessionHttpHandler;
@ -17,14 +16,15 @@ describe('A SessionHttpHandler', (): void => {
it('requires a defined oidcInteraction with a session.', async(): Promise<void> => {
oidcInteraction!.session = undefined;
await expect(handler.handle({ request, oidcInteraction })).rejects.toThrow(NotImplementedHttpError);
await expect(handler.handle({ request: {} as any, oidcInteraction })).rejects.toThrow(NotImplementedHttpError);
await expect(handler.handle({ request })).rejects.toThrow(NotImplementedHttpError);
await expect(handler.handle({ request: {} as any })).rejects.toThrow(NotImplementedHttpError);
});
it('returns an InteractionCompleteResult when done.', async(): Promise<void> => {
const request = createPostFormRequest({ remember: true });
await expect(handler.handle({ request, oidcInteraction })).resolves.toEqual({
details: { webId },
details: { webId, shouldRemember: true },
type: 'complete',
});
});