zavadil-ts-common 1.2.39 → 1.2.41
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 +23 -30
- 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 +14 -4
- package/dist/oauth/RestClientWithOAuth.d.ts +7 -26
- 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 +44 -23
- package/src/oauth/RestClientWithOAuth.ts +18 -118
- 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,30 +1,23 @@
|
|
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;
|
7
8
|
oauthServerUrl: string;
|
8
9
|
version: string;
|
9
10
|
};
|
10
|
-
export declare class RestClientWithOAuth extends RestClient {
|
11
|
-
private tokenName;
|
11
|
+
export declare class RestClientWithOAuth extends RestClient implements OAuthIdTokenProvider {
|
12
12
|
private insecureClient;
|
13
|
+
private freshIdTokenProvider;
|
13
14
|
private tokenManager;
|
14
15
|
private serverInfo;
|
15
16
|
private defaultPrivilege;
|
16
|
-
|
17
|
-
|
18
|
-
isRedirecting(): boolean;
|
19
|
-
redirectingTo(): string;
|
20
|
-
redirectTo(url: string): Promise<any>;
|
21
|
-
initializeIdToken(): Promise<any>;
|
17
|
+
constructor(url: string, freshIdTokenProvider?: OAuthIdTokenProvider, defaultPrivilege?: string);
|
18
|
+
getIdToken(): Promise<IdTokenPayload>;
|
22
19
|
/**
|
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
|
20
|
+
* Attempt to get ID token from token manager
|
28
21
|
*/
|
29
22
|
initialize(): Promise<any>;
|
30
23
|
logout(): Promise<any>;
|
@@ -33,23 +26,11 @@ export declare class RestClientWithOAuth extends RestClient {
|
|
33
26
|
* @param url
|
34
27
|
*/
|
35
28
|
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
29
|
private getServerInfoInternal;
|
43
30
|
getServerInfo(): Promise<ServerOAuthInfoPayload>;
|
44
|
-
|
31
|
+
protected getTokenManagerInternal(): Promise<OAuthTokenManager>;
|
45
32
|
getTokenManager(): Promise<OAuthTokenManager>;
|
46
33
|
login(login: string, password: string): Promise<any>;
|
47
34
|
setIdToken(token: IdTokenPayload): Promise<any>;
|
48
|
-
setIdTokenRaw(token: string): Promise<any>;
|
49
35
|
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
36
|
}
|
@@ -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,41 @@ export class OAuthTokenManager {
|
|
65
69
|
this.accessTokens.clear();
|
66
70
|
}
|
67
71
|
|
68
|
-
|
72
|
+
/**
|
73
|
+
* Get stored id token or ask the provider, this will trigger redirect to login screen in case of the default provider
|
74
|
+
*/
|
75
|
+
getIdTokenInternal(): Promise<IdTokenPayload> {
|
69
76
|
if (this.idToken === undefined || !this.hasValidIdToken()) {
|
70
|
-
return
|
77
|
+
return this.freshIdTokenProvider.getIdToken();
|
71
78
|
}
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
return Promise.resolve(this.idToken);
|
80
|
+
}
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Get id token, refresh it if needed
|
84
|
+
*/
|
85
|
+
getIdToken(): Promise<IdTokenPayload> {
|
86
|
+
return this.getIdTokenInternal()
|
87
|
+
.then(
|
88
|
+
(t: IdTokenPayload) => {
|
89
|
+
if (this.isTokenReadyForRefresh(t.issuedAt, t.expires)) {
|
90
|
+
return this.oAuthServer
|
91
|
+
.refreshIdToken({idToken: t.token})
|
92
|
+
.then(
|
93
|
+
(t) => {
|
94
|
+
this.setIdToken(t);
|
95
|
+
return t;
|
96
|
+
}
|
97
|
+
);
|
79
98
|
}
|
80
|
-
|
81
|
-
|
82
|
-
|
99
|
+
this.setIdToken(t);
|
100
|
+
return Promise.resolve(t);
|
101
|
+
}
|
102
|
+
);
|
103
|
+
}
|
104
|
+
|
105
|
+
getIdTokenRaw(): Promise<string> {
|
106
|
+
return this.getIdToken().then(t => t.token);
|
83
107
|
}
|
84
108
|
|
85
109
|
setIdToken(token?: IdTokenPayload) {
|
@@ -90,22 +114,19 @@ export class OAuthTokenManager {
|
|
90
114
|
this.eventManager.triggerEvent('id-token-changed', token);
|
91
115
|
}
|
92
116
|
|
93
|
-
verifyIdToken(token: string): Promise<
|
94
|
-
return this.oAuthServer.verifyIdToken(token)
|
95
|
-
.then((t) => this.setIdToken(t));
|
117
|
+
verifyIdToken(token: string): Promise<IdTokenPayload> {
|
118
|
+
return this.oAuthServer.verifyIdToken(token);
|
96
119
|
}
|
97
120
|
|
98
121
|
login(login: string, password: string): Promise<any> {
|
99
122
|
this.reset();
|
100
|
-
return this.oAuthServer
|
101
|
-
.
|
102
|
-
|
103
|
-
this.setIdToken(t);
|
104
|
-
})
|
123
|
+
return this.oAuthServer
|
124
|
+
.requestIdTokenFromLogin({login: login, password: password, targetAudience: this.audience})
|
125
|
+
.then((t) => this.setIdToken(t));
|
105
126
|
}
|
106
127
|
|
107
128
|
private getAccessTokenInternal(privilege: string): Promise<AccessTokenPayload> {
|
108
|
-
return this.
|
129
|
+
return this.getIdTokenRaw()
|
109
130
|
.then(
|
110
131
|
(idToken: string) => this.oAuthServer
|
111
132
|
.requestAccessToken({idToken: idToken, targetAudience: this.audience, privilege: privilege})
|
@@ -1,8 +1,9 @@
|
|
1
1
|
import {OAuthTokenManager} from "./OAuthTokenManager";
|
2
2
|
import {RestClient} from "../client";
|
3
|
-
import {IdTokenPayload} from "./OAuthRestClient";
|
3
|
+
import {IdTokenPayload, TokenResponsePayloadBase} 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;
|
@@ -11,22 +12,22 @@ export type ServerOAuthInfoPayload = {
|
|
11
12
|
version: string;
|
12
13
|
}
|
13
14
|
|
14
|
-
export class RestClientWithOAuth extends RestClient {
|
15
|
-
|
16
|
-
private tokenName = 'token';
|
15
|
+
export class RestClientWithOAuth extends RestClient implements OAuthIdTokenProvider {
|
17
16
|
|
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,15 @@ export class RestClientWithOAuth extends RestClient {
|
|
36
37
|
this.tokenManager = new LazyAsync<OAuthTokenManager>(() => this.getTokenManagerInternal());
|
37
38
|
}
|
38
39
|
|
39
|
-
|
40
|
-
|
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 ${url}`);
|
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
|
-
/**
|
69
|
-
* Attempt to get ID token from URL or storage, redirect to login page when not successful
|
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
|
-
}
|
40
|
+
getIdToken(): Promise<IdTokenPayload> {
|
41
|
+
return this.getTokenManager().then(t => t.getIdToken());
|
42
|
+
}
|
83
43
|
|
84
44
|
/**
|
85
|
-
* Attempt to get ID token from
|
45
|
+
* Attempt to get ID token from token manager
|
86
46
|
*/
|
87
47
|
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
|
-
);
|
48
|
+
return this.getIdToken();
|
98
49
|
}
|
99
50
|
|
100
51
|
logout(): Promise<any> {
|
@@ -111,38 +62,6 @@ export class RestClientWithOAuth extends RestClient {
|
|
111
62
|
return this.defaultPrivilege;
|
112
63
|
}
|
113
64
|
|
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
65
|
private getServerInfoInternal(): Promise<ServerOAuthInfoPayload> {
|
147
66
|
return this.insecureClient.getJson('status/oauth/info');
|
148
67
|
}
|
@@ -151,15 +70,10 @@ export class RestClientWithOAuth extends RestClient {
|
|
151
70
|
return this.serverInfo.get();
|
152
71
|
}
|
153
72
|
|
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
|
-
);
|
73
|
+
protected getTokenManagerInternal(): Promise<OAuthTokenManager> {
|
74
|
+
return this
|
75
|
+
.getServerInfo()
|
76
|
+
.then((info) => new OAuthTokenManager(info.oauthServerUrl, info.targetAudience, this.freshIdTokenProvider));
|
163
77
|
}
|
164
78
|
|
165
79
|
getTokenManager(): Promise<OAuthTokenManager> {
|
@@ -175,10 +89,6 @@ export class RestClientWithOAuth extends RestClient {
|
|
175
89
|
.then((m) => m.setIdToken(token));
|
176
90
|
}
|
177
91
|
|
178
|
-
setIdTokenRaw(token: string): Promise<any> {
|
179
|
-
return this.getTokenManager().then(m => m.verifyIdToken(token))
|
180
|
-
}
|
181
|
-
|
182
92
|
getHeaders(endpoint: string): Promise<Headers> {
|
183
93
|
return this.getTokenManager()
|
184
94
|
.then(tm => tm.getAccessToken(this.getPrivilege(endpoint)))
|
@@ -193,14 +103,4 @@ export class RestClientWithOAuth extends RestClient {
|
|
193
103
|
);
|
194
104
|
}
|
195
105
|
|
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
106
|
}
|
@@ -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
|
+
}
|