UNPKG

3.76 kBPlain TextView Raw
1/*
2 * Copyright 2021 Inrupt Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal in
6 * the Software without restriction, including without limitation the rights to use,
7 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8 * Software, and to permit persons to whom the Software is furnished to do so,
9 * subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22/**
23 * @hidden
24 * @packageDocumentation
25 */
26
27import { inject, injectable } from "tsyringe";
28import {
29 IStorageUtility,
30 IClientRegistrar,
31 IIssuerConfig,
32 IClient,
33 IClientRegistrarOptions,
34} from "@inrupt/solid-client-authn-core";
35import { registerClient } from "@inrupt/oidc-client-ext";
36
37/**
38 * @hidden
39 */
40@injectable()
41export default class ClientRegistrar implements IClientRegistrar {
42 constructor(
43 @inject("storageUtility") private storageUtility: IStorageUtility
44 ) {}
45
46 async getClient(
47 options: IClientRegistrarOptions,
48 issuerConfig: IIssuerConfig
49 ): Promise<IClient> {
50 // If client secret and/or client id are stored in storage, use those.
51 const [
52 storedClientId,
53 storedClientSecret,
54 // storedClientName,
55 ] = await Promise.all([
56 this.storageUtility.getForUser(options.sessionId, "clientId", {
57 // FIXME: figure out how to persist secure storage at reload
58 secure: false,
59 }),
60 this.storageUtility.getForUser(options.sessionId, "clientSecret", {
61 // FIXME: figure out how to persist secure storage at reload
62 secure: false,
63 }),
64 // this.storageUtility.getForUser(options.sessionId, "clientName", {
65 // // FIXME: figure out how to persist secure storage at reload
66 // secure: false,
67 // }),
68 ]);
69 if (storedClientId) {
70 return {
71 clientId: storedClientId,
72 clientSecret: storedClientSecret,
73 };
74 }
75 const extendedOptions = { ...options };
76 // If registration access token is stored, use that.
77 extendedOptions.registrationAccessToken =
78 extendedOptions.registrationAccessToken ??
79 (await this.storageUtility.getForUser(
80 options.sessionId,
81 "registrationAccessToken"
82 ));
83
84 try {
85 const registeredClient = await registerClient(
86 extendedOptions,
87 issuerConfig
88 );
89 // Save info
90 const infoToSave: Record<string, string> = {
91 clientId: registeredClient.clientId,
92 };
93 if (registeredClient.clientSecret) {
94 infoToSave.clientSecret = registeredClient.clientSecret;
95 }
96 await this.storageUtility.setForUser(
97 extendedOptions.sessionId,
98 infoToSave,
99 {
100 // FIXME: figure out how to persist secure storage at reload
101 // Otherwise, the client info cannot be retrieved from storage, and
102 // the lib tries to re-register the client on each fetch
103 secure: false,
104 }
105 );
106 return registeredClient;
107 } catch (error) {
108 throw new Error(`Client registration failed: [${error.toString()}]`);
109 }
110 }
111}