This repository has been archived by the owner on Jul 26, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 232
/
Auth.js
149 lines (133 loc) · 5 KB
/
Auth.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
* Copyright (c) 2017-Present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*/
import {
assertIssuer,
assertClientId,
assertRedirectUri,
buildConfigObject
} from '@okta/configuration-validation';
import OktaAuth from '@okta/okta-auth-js';
import packageInfo from './packageInfo';
const containsAuthTokens = /id_token|access_token|code/;
export default class Auth {
constructor(config) {
const testing = {
// If the config is undefined, cast it to false
disableHttpsCheck: !!config.disableHttpsCheck
};
// normalize authJS config. In this SDK, we allow underscore on certain properties, but AuthJS consistently uses camel case.
const authConfig = buildConfigObject(config);
assertIssuer(authConfig.issuer, testing);
assertClientId(authConfig.clientId);
assertRedirectUri(authConfig.redirectUri);
this._oktaAuth = new OktaAuth(authConfig);
this._oktaAuth.userAgent = `${packageInfo.name}/${packageInfo.version} ${this._oktaAuth.userAgent}`;
this._config = config;
this._history = config.history;
this.handleAuthentication = this.handleAuthentication.bind(this);
this.isAuthenticated = this.isAuthenticated.bind(this);
this.getUser = this.getUser.bind(this);
this.getIdToken = this.getIdToken.bind(this);
this.getAccessToken = this.getAccessToken.bind(this);
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
this.redirect = this.redirect.bind(this);
}
async handleAuthentication() {
let tokens = await this._oktaAuth.token.parseFromUrl();
tokens = Array.isArray(tokens) ? tokens : [tokens];
for (let token of tokens) {
if (token.idToken) {
this._oktaAuth.tokenManager.add('idToken', token);
} else if (token.accessToken) {
this._oktaAuth.tokenManager.add('accessToken', token);
}
}
}
async isAuthenticated() {
// If there could be tokens in the url
if (location && location.hash && containsAuthTokens.test(location.hash)) return null;
return !!(await this.getAccessToken()) || !!(await this.getIdToken());
}
async getUser() {
const accessToken = await this._oktaAuth.tokenManager.get('accessToken');
const idToken = await this._oktaAuth.tokenManager.get('idToken');
if (accessToken && idToken) {
const userinfo = await this._oktaAuth.token.getUserInfo(accessToken);
if (userinfo.sub === idToken.claims.sub) {
// Only return the userinfo response if subjects match to
// mitigate token substitution attacks
return userinfo
}
}
return idToken ? idToken.claims : undefined;
}
async getIdToken() {
try {
const idToken = await this._oktaAuth.tokenManager.get('idToken');
return idToken.idToken;
} catch (err) {
// The user no longer has an existing SSO session in the browser.
// (OIDC error `login_required`)
// Ask the user to authenticate again.
return undefined;
}
}
async getAccessToken() {
try {
const accessToken = await this._oktaAuth.tokenManager.get('accessToken');
return accessToken.accessToken;
} catch (err) {
// The user no longer has an existing SSO session in the browser.
// (OIDC error `login_required`)
// Ask the user to authenticate again.
return undefined;
}
}
async login(fromUri, additionalParams) {
const referrerPath = fromUri
? { pathname: fromUri }
: this._history.location;
localStorage.setItem(
'secureRouterReferrerPath',
JSON.stringify(referrerPath)
);
if (this._config.onAuthRequired) {
const auth = this;
const history = this._history;
return this._config.onAuthRequired({ auth, history });
}
await this.redirect(additionalParams);
}
async logout(path) {
this._oktaAuth.tokenManager.clear();
await this._oktaAuth.signOut();
this._history.push(path || '/');
}
async redirect(additionalParams = {}) {
const responseType = additionalParams.response_type
|| this._config.response_type
|| ['id_token', 'token'];
const scopes = additionalParams.scope
|| this._config.scope
|| ['openid', 'email', 'profile'];
this._oktaAuth.token.getWithRedirect({
responseType: responseType,
scopes: scopes,
...additionalParams
});
// return a promise that doesn't terminate so nothing
// happens after setting window.location
/* eslint-disable-next-line no-unused-vars */
return new Promise((resolve, reject) => {});
}
}