UNPKG

4.89 kBPlain TextView Raw
1/*
2 * Copyright 2020 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 { injectable, inject } from "tsyringe";
28import {
29 ILoginInputOptions,
30 ILoginHandler,
31 ILogoutHandler,
32 IRedirectHandler,
33 ISessionInfo,
34 ISessionInfoManager,
35} from "@inrupt/solid-client-authn-core";
36import { removeOidcQueryParam } from "@inrupt/oidc-client-ext";
37
38/**
39 * @hidden
40 */
41@injectable()
42export default class ClientAuthentication {
43 constructor(
44 @inject("loginHandler") private loginHandler: ILoginHandler,
45 @inject("redirectHandler") private redirectHandler: IRedirectHandler,
46 @inject("logoutHandler") private logoutHandler: ILogoutHandler,
47 @inject("sessionInfoManager")
48 private sessionInfoManager: ISessionInfoManager
49 ) {}
50
51 // Define these functions as properties so that they don't get accidentally re-bound.
52 // Isn't Javascript fun?
53 login = async (
54 sessionId: string,
55 options: ILoginInputOptions
56 ): Promise<void> => {
57 // In order to get a clean start, make sure that the session is logged out
58 // on login.
59 // But we may want to preserve our client application info, particularly if
60 // we used Dynamic Client Registration to register (since we don't
61 // necessarily want the user to have to register this app each time they
62 // login).
63 await this.sessionInfoManager.clear(sessionId);
64
65 // In the case of the user hitting the 'back' button in their browser, they
66 // could return to a previous redirect URL that contains OIDC params that
67 // are now longer valid - so just to be safe, strip relevant params now.
68 const redirectUrl = removeOidcQueryParam(
69 options.redirectUrl ?? window.location.href
70 );
71
72 await this.loginHandler.handle({
73 sessionId,
74 oidcIssuer: options.oidcIssuer,
75 redirectUrl,
76 clientId: options.clientId,
77 clientSecret: options.clientSecret,
78 clientName: options.clientName ?? options.clientId,
79 popUp: options.popUp || false,
80 handleRedirect: options.handleRedirect,
81 // Defaults to DPoP
82 tokenType: options.tokenType ?? "DPoP",
83 });
84 };
85
86 // By default, our fetch() resolves to the environment fetch() function.
87 fetch = window.fetch;
88
89 logout = async (sessionId: string): Promise<void> => {
90 await this.logoutHandler.handle(sessionId);
91
92 // Restore our fetch() function back to the environment fetch(), effectively
93 // leaving us with un-authenticated fetches from now on.
94 this.fetch = window.fetch;
95 };
96
97 getSessionInfo = async (
98 sessionId: string
99 ): Promise<ISessionInfo | undefined> => {
100 // TODO complete
101 return this.sessionInfoManager.get(sessionId);
102 };
103
104 getAllSessionInfo = async (): Promise<ISessionInfo[]> => {
105 return this.sessionInfoManager.getAll();
106 };
107
108 handleIncomingRedirect = async (
109 url: string
110 ): Promise<ISessionInfo | undefined> => {
111 const redirectInfo = await this.redirectHandler.handle(url);
112
113 this.fetch = redirectInfo.fetch;
114
115 const cleanedUpUrl = new URL(url);
116 cleanedUpUrl.searchParams.delete("state");
117 // For auth code flow
118 cleanedUpUrl.searchParams.delete("code");
119 // For implicit flow
120 cleanedUpUrl.searchParams.delete("id_token");
121 cleanedUpUrl.searchParams.delete("access_token");
122
123 // Remove OAuth-specific query params (since the login flow finishes with the
124 // browser being redirected back with OAuth2 query params (e.g. for 'code'
125 // and 'state'), and so if the user simply refreshes this page our
126 // authentication library will be called again with what are now invalid
127 // query parameters!).
128 window.history.replaceState(null, "", cleanedUpUrl.toString());
129
130 return {
131 isLoggedIn: redirectInfo.isLoggedIn,
132 webId: redirectInfo.webId,
133 sessionId: redirectInfo.sessionId,
134 };
135 };
136}