zavadil-ts-common 1.2.38 → 1.2.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +15 -29
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/oauth/OAuthTokenManager.d.ts +8 -4
- package/dist/oauth/RestClientWithOAuth.d.ts +5 -25
- package/dist/oauth/tokenprovider/IdTokenProviderDefault.d.ts +13 -0
- package/dist/oauth/tokenprovider/IdTokenProviderLogin.d.ts +14 -0
- package/dist/oauth/tokenprovider/IdTokenProviderStorage.d.ts +9 -0
- package/dist/oauth/tokenprovider/IdTokenProviderUrl.d.ts +10 -0
- package/dist/oauth/tokenprovider/OAuthIdTokenProvider.d.ts +4 -0
- package/dist/oauth/tokenprovider/RedirectionProvider.d.ts +6 -0
- package/dist/util/UrlUtil.d.ts +5 -0
- package/package.json +1 -1
- package/src/oauth/OAuthTokenManager.ts +38 -23
- package/src/oauth/RestClientWithOAuth.ts +13 -117
- package/src/oauth/tokenprovider/IdTokenProviderDefault.ts +44 -0
- package/src/oauth/tokenprovider/IdTokenProviderLogin.ts +39 -0
- package/src/oauth/tokenprovider/IdTokenProviderStorage.ts +32 -0
- package/src/oauth/tokenprovider/IdTokenProviderUrl.ts +30 -0
- package/src/oauth/tokenprovider/OAuthIdTokenProvider.ts +5 -0
- package/src/oauth/tokenprovider/RedirectionProvider.ts +21 -0
- package/src/util/UrlUtil.ts +19 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
import { OAuthTokenManager } from "./OAuthTokenManager";
|
2
2
|
import { RestClient } from "../client";
|
3
3
|
import { IdTokenPayload } from "./OAuthRestClient";
|
4
|
+
import { OAuthIdTokenProvider } from "./tokenprovider/OAuthIdTokenProvider";
|
4
5
|
export type ServerOAuthInfoPayload = {
|
5
6
|
debugMode?: boolean;
|
6
7
|
targetAudience: string;
|
@@ -8,23 +9,14 @@ export type ServerOAuthInfoPayload = {
|
|
8
9
|
version: string;
|
9
10
|
};
|
10
11
|
export declare class RestClientWithOAuth extends RestClient {
|
11
|
-
private tokenName;
|
12
12
|
private insecureClient;
|
13
|
+
private freshIdTokenProvider;
|
13
14
|
private tokenManager;
|
14
15
|
private serverInfo;
|
15
16
|
private defaultPrivilege;
|
16
|
-
|
17
|
-
constructor(url: string, defaultPrivilege?: string);
|
18
|
-
isRedirecting(): boolean;
|
19
|
-
redirectingTo(): string;
|
20
|
-
redirectTo(url: string): Promise<any>;
|
21
|
-
initializeIdToken(): Promise<any>;
|
17
|
+
constructor(url: string, freshIdTokenProvider?: OAuthIdTokenProvider, defaultPrivilege?: string);
|
22
18
|
/**
|
23
|
-
* Attempt to get ID token from
|
24
|
-
*/
|
25
|
-
redirectToLogin(): Promise<any>;
|
26
|
-
/**
|
27
|
-
* Attempt to get ID token from URL or storage, redirect to login page when not successful
|
19
|
+
* Attempt to get ID token from the provider, this will trigger redirect to login screen in case of the default provider
|
28
20
|
*/
|
29
21
|
initialize(): Promise<any>;
|
30
22
|
logout(): Promise<any>;
|
@@ -33,23 +25,11 @@ export declare class RestClientWithOAuth extends RestClient {
|
|
33
25
|
* @param url
|
34
26
|
*/
|
35
27
|
getPrivilege(url: string): string;
|
36
|
-
deleteIdTokenFromUrl(): string;
|
37
|
-
getIdTokenFromUrl(): string | null;
|
38
|
-
getIdTokenFromLocalStorage(): IdTokenPayload | null | undefined;
|
39
|
-
saveIdTokenToLocalStorage(token: IdTokenPayload | null): void;
|
40
|
-
addIdTokenChangedHandler(handler: () => any): void;
|
41
|
-
removeIdTokenChangedHandler(handler: () => any): void;
|
42
28
|
private getServerInfoInternal;
|
43
29
|
getServerInfo(): Promise<ServerOAuthInfoPayload>;
|
44
|
-
|
30
|
+
protected getTokenManagerInternal(): Promise<OAuthTokenManager>;
|
45
31
|
getTokenManager(): Promise<OAuthTokenManager>;
|
46
32
|
login(login: string, password: string): Promise<any>;
|
47
33
|
setIdToken(token: IdTokenPayload): Promise<any>;
|
48
|
-
setIdTokenRaw(token: string): Promise<any>;
|
49
34
|
getHeaders(endpoint: string): Promise<Headers>;
|
50
|
-
/**
|
51
|
-
* Try to obtain access token, then return if everything is okay.
|
52
|
-
* This is basically only used when initializing and trying to determine whether we need to redirect user to login page
|
53
|
-
*/
|
54
|
-
checkAccessToken(privilege?: string): Promise<any>;
|
55
35
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { OAuthIdTokenProvider } from "./OAuthIdTokenProvider";
|
2
|
+
import { IdTokenPayload } from "../OAuthRestClient";
|
3
|
+
import { IdTokenProviderLogin } from "./IdTokenProviderLogin";
|
4
|
+
import { RestClientWithOAuth } from "../RestClientWithOAuth";
|
5
|
+
import { IdTokenProviderUrl } from "./IdTokenProviderUrl";
|
6
|
+
import { IdTokenProviderStorage } from "./IdTokenProviderStorage";
|
7
|
+
export declare class IdTokenProviderDefault implements OAuthIdTokenProvider {
|
8
|
+
login: IdTokenProviderLogin;
|
9
|
+
url: IdTokenProviderUrl;
|
10
|
+
storage: IdTokenProviderStorage;
|
11
|
+
constructor(client: RestClientWithOAuth, tokenStorageKey?: string, tokenUrlName?: string);
|
12
|
+
getIdToken(): Promise<IdTokenPayload>;
|
13
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { OAuthIdTokenProvider } from "./OAuthIdTokenProvider";
|
2
|
+
import { IdTokenPayload } from "../OAuthRestClient";
|
3
|
+
import { RedirectionProvider } from "./RedirectionProvider";
|
4
|
+
import { RestClientWithOAuth } from "../RestClientWithOAuth";
|
5
|
+
export declare class IdTokenProviderLogin extends RedirectionProvider implements OAuthIdTokenProvider {
|
6
|
+
client: RestClientWithOAuth;
|
7
|
+
tokenQueryName: string;
|
8
|
+
constructor(client: RestClientWithOAuth, tokenQueryName?: string);
|
9
|
+
/**
|
10
|
+
* Attempt to get ID token from URL or storage, redirect to login page when not successful
|
11
|
+
*/
|
12
|
+
redirectToLogin(): Promise<any>;
|
13
|
+
getIdToken(): Promise<IdTokenPayload>;
|
14
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
import { OAuthIdTokenProvider } from "./OAuthIdTokenProvider";
|
2
|
+
import { IdTokenPayload } from "../OAuthRestClient";
|
3
|
+
export declare class IdTokenProviderStorage implements OAuthIdTokenProvider {
|
4
|
+
key: string;
|
5
|
+
constructor(storageKey?: string);
|
6
|
+
saveIdTokenToLocalStorage(token: IdTokenPayload | null): void;
|
7
|
+
getIdTokenFromLocalStorage(): IdTokenPayload | null | undefined;
|
8
|
+
getIdToken(): Promise<IdTokenPayload>;
|
9
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { OAuthIdTokenProvider } from "./OAuthIdTokenProvider";
|
2
|
+
import { IdTokenPayload } from "../OAuthRestClient";
|
3
|
+
import { RestClientWithOAuth } from "../RestClientWithOAuth";
|
4
|
+
export declare class IdTokenProviderUrl implements OAuthIdTokenProvider {
|
5
|
+
client: RestClientWithOAuth;
|
6
|
+
tokenQueryName: string;
|
7
|
+
constructor(client: RestClientWithOAuth, tokenQueryName?: string);
|
8
|
+
getIdTokenFromUrl(): string | null;
|
9
|
+
getIdToken(): Promise<IdTokenPayload>;
|
10
|
+
}
|
package/package.json
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
import {AccessTokenPayload, IdTokenPayload, OAuthRestClient} from "./OAuthRestClient";
|
2
2
|
import {EventManager} from "../component";
|
3
3
|
import {StringUtil} from "../util";
|
4
|
+
import {OAuthIdTokenProvider} from "./tokenprovider/OAuthIdTokenProvider";
|
4
5
|
|
5
6
|
/**
|
6
7
|
* Manages refresh of id and access tokens.
|
7
8
|
*/
|
8
|
-
export class OAuthTokenManager {
|
9
|
+
export class OAuthTokenManager implements OAuthIdTokenProvider {
|
9
10
|
|
10
11
|
private eventManager: EventManager = new EventManager();
|
11
12
|
|
@@ -15,9 +16,12 @@ export class OAuthTokenManager {
|
|
15
16
|
|
16
17
|
idToken?: IdTokenPayload;
|
17
18
|
|
19
|
+
freshIdTokenProvider: OAuthIdTokenProvider;
|
20
|
+
|
18
21
|
accessTokens: Map<string, AccessTokenPayload>;
|
19
22
|
|
20
|
-
constructor(oAuthServerBaseUrl: string, targetAudience: string) {
|
23
|
+
constructor(oAuthServerBaseUrl: string, targetAudience: string, freshIdTokenProvider: OAuthIdTokenProvider) {
|
24
|
+
this.freshIdTokenProvider = freshIdTokenProvider;
|
21
25
|
this.audience = targetAudience;
|
22
26
|
this.oAuthServer = new OAuthRestClient(oAuthServerBaseUrl);
|
23
27
|
this.accessTokens = new Map<string, AccessTokenPayload>();
|
@@ -65,21 +69,35 @@ export class OAuthTokenManager {
|
|
65
69
|
this.accessTokens.clear();
|
66
70
|
}
|
67
71
|
|
68
|
-
|
72
|
+
getIdTokenInternal(): Promise<IdTokenPayload> {
|
69
73
|
if (this.idToken === undefined || !this.hasValidIdToken()) {
|
70
|
-
return
|
74
|
+
return this.freshIdTokenProvider.getIdToken();
|
71
75
|
}
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
return Promise.resolve(this.idToken);
|
77
|
+
}
|
78
|
+
|
79
|
+
getIdToken(): Promise<IdTokenPayload> {
|
80
|
+
return this.getIdTokenInternal()
|
81
|
+
.then(
|
82
|
+
(t: IdTokenPayload) => {
|
83
|
+
if (this.isTokenReadyForRefresh(t.issuedAt, t.expires)) {
|
84
|
+
return this.oAuthServer
|
85
|
+
.refreshIdToken({idToken: t.token})
|
86
|
+
.then(
|
87
|
+
(t) => {
|
88
|
+
this.setIdToken(t);
|
89
|
+
return t;
|
90
|
+
}
|
91
|
+
);
|
79
92
|
}
|
80
|
-
|
81
|
-
|
82
|
-
|
93
|
+
this.setIdToken(t);
|
94
|
+
return Promise.resolve(t);
|
95
|
+
}
|
96
|
+
);
|
97
|
+
}
|
98
|
+
|
99
|
+
getIdTokenRaw(): Promise<string> {
|
100
|
+
return this.getIdToken().then(t => t.token);
|
83
101
|
}
|
84
102
|
|
85
103
|
setIdToken(token?: IdTokenPayload) {
|
@@ -90,22 +108,19 @@ export class OAuthTokenManager {
|
|
90
108
|
this.eventManager.triggerEvent('id-token-changed', token);
|
91
109
|
}
|
92
110
|
|
93
|
-
verifyIdToken(token: string): Promise<
|
94
|
-
return this.oAuthServer.verifyIdToken(token)
|
95
|
-
.then((t) => this.setIdToken(t));
|
111
|
+
verifyIdToken(token: string): Promise<IdTokenPayload> {
|
112
|
+
return this.oAuthServer.verifyIdToken(token);
|
96
113
|
}
|
97
114
|
|
98
115
|
login(login: string, password: string): Promise<any> {
|
99
116
|
this.reset();
|
100
|
-
return this.oAuthServer
|
101
|
-
.
|
102
|
-
|
103
|
-
this.setIdToken(t);
|
104
|
-
})
|
117
|
+
return this.oAuthServer
|
118
|
+
.requestIdTokenFromLogin({login: login, password: password, targetAudience: this.audience})
|
119
|
+
.then((t) => this.setIdToken(t));
|
105
120
|
}
|
106
121
|
|
107
122
|
private getAccessTokenInternal(privilege: string): Promise<AccessTokenPayload> {
|
108
|
-
return this.
|
123
|
+
return this.getIdTokenRaw()
|
109
124
|
.then(
|
110
125
|
(idToken: string) => this.oAuthServer
|
111
126
|
.requestAccessToken({idToken: idToken, targetAudience: this.audience, privilege: privilege})
|
@@ -2,7 +2,8 @@ import {OAuthTokenManager} from "./OAuthTokenManager";
|
|
2
2
|
import {RestClient} from "../client";
|
3
3
|
import {IdTokenPayload} from "./OAuthRestClient";
|
4
4
|
import {LazyAsync} from "../cache";
|
5
|
-
import {
|
5
|
+
import {OAuthIdTokenProvider} from "./tokenprovider/OAuthIdTokenProvider";
|
6
|
+
import {IdTokenProviderDefault} from "./tokenprovider/IdTokenProviderDefault";
|
6
7
|
|
7
8
|
export type ServerOAuthInfoPayload = {
|
8
9
|
debugMode?: boolean;
|
@@ -13,20 +14,20 @@ export type ServerOAuthInfoPayload = {
|
|
13
14
|
|
14
15
|
export class RestClientWithOAuth extends RestClient {
|
15
16
|
|
16
|
-
private tokenName = 'token';
|
17
|
-
|
18
17
|
private insecureClient: RestClient;
|
19
18
|
|
19
|
+
private freshIdTokenProvider: OAuthIdTokenProvider;
|
20
|
+
|
20
21
|
private tokenManager: LazyAsync<OAuthTokenManager>;
|
21
22
|
|
22
23
|
private serverInfo: LazyAsync<ServerOAuthInfoPayload>;
|
23
24
|
|
24
25
|
private defaultPrivilege: string;
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
constructor(url: string, defaultPrivilege: string = '*') {
|
27
|
+
constructor(url: string, freshIdTokenProvider?: OAuthIdTokenProvider, defaultPrivilege: string = '*') {
|
29
28
|
super(url);
|
29
|
+
|
30
|
+
this.freshIdTokenProvider = freshIdTokenProvider || new IdTokenProviderDefault(this);
|
30
31
|
this.defaultPrivilege = defaultPrivilege;
|
31
32
|
|
32
33
|
// rest client without OAuth headers
|
@@ -36,65 +37,11 @@ export class RestClientWithOAuth extends RestClient {
|
|
36
37
|
this.tokenManager = new LazyAsync<OAuthTokenManager>(() => this.getTokenManagerInternal());
|
37
38
|
}
|
38
39
|
|
39
|
-
isRedirecting(): boolean {
|
40
|
-
return StringUtil.isEmpty(this.redirecting);
|
41
|
-
}
|
42
|
-
|
43
|
-
redirectingTo(): string {
|
44
|
-
return StringUtil.getNonEmpty(this.redirecting);
|
45
|
-
}
|
46
|
-
|
47
|
-
redirectTo(url: string): Promise<any> {
|
48
|
-
this.redirecting = url;
|
49
|
-
document.location.href = url;
|
50
|
-
return Promise.reject(`Redirecting to ${location}`);
|
51
|
-
}
|
52
|
-
|
53
|
-
initializeIdToken(): Promise<any> {
|
54
|
-
const urlToken = this.getIdTokenFromUrl();
|
55
|
-
if (urlToken !== null) {
|
56
|
-
return this
|
57
|
-
.setIdTokenRaw(urlToken)
|
58
|
-
.then(
|
59
|
-
() => this.redirectTo(this.deleteIdTokenFromUrl())
|
60
|
-
);
|
61
|
-
} else {
|
62
|
-
const storageToken = this.getIdTokenFromLocalStorage();
|
63
|
-
if (storageToken) return this.setIdToken(storageToken);
|
64
|
-
}
|
65
|
-
return Promise.reject("No valid ID token!");
|
66
|
-
}
|
67
|
-
|
68
40
|
/**
|
69
|
-
* Attempt to get ID token from
|
70
|
-
*/
|
71
|
-
redirectToLogin(): Promise<any> {
|
72
|
-
if (this.isRedirecting()) return Promise.reject("Already redirecting!");
|
73
|
-
return this.getServerInfo().then(
|
74
|
-
(si) => {
|
75
|
-
const location = `${si.oauthServerUrl}/login?app_name=${si.targetAudience}&redirect_url=${this.deleteIdTokenFromUrl()}`;
|
76
|
-
return this.redirectTo(location);
|
77
|
-
}
|
78
|
-
).catch((err) => {
|
79
|
-
console.error('Redirection failed: OAuth info not fetched:', err);
|
80
|
-
return Promise.reject(err);
|
81
|
-
});
|
82
|
-
}
|
83
|
-
|
84
|
-
/**
|
85
|
-
* Attempt to get ID token from URL or storage, redirect to login page when not successful
|
41
|
+
* Attempt to get ID token from the provider, this will trigger redirect to login screen in case of the default provider
|
86
42
|
*/
|
87
43
|
initialize(): Promise<any> {
|
88
|
-
return this.
|
89
|
-
.then(() => {
|
90
|
-
if (!this.isRedirecting()) return this.checkAccessToken();
|
91
|
-
})
|
92
|
-
.catch(
|
93
|
-
(reason) => {
|
94
|
-
console.log('OAuth initialization failed:', reason);
|
95
|
-
return this.redirectToLogin();
|
96
|
-
}
|
97
|
-
);
|
44
|
+
return this.getTokenManager().then(tm => tm.getIdToken())
|
98
45
|
}
|
99
46
|
|
100
47
|
logout(): Promise<any> {
|
@@ -111,38 +58,6 @@ export class RestClientWithOAuth extends RestClient {
|
|
111
58
|
return this.defaultPrivilege;
|
112
59
|
}
|
113
60
|
|
114
|
-
deleteIdTokenFromUrl(): string {
|
115
|
-
const url = new URL(document.location.toString());
|
116
|
-
url.searchParams.delete(this.tokenName);
|
117
|
-
return StringUtil.trimTrailingSlashes(url.toString());
|
118
|
-
}
|
119
|
-
|
120
|
-
getIdTokenFromUrl(): string | null {
|
121
|
-
const up = new URLSearchParams(document.location.search);
|
122
|
-
return up.get(this.tokenName);
|
123
|
-
}
|
124
|
-
|
125
|
-
getIdTokenFromLocalStorage(): IdTokenPayload | null | undefined {
|
126
|
-
return JsonUtil.parse(localStorage.getItem('id-token'));
|
127
|
-
}
|
128
|
-
|
129
|
-
saveIdTokenToLocalStorage(token: IdTokenPayload | null) {
|
130
|
-
const raw = token ? JSON.stringify(token) : null;
|
131
|
-
if (raw === null) {
|
132
|
-
localStorage.removeItem('id-token');
|
133
|
-
return;
|
134
|
-
}
|
135
|
-
localStorage.setItem('id-token', raw);
|
136
|
-
}
|
137
|
-
|
138
|
-
addIdTokenChangedHandler(handler: () => any) {
|
139
|
-
this.getTokenManager().then((m) => m.addIdTokenChangedHandler(handler));
|
140
|
-
}
|
141
|
-
|
142
|
-
removeIdTokenChangedHandler(handler: () => any) {
|
143
|
-
this.getTokenManager().then((m) => m.removeIdTokenChangedHandler(handler));
|
144
|
-
}
|
145
|
-
|
146
61
|
private getServerInfoInternal(): Promise<ServerOAuthInfoPayload> {
|
147
62
|
return this.insecureClient.getJson('status/oauth/info');
|
148
63
|
}
|
@@ -151,15 +66,10 @@ export class RestClientWithOAuth extends RestClient {
|
|
151
66
|
return this.serverInfo.get();
|
152
67
|
}
|
153
68
|
|
154
|
-
|
155
|
-
return this
|
156
|
-
.
|
157
|
-
|
158
|
-
const tm = new OAuthTokenManager(info.oauthServerUrl, info.targetAudience);
|
159
|
-
tm.addIdTokenChangedHandler((t: IdTokenPayload) => this.saveIdTokenToLocalStorage(t));
|
160
|
-
return tm;
|
161
|
-
}
|
162
|
-
);
|
69
|
+
protected getTokenManagerInternal(): Promise<OAuthTokenManager> {
|
70
|
+
return this
|
71
|
+
.getServerInfo()
|
72
|
+
.then((info) => new OAuthTokenManager(info.oauthServerUrl, info.targetAudience, this.freshIdTokenProvider));
|
163
73
|
}
|
164
74
|
|
165
75
|
getTokenManager(): Promise<OAuthTokenManager> {
|
@@ -175,10 +85,6 @@ export class RestClientWithOAuth extends RestClient {
|
|
175
85
|
.then((m) => m.setIdToken(token));
|
176
86
|
}
|
177
87
|
|
178
|
-
setIdTokenRaw(token: string): Promise<any> {
|
179
|
-
return this.getTokenManager().then(m => m.verifyIdToken(token))
|
180
|
-
}
|
181
|
-
|
182
88
|
getHeaders(endpoint: string): Promise<Headers> {
|
183
89
|
return this.getTokenManager()
|
184
90
|
.then(tm => tm.getAccessToken(this.getPrivilege(endpoint)))
|
@@ -193,14 +99,4 @@ export class RestClientWithOAuth extends RestClient {
|
|
193
99
|
);
|
194
100
|
}
|
195
101
|
|
196
|
-
/**
|
197
|
-
* Try to obtain access token, then return if everything is okay.
|
198
|
-
* This is basically only used when initializing and trying to determine whether we need to redirect user to login page
|
199
|
-
*/
|
200
|
-
checkAccessToken(privilege?: string): Promise<any> {
|
201
|
-
return this.getTokenManager()
|
202
|
-
.then(tm => tm.getAccessToken(StringUtil.getNonEmpty(privilege, this.defaultPrivilege)))
|
203
|
-
.catch((e) => Promise.reject(`Access token check failed: ${e}`));
|
204
|
-
}
|
205
|
-
|
206
102
|
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import {OAuthIdTokenProvider} from "./OAuthIdTokenProvider";
|
2
|
+
import {IdTokenPayload} from "../OAuthRestClient";
|
3
|
+
import {IdTokenProviderLogin} from "./IdTokenProviderLogin";
|
4
|
+
import {RestClientWithOAuth} from "../RestClientWithOAuth";
|
5
|
+
import { IdTokenProviderUrl } from "./IdTokenProviderUrl";
|
6
|
+
import {IdTokenProviderStorage} from "./IdTokenProviderStorage";
|
7
|
+
|
8
|
+
export class IdTokenProviderDefault implements OAuthIdTokenProvider {
|
9
|
+
|
10
|
+
login: IdTokenProviderLogin;
|
11
|
+
|
12
|
+
url: IdTokenProviderUrl;
|
13
|
+
|
14
|
+
storage: IdTokenProviderStorage;
|
15
|
+
|
16
|
+
constructor(client: RestClientWithOAuth, tokenStorageKey?: string, tokenUrlName?: string) {
|
17
|
+
this.login = new IdTokenProviderLogin(client, tokenUrlName);
|
18
|
+
this.url = new IdTokenProviderUrl(client, tokenUrlName);
|
19
|
+
this.storage = new IdTokenProviderStorage(tokenStorageKey);
|
20
|
+
}
|
21
|
+
|
22
|
+
getIdToken(): Promise<IdTokenPayload> {
|
23
|
+
return this.url
|
24
|
+
.getIdToken()
|
25
|
+
.catch(
|
26
|
+
(err) => {
|
27
|
+
console.log("No token in url, loading from storage", err);
|
28
|
+
return this.storage
|
29
|
+
.getIdToken()
|
30
|
+
.catch(
|
31
|
+
(err) => {
|
32
|
+
console.log("No token in storage, redirecting to login page", err);
|
33
|
+
return this.login.getIdToken();
|
34
|
+
}
|
35
|
+
);
|
36
|
+
}
|
37
|
+
)
|
38
|
+
.then((t) => {
|
39
|
+
this.storage.saveIdTokenToLocalStorage(t);
|
40
|
+
return t;
|
41
|
+
});
|
42
|
+
}
|
43
|
+
|
44
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import {OAuthIdTokenProvider} from "./OAuthIdTokenProvider";
|
2
|
+
import {IdTokenPayload} from "../OAuthRestClient";
|
3
|
+
import {RedirectionProvider} from "./RedirectionProvider";
|
4
|
+
import {RestClientWithOAuth} from "../RestClientWithOAuth";
|
5
|
+
import UrlUtil from "../../util/UrlUtil";
|
6
|
+
|
7
|
+
export class IdTokenProviderLogin extends RedirectionProvider implements OAuthIdTokenProvider {
|
8
|
+
|
9
|
+
client: RestClientWithOAuth;
|
10
|
+
|
11
|
+
tokenQueryName: string;
|
12
|
+
|
13
|
+
constructor(client: RestClientWithOAuth, tokenQueryName?: string) {
|
14
|
+
super();
|
15
|
+
this.client = client;
|
16
|
+
this.tokenQueryName = tokenQueryName || 'token';
|
17
|
+
}
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Attempt to get ID token from URL or storage, redirect to login page when not successful
|
21
|
+
*/
|
22
|
+
redirectToLogin(): Promise<any> {
|
23
|
+
return this.client.getServerInfo().then(
|
24
|
+
(si) => {
|
25
|
+
const thisUrl = UrlUtil.deleteParamFromUrl(document.location.toString(), this.tokenQueryName);
|
26
|
+
const location = `${si.oauthServerUrl}/login?app_name=${si.targetAudience}&redirect_url=${thisUrl}`;
|
27
|
+
return this.redirectTo(location);
|
28
|
+
}
|
29
|
+
).catch((err) => {
|
30
|
+
console.error('Redirection failed: OAuth info not fetched:', err);
|
31
|
+
return Promise.reject(err);
|
32
|
+
});
|
33
|
+
}
|
34
|
+
|
35
|
+
getIdToken(): Promise<IdTokenPayload> {
|
36
|
+
return this.redirectToLogin();
|
37
|
+
}
|
38
|
+
|
39
|
+
}
|
@@ -0,0 +1,32 @@
|
|
1
|
+
import {OAuthIdTokenProvider} from "./OAuthIdTokenProvider";
|
2
|
+
import {IdTokenPayload} from "../OAuthRestClient";
|
3
|
+
import {JsonUtil} from "../../util";
|
4
|
+
|
5
|
+
export class IdTokenProviderStorage implements OAuthIdTokenProvider {
|
6
|
+
|
7
|
+
key: string;
|
8
|
+
|
9
|
+
constructor(storageKey?: string) {
|
10
|
+
this.key = storageKey || 'id-token';
|
11
|
+
}
|
12
|
+
|
13
|
+
saveIdTokenToLocalStorage(token: IdTokenPayload | null) {
|
14
|
+
const raw = token ? JSON.stringify(token) : null;
|
15
|
+
if (raw === null) {
|
16
|
+
localStorage.removeItem(this.key);
|
17
|
+
return;
|
18
|
+
}
|
19
|
+
localStorage.setItem(this.key, raw);
|
20
|
+
}
|
21
|
+
|
22
|
+
getIdTokenFromLocalStorage(): IdTokenPayload | null | undefined {
|
23
|
+
return JsonUtil.parse(localStorage.getItem(this.key));
|
24
|
+
}
|
25
|
+
|
26
|
+
getIdToken(): Promise<IdTokenPayload> {
|
27
|
+
const token = this.getIdTokenFromLocalStorage();
|
28
|
+
if (token) return Promise.resolve(token);
|
29
|
+
return Promise.reject("No token found in storage!");
|
30
|
+
}
|
31
|
+
|
32
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import {OAuthIdTokenProvider} from "./OAuthIdTokenProvider";
|
2
|
+
import {IdTokenPayload} from "../OAuthRestClient";
|
3
|
+
import {RestClientWithOAuth} from "../RestClientWithOAuth";
|
4
|
+
import {StringUtil} from "../../util";
|
5
|
+
import UrlUtil from "../../util/UrlUtil";
|
6
|
+
|
7
|
+
export class IdTokenProviderUrl implements OAuthIdTokenProvider {
|
8
|
+
|
9
|
+
client: RestClientWithOAuth;
|
10
|
+
|
11
|
+
tokenQueryName: string;
|
12
|
+
|
13
|
+
constructor(client: RestClientWithOAuth, tokenQueryName?: string) {
|
14
|
+
this.client = client;
|
15
|
+
this.tokenQueryName = tokenQueryName || 'token';
|
16
|
+
}
|
17
|
+
|
18
|
+
getIdTokenFromUrl(): string | null {
|
19
|
+
return UrlUtil.extractParamFromUrl(document.location.toString(), this.tokenQueryName);
|
20
|
+
}
|
21
|
+
|
22
|
+
getIdToken(): Promise<IdTokenPayload> {
|
23
|
+
const raw = this.getIdTokenFromUrl();
|
24
|
+
if (raw === null || StringUtil.isBlank(raw)) return Promise.reject("No token in URL!");
|
25
|
+
return this.client
|
26
|
+
.getTokenManager()
|
27
|
+
.then(m => m.verifyIdToken(raw));
|
28
|
+
}
|
29
|
+
|
30
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import {StringUtil} from "../../util";
|
2
|
+
|
3
|
+
export class RedirectionProvider {
|
4
|
+
|
5
|
+
private redirecting?: string;
|
6
|
+
|
7
|
+
redirectTo(url: string): Promise<any> {
|
8
|
+
this.redirecting = url;
|
9
|
+
document.location.href = url;
|
10
|
+
return Promise.reject(`Redirecting to ${url}`);
|
11
|
+
}
|
12
|
+
|
13
|
+
isRedirecting(): boolean {
|
14
|
+
return StringUtil.notBlank(this.redirecting);
|
15
|
+
}
|
16
|
+
|
17
|
+
redirectingTo(): string {
|
18
|
+
return StringUtil.getNonEmpty(this.redirecting);
|
19
|
+
}
|
20
|
+
|
21
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import {StringUtil} from "./StringUtil";
|
2
|
+
|
3
|
+
export default class UrlUtil {
|
4
|
+
|
5
|
+
static deleteParamFromUrl(url: string, paramName: string): string {
|
6
|
+
const urlObj = new URL(url);
|
7
|
+
urlObj.searchParams.delete(paramName);
|
8
|
+
return StringUtil.trimTrailingSlashes(url.toString());
|
9
|
+
}
|
10
|
+
|
11
|
+
static extractParamFromUrl(url: string, name: string): string | null {
|
12
|
+
const usp = new URLSearchParams(new URL(url).search);
|
13
|
+
return usp.get(name);
|
14
|
+
}
|
15
|
+
|
16
|
+
static paramExistsInUrl(url: string, name: string): boolean {
|
17
|
+
return StringUtil.notBlank(UrlUtil.extractParamFromUrl(url, name));
|
18
|
+
}
|
19
|
+
}
|