piral-oauth2 1.0.0-pre.2112 → 1.0.0
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/LICENSE +1 -1
- package/README.md +31 -5
- package/esm/create.d.ts +1 -2
- package/esm/create.js +2 -2
- package/esm/create.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/setup.d.ts +1 -69
- package/esm/setup.js +70 -47
- package/esm/setup.js.map +1 -1
- package/esm/types.d.ts +117 -0
- package/esm/utils.d.ts +13 -0
- package/esm/utils.js +56 -0
- package/esm/utils.js.map +1 -0
- package/lib/create.d.ts +1 -2
- package/lib/create.js +2 -2
- package/lib/create.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/setup.d.ts +1 -69
- package/lib/setup.js +71 -47
- package/lib/setup.js.map +1 -1
- package/lib/types.d.ts +117 -0
- package/lib/utils.d.ts +13 -0
- package/lib/utils.js +62 -0
- package/lib/utils.js.map +1 -0
- package/package.json +26 -6
- package/piral-oauth2.min.js +1 -0
- package/src/create.ts +1 -2
- package/src/index.ts +1 -0
- package/src/setup.ts +72 -108
- package/src/types.ts +123 -0
- package/src/utils.ts +61 -0
package/src/setup.ts
CHANGED
|
@@ -1,76 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Available configuration options for the OAuth 2.0 plugin.
|
|
5
|
-
*/
|
|
6
|
-
export interface OAuth2Config {
|
|
7
|
-
/**
|
|
8
|
-
* The id of the client. Required for the setup of OAuth 2.0.
|
|
9
|
-
*/
|
|
10
|
-
clientId: string;
|
|
11
|
-
/**
|
|
12
|
-
* The client secret. Only required for the `code` flow.
|
|
13
|
-
*/
|
|
14
|
-
clientSecret?: string;
|
|
15
|
-
/**
|
|
16
|
-
* The Uri pointing to the authorization endpoint of the Identity Provider.
|
|
17
|
-
*/
|
|
18
|
-
authorizationUri: string;
|
|
19
|
-
/**
|
|
20
|
-
* The Uri pointing to the access token endpoint of the Identity Provider.
|
|
21
|
-
*/
|
|
22
|
-
accessTokenUri?: string;
|
|
23
|
-
/**
|
|
24
|
-
* The redirect Uri to use. By default the origin with /auth
|
|
25
|
-
* is used.
|
|
26
|
-
*/
|
|
27
|
-
redirectUri?: string;
|
|
28
|
-
/**
|
|
29
|
-
* The scopes to be used.
|
|
30
|
-
*/
|
|
31
|
-
scopes?: Array<string>;
|
|
32
|
-
/**
|
|
33
|
-
* The OAuth 2.0 authorization flow type to be used.
|
|
34
|
-
*/
|
|
35
|
-
flow?: 'implicit' | 'code';
|
|
36
|
-
/**
|
|
37
|
-
* Restricts token sharing such that other integrations, e.g., with
|
|
38
|
-
* fetch would need to be done manually.
|
|
39
|
-
* Otherwise, the client is responsive to the `before-fetch` event.
|
|
40
|
-
*/
|
|
41
|
-
restrict?: boolean;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface OAuth2Request {
|
|
45
|
-
/**
|
|
46
|
-
* Sets the headers of the request.
|
|
47
|
-
* @param headers Headers or a promise to headers.
|
|
48
|
-
*/
|
|
49
|
-
setHeaders(headers: any): void;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export interface OAuth2Client {
|
|
53
|
-
/**
|
|
54
|
-
* Performs a login.
|
|
55
|
-
*/
|
|
56
|
-
login(): void;
|
|
57
|
-
/**
|
|
58
|
-
* Performs a logout.
|
|
59
|
-
*/
|
|
60
|
-
logout(): void;
|
|
61
|
-
/**
|
|
62
|
-
* Gets a token.
|
|
63
|
-
*/
|
|
64
|
-
token(): Promise<string>;
|
|
65
|
-
/**
|
|
66
|
-
* Checks if the user is currently logged in.
|
|
67
|
-
*/
|
|
68
|
-
account(): boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Extends the headers of the provided request.
|
|
71
|
-
*/
|
|
72
|
-
extendHeaders(req: OAuth2Request): void;
|
|
73
|
-
}
|
|
1
|
+
import ClientOAuth2 from 'client-oauth2';
|
|
2
|
+
import { createOAuth2MemoryPersistence } from './utils';
|
|
3
|
+
import { OAuth2Config, OAuth2Client } from './types';
|
|
74
4
|
|
|
75
5
|
const callbackName = 'oauth2Cb';
|
|
76
6
|
|
|
@@ -87,8 +17,14 @@ export function setupOAuth2Client(config: OAuth2Config): OAuth2Client {
|
|
|
87
17
|
redirectUri = `${location.origin}/auth`,
|
|
88
18
|
scopes = [],
|
|
89
19
|
flow,
|
|
20
|
+
headers,
|
|
21
|
+
query,
|
|
22
|
+
state,
|
|
90
23
|
restrict = false,
|
|
24
|
+
returnPath = '/',
|
|
25
|
+
persist = createOAuth2MemoryPersistence(),
|
|
91
26
|
} = config;
|
|
27
|
+
|
|
92
28
|
const client = new ClientOAuth2({
|
|
93
29
|
clientId,
|
|
94
30
|
clientSecret,
|
|
@@ -96,66 +32,94 @@ export function setupOAuth2Client(config: OAuth2Config): OAuth2Client {
|
|
|
96
32
|
authorizationUri,
|
|
97
33
|
accessTokenUri,
|
|
98
34
|
scopes,
|
|
35
|
+
headers,
|
|
36
|
+
query,
|
|
37
|
+
state,
|
|
99
38
|
});
|
|
39
|
+
|
|
100
40
|
let currentToken: ClientOAuth2.Token;
|
|
101
41
|
let retrieveToken: () => Promise<string>;
|
|
102
42
|
let getLoginUri: () => string;
|
|
103
43
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
44
|
+
const setCurrentToken = (token: ClientOAuth2.Token) => {
|
|
45
|
+
persist.save({
|
|
46
|
+
accessToken: token.accessToken,
|
|
47
|
+
data: token.data,
|
|
48
|
+
refreshToken: token.refreshToken,
|
|
49
|
+
});
|
|
109
50
|
|
|
110
|
-
|
|
51
|
+
currentToken = token;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const retrieve = (init: Promise<void>, refresh: () => Promise<ClientOAuth2.Token>) => {
|
|
55
|
+
return init.then(() => {
|
|
111
56
|
if (!currentToken) {
|
|
112
57
|
return Promise.reject('Not logged in. Please call `login()` to retrieve a token.');
|
|
113
58
|
}
|
|
114
59
|
|
|
115
60
|
if (!currentToken.expired()) {
|
|
116
|
-
return
|
|
61
|
+
return currentToken.accessToken;
|
|
117
62
|
}
|
|
118
63
|
|
|
119
|
-
return
|
|
120
|
-
|
|
64
|
+
return refresh().then((refreshedToken) => {
|
|
65
|
+
setCurrentToken(refreshedToken);
|
|
121
66
|
return currentToken.accessToken;
|
|
122
67
|
});
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const initialize = (load: () => Promise<ClientOAuth2.Token>) => {
|
|
72
|
+
const info = persist.load();
|
|
73
|
+
|
|
74
|
+
if (info) {
|
|
75
|
+
currentToken = client.createToken(info.accessToken, info.refreshToken, info.data);
|
|
76
|
+
return Promise.resolve();
|
|
77
|
+
} else {
|
|
78
|
+
return load().then(
|
|
79
|
+
(token) => {
|
|
80
|
+
const opener = window.opener;
|
|
81
|
+
|
|
82
|
+
setCurrentToken(token);
|
|
83
|
+
|
|
84
|
+
if (opener && typeof opener[callbackName] === 'function') {
|
|
85
|
+
opener[callbackName](token);
|
|
86
|
+
window.close();
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
() => {},
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
if (flow === 'code') {
|
|
95
|
+
const init = initialize(() => {
|
|
96
|
+
const url = location.href;
|
|
97
|
+
history.replaceState(undefined, undefined, returnPath);
|
|
98
|
+
return client.code.getToken(url);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
retrieveToken = () => {
|
|
102
|
+
return retrieve(init, () => currentToken.refresh());
|
|
123
103
|
};
|
|
124
104
|
getLoginUri = () => client.code.getUri();
|
|
125
105
|
} else {
|
|
126
|
-
client.token.getToken(location.href)
|
|
127
|
-
(token) => {
|
|
128
|
-
const opener = window.opener;
|
|
129
|
-
if (opener && typeof opener[callbackName] === 'function') {
|
|
130
|
-
opener[callbackName](token);
|
|
131
|
-
window.close();
|
|
132
|
-
}
|
|
133
|
-
currentToken = token;
|
|
134
|
-
},
|
|
135
|
-
() => {},
|
|
136
|
-
);
|
|
106
|
+
const init = initialize(() => client.token.getToken(location.href));
|
|
137
107
|
|
|
138
108
|
retrieveToken = () => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return new Promise<string>((res) => {
|
|
148
|
-
window[callbackName] = (token: ClientOAuth2.Token) => {
|
|
149
|
-
currentToken = token;
|
|
150
|
-
res(currentToken.accessToken);
|
|
151
|
-
};
|
|
152
|
-
window.open(client.token.getUri());
|
|
153
|
-
});
|
|
109
|
+
return retrieve(
|
|
110
|
+
init,
|
|
111
|
+
() =>
|
|
112
|
+
new Promise<ClientOAuth2.Token>((resolve) => {
|
|
113
|
+
window[callbackName] = resolve;
|
|
114
|
+
window.open(client.token.getUri());
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
154
117
|
};
|
|
155
118
|
getLoginUri = () => client.token.getUri();
|
|
156
119
|
}
|
|
157
120
|
|
|
158
121
|
return {
|
|
122
|
+
_: client,
|
|
159
123
|
login() {
|
|
160
124
|
window.location.href = getLoginUri();
|
|
161
125
|
},
|
package/src/types.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Data } from 'client-oauth2';
|
|
2
|
+
|
|
1
3
|
declare module 'piral-core/lib/types/custom' {
|
|
2
4
|
interface PiletCustomApi extends PiralOAuth2Api {}
|
|
3
5
|
}
|
|
@@ -8,3 +10,124 @@ export interface PiralOAuth2Api {
|
|
|
8
10
|
*/
|
|
9
11
|
getAccessToken(): Promise<string | undefined>;
|
|
10
12
|
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The relevant OAuth 2 token information.
|
|
16
|
+
*/
|
|
17
|
+
export interface OAuth2TokenInfo {
|
|
18
|
+
accessToken: string;
|
|
19
|
+
refreshToken: string;
|
|
20
|
+
data: Data;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Available configuration options for the OAuth 2 plugin.
|
|
25
|
+
*/
|
|
26
|
+
export interface OAuth2Config {
|
|
27
|
+
/**
|
|
28
|
+
* The id of the client. Required for the setup of OAuth 2.
|
|
29
|
+
*/
|
|
30
|
+
clientId: string;
|
|
31
|
+
/**
|
|
32
|
+
* The client secret. Only required for the `code` flow.
|
|
33
|
+
*/
|
|
34
|
+
clientSecret?: string;
|
|
35
|
+
/**
|
|
36
|
+
* The Uri pointing to the authorization endpoint of the Identity Provider.
|
|
37
|
+
*/
|
|
38
|
+
authorizationUri: string;
|
|
39
|
+
/**
|
|
40
|
+
* The Uri pointing to the access token endpoint of the Identity Provider.
|
|
41
|
+
*/
|
|
42
|
+
accessTokenUri?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The redirect Uri to use. By default the origin with /auth
|
|
45
|
+
* is used.
|
|
46
|
+
*/
|
|
47
|
+
redirectUri?: string;
|
|
48
|
+
/**
|
|
49
|
+
* The return path to use in case of the "code" flow. By default the
|
|
50
|
+
* path will be set to "/".
|
|
51
|
+
*/
|
|
52
|
+
returnPath?: string;
|
|
53
|
+
/**
|
|
54
|
+
* The scopes to be used.
|
|
55
|
+
*/
|
|
56
|
+
scopes?: Array<string>;
|
|
57
|
+
/**
|
|
58
|
+
* The OAuth 2 authorization flow type to be used.
|
|
59
|
+
*/
|
|
60
|
+
flow?: 'implicit' | 'code';
|
|
61
|
+
/**
|
|
62
|
+
* Restricts token sharing such that other integrations, e.g., with
|
|
63
|
+
* fetch would need to be done manually.
|
|
64
|
+
* Otherwise, the client is responsive to the `before-fetch` event.
|
|
65
|
+
*/
|
|
66
|
+
restrict?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Optional persistence layer for OAuth 2. By default nothing is stored.
|
|
69
|
+
*/
|
|
70
|
+
persist?: OAuth2Persistence;
|
|
71
|
+
/**
|
|
72
|
+
* The optional headers to supply in OAuth 2 requests.
|
|
73
|
+
*/
|
|
74
|
+
headers?: Record<string, string | Array<string>>;
|
|
75
|
+
/**
|
|
76
|
+
* The optional query parameters to supply in OAuth 2 requests.
|
|
77
|
+
*/
|
|
78
|
+
query?: Record<string, string | Array<string>>;
|
|
79
|
+
/**
|
|
80
|
+
* The optional state parameter to supply in OAuth 2 requests.
|
|
81
|
+
*/
|
|
82
|
+
state?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface OAuth2Request {
|
|
86
|
+
/**
|
|
87
|
+
* Sets the headers of the request.
|
|
88
|
+
* @param headers Headers or a promise to headers.
|
|
89
|
+
*/
|
|
90
|
+
setHeaders(headers: any): void;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface OAuth2Client {
|
|
94
|
+
/**
|
|
95
|
+
* The underlying OAuth2 client.
|
|
96
|
+
*/
|
|
97
|
+
_: any;
|
|
98
|
+
/**
|
|
99
|
+
* Performs a login.
|
|
100
|
+
*/
|
|
101
|
+
login(): void;
|
|
102
|
+
/**
|
|
103
|
+
* Performs a logout.
|
|
104
|
+
*/
|
|
105
|
+
logout(): void;
|
|
106
|
+
/**
|
|
107
|
+
* Gets a token.
|
|
108
|
+
*/
|
|
109
|
+
token(): Promise<string>;
|
|
110
|
+
/**
|
|
111
|
+
* Checks if the user is currently logged in.
|
|
112
|
+
*/
|
|
113
|
+
account(): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Extends the headers of the provided request.
|
|
116
|
+
*/
|
|
117
|
+
extendHeaders(req: OAuth2Request): void;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Defines the interface for the OAuth 2 persistence layer.
|
|
122
|
+
*/
|
|
123
|
+
export interface OAuth2Persistence {
|
|
124
|
+
/**
|
|
125
|
+
* Loads an OAuth 2 token structure.
|
|
126
|
+
*/
|
|
127
|
+
load(): OAuth2TokenInfo;
|
|
128
|
+
/**
|
|
129
|
+
* Stores an OAuth 2 token structure.
|
|
130
|
+
* @param info The token infos to store.
|
|
131
|
+
*/
|
|
132
|
+
save(info: OAuth2TokenInfo): void;
|
|
133
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { OAuth2Persistence } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates an OAuth 2 persistence layer using memory.
|
|
5
|
+
*/
|
|
6
|
+
export function createOAuth2MemoryPersistence(): OAuth2Persistence {
|
|
7
|
+
return {
|
|
8
|
+
load() {
|
|
9
|
+
return undefined;
|
|
10
|
+
},
|
|
11
|
+
save() {},
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates an OAuth 2 persistence layer using sessionStorage.
|
|
17
|
+
*/
|
|
18
|
+
export function createOAuth2SessionPersistence(sessionKey = '$piral_oauth2_info'): OAuth2Persistence {
|
|
19
|
+
return {
|
|
20
|
+
load() {
|
|
21
|
+
const content = sessionStorage.getItem(sessionKey);
|
|
22
|
+
|
|
23
|
+
if (typeof content === 'string') {
|
|
24
|
+
try {
|
|
25
|
+
return JSON.parse(content);
|
|
26
|
+
} catch {
|
|
27
|
+
console.error('Found invalid data in the OAuth 2 session storage key. Skipped.');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return undefined;
|
|
32
|
+
},
|
|
33
|
+
save(info) {
|
|
34
|
+
sessionStorage.setItem(sessionKey, JSON.stringify(info));
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creates an OAuth 2 persistence layer using localStorage.
|
|
41
|
+
*/
|
|
42
|
+
export function createOAuth2BrowserPersistence(localKey = '$piral_oauth2_info'): OAuth2Persistence {
|
|
43
|
+
return {
|
|
44
|
+
load() {
|
|
45
|
+
const content = localStorage.getItem(localKey);
|
|
46
|
+
|
|
47
|
+
if (typeof content === 'string') {
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(content);
|
|
50
|
+
} catch {
|
|
51
|
+
console.error('Found invalid data in the OAuth 2 local storage key. Skipped.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return undefined;
|
|
56
|
+
},
|
|
57
|
+
save(info) {
|
|
58
|
+
localStorage.setItem(localKey, JSON.stringify(info));
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|