mirror of
https://github.com/CommunitySolidServer/CommunitySolidServer.git
synced 2024-10-03 14:55:10 +00:00
feat: Allow switching accounts
* feat: Allow logging out on the consent page * feat: log in with a different account cleanup Co-authored-by: Joachim Van Herwegen <joachimvh@gmail.com>
This commit is contained in:
parent
9dcba1a288
commit
3fea5c98f5
@ -8,6 +8,7 @@
|
||||
- A new FileSystemResourceLocker has been added. It allows for true threadsafe locking without external dependencies.
|
||||
- The CSS can now run multithreaded with multiple workers, this is done with the `--workers` or `-w` flag.
|
||||
- When starting the server through code, it is now possible to provide CLI value bindings as well in `AppRunner`.
|
||||
- The user can choose to "Log in with a different account" on the consent page
|
||||
|
||||
### Data migration
|
||||
The following actions are required if you are upgrading from a v4 server and want to retain your data.
|
||||
|
@ -56,13 +56,22 @@ export class ConsentHandler extends BaseInteractionHandler {
|
||||
.map((key): [ string, unknown ] => [ key, metadata[key] ]),
|
||||
);
|
||||
jsonLd['@context'] = 'https://www.w3.org/ns/solid/oidc-context.jsonld';
|
||||
const json = { client: jsonLd };
|
||||
const json = { webId: oidcInteraction.session?.accountId, client: jsonLd };
|
||||
|
||||
return new BasicRepresentation(JSON.stringify(json), operation.target, APPLICATION_JSON);
|
||||
}
|
||||
|
||||
protected async handlePost({ operation, oidcInteraction }: InteractionHandlerInput): Promise<never> {
|
||||
const { remember } = await readJsonStream(operation.body.data);
|
||||
const { remember, logOut } = await readJsonStream(operation.body.data);
|
||||
|
||||
if (logOut) {
|
||||
const provider = await this.providerFactory.getProvider();
|
||||
const session = (await provider.Session.find(oidcInteraction!.session!.cookie))!;
|
||||
delete session.accountId;
|
||||
await session.save(session.exp - Math.floor(Date.now() / 1000));
|
||||
|
||||
throw new FoundHttpError(oidcInteraction!.returnTo);
|
||||
}
|
||||
|
||||
const grant = await this.getGrant(oidcInteraction!);
|
||||
this.updateGrant(grant, oidcInteraction!.prompt.details, remember);
|
||||
|
@ -1,4 +1,5 @@
|
||||
<h1>Authorize</h1>
|
||||
<p id="webId">Your WebID: </p>
|
||||
<p>The following client wants to do authorized requests in your name:</p>
|
||||
<ul id="clientInfo">
|
||||
</ul>
|
||||
@ -13,10 +14,33 @@
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
<p class="actions"><button autofocus type="submit" name="submit">Consent</button></p>
|
||||
<p class="actions">
|
||||
<button autofocus type="submit" name="submit">Consent</button>
|
||||
<button onclick="logOut(event)">Log in with a different account</button>
|
||||
</p>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
async function logOut(e) {
|
||||
e.preventDefault();
|
||||
const res = await fetch('', {
|
||||
method: 'POST',
|
||||
headers: { accept: 'application/json', 'content-type': 'application/json' },
|
||||
body: JSON.stringify({ logOut: true }),
|
||||
});
|
||||
const json = await res.json();
|
||||
location.href = json.location;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
function addWebId(webId) {
|
||||
const p = document.getElementById('webId');
|
||||
const strong = document.createElement('strong')
|
||||
strong.appendChild(document.createTextNode(webId));
|
||||
p.appendChild(strong);
|
||||
}
|
||||
|
||||
const clientInfo = document.getElementById('clientInfo');
|
||||
function addClientInfo(text, value) {
|
||||
if (value) {
|
||||
@ -31,8 +55,9 @@
|
||||
|
||||
// Update the client information
|
||||
(async() => {
|
||||
const res = await fetch('', { headers: { accept: 'application/json' } })
|
||||
const { client } = await res.json();
|
||||
const res = await fetch('', { headers: { accept: 'application/json' } });
|
||||
const { webId, client } = await res.json();
|
||||
addWebId(webId);
|
||||
addClientInfo('Name', client.client_name);
|
||||
addClientInfo('ID', client.client_id);
|
||||
})()
|
||||
|
@ -59,7 +59,10 @@ describe('A ConsentHandler', (): void => {
|
||||
|
||||
beforeEach(async(): Promise<void> => {
|
||||
oidcInteraction = {
|
||||
session: { accountId },
|
||||
session: {
|
||||
accountId,
|
||||
save: jest.fn(),
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
params: { client_id: clientId },
|
||||
prompt: { details: {}},
|
||||
@ -76,6 +79,9 @@ describe('A ConsentHandler', (): void => {
|
||||
Client: {
|
||||
find: (id: string): any => (id ? { metadata: jest.fn().mockReturnValue(clientMetadata) } : undefined),
|
||||
},
|
||||
Session: {
|
||||
find: (): Interaction['session'] => oidcInteraction.session,
|
||||
},
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
} as any;
|
||||
|
||||
@ -106,6 +112,7 @@ describe('A ConsentHandler', (): void => {
|
||||
...clientMetadata,
|
||||
'@context': 'https://www.w3.org/ns/solid/oidc-context.jsonld',
|
||||
},
|
||||
webId: accountId,
|
||||
});
|
||||
});
|
||||
|
||||
@ -117,6 +124,7 @@ describe('A ConsentHandler', (): void => {
|
||||
client: {
|
||||
'@context': 'https://www.w3.org/ns/solid/oidc-context.jsonld',
|
||||
},
|
||||
webId: accountId,
|
||||
});
|
||||
});
|
||||
|
||||
@ -170,4 +178,11 @@ describe('A ConsentHandler', (): void => {
|
||||
expect(grantFn.mock.results).toHaveLength(1);
|
||||
expect(grantFn.mock.results[0].value.rejectedScopes).toEqual([ 'offline_access' ]);
|
||||
});
|
||||
|
||||
it('deletes the accountId when logout is provided.', async(): Promise<void> => {
|
||||
const operation = createPostJsonOperation({ logOut: true });
|
||||
await expect(handler.handle({ operation, oidcInteraction })).rejects.toThrow(FoundHttpError);
|
||||
expect((oidcInteraction!.session! as any).save).toHaveBeenCalledTimes(1);
|
||||
expect(oidcInteraction!.session!.accountId).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user