@leancodepl/login-manager 8.5.0 → 8.5.1
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/README.md +214 -0
- package/index.cjs.default.js +1 -0
- package/index.cjs.js +554 -0
- package/index.cjs.mjs +2 -0
- package/index.d.ts +1 -0
- package/index.esm.js +545 -0
- package/package.json +1 -6
- package/src/index.d.ts +9 -0
- package/src/lib/asyncLoginManager.d.ts +32 -0
- package/src/lib/baseLoginManager.d.ts +46 -0
- package/src/lib/cannotRefreshToken.d.ts +19 -0
- package/src/lib/facebookClient.d.ts +29 -0
- package/src/lib/localTokenStorage.d.ts +29 -0
- package/src/lib/memoryTokenStorage.d.ts +19 -0
- package/src/lib/sessionTokenStorage.d.ts +29 -0
- package/src/lib/syncLoginManager.d.ts +31 -0
- package/src/lib/tokenStorage.d.ts +17 -0
package/index.cjs.js
ADDED
|
@@ -0,0 +1,554 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var buffer = require('buffer');
|
|
4
|
+
|
|
5
|
+
function _extends() {
|
|
6
|
+
_extends = Object.assign || function assign(target) {
|
|
7
|
+
for(var i = 1; i < arguments.length; i++){
|
|
8
|
+
var source = arguments[i];
|
|
9
|
+
for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
|
|
10
|
+
}
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
return _extends.apply(this, arguments);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
class BaseLoginManager {
|
|
17
|
+
trySignIn(username, password) {
|
|
18
|
+
return this.acquireToken(this.buildSignInRequest(username, password));
|
|
19
|
+
}
|
|
20
|
+
trySignInWithFacebook(accessToken) {
|
|
21
|
+
return this.acquireToken(this.buildSignInWithFacebookRequest(accessToken));
|
|
22
|
+
}
|
|
23
|
+
trySignInWithOneTimeToken(token) {
|
|
24
|
+
return this.acquireToken(this.buildSignInWithOneTimeTokenRequest(token));
|
|
25
|
+
}
|
|
26
|
+
trySignInWithGoogle(accessToken) {
|
|
27
|
+
return this.acquireToken(this.buildSignInWithGoogleRequest(accessToken));
|
|
28
|
+
}
|
|
29
|
+
trySignInWithLinkedIn(accessToken) {
|
|
30
|
+
return this.acquireToken(this.buildSignInWithLinkedInRequest(accessToken));
|
|
31
|
+
}
|
|
32
|
+
async tryRefreshToken() {
|
|
33
|
+
const token = await this.storage.getToken();
|
|
34
|
+
if (token !== null) {
|
|
35
|
+
return await this.tryRefreshTokenInternal(token);
|
|
36
|
+
} else {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
tryRefreshTokenInternal(token) {
|
|
41
|
+
if (!this.isRefreshingToken) {
|
|
42
|
+
this.isRefreshingToken = true;
|
|
43
|
+
this.acquireToken(this.buildRefreshRequest(token)).then((result)=>{
|
|
44
|
+
this.isRefreshingToken = false;
|
|
45
|
+
this.refreshTokenCallbacks.forEach((c)=>c(result.type === "success"));
|
|
46
|
+
this.refreshTokenCallbacks = [];
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return new Promise((resolve)=>{
|
|
50
|
+
this.refreshTokenCallbacks.push(resolve);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
onChange(callback) {
|
|
54
|
+
this.callbacks.push(callback);
|
|
55
|
+
}
|
|
56
|
+
removeOnChange(callback) {
|
|
57
|
+
const idx = this.callbacks.indexOf(callback);
|
|
58
|
+
if (idx !== -1) {
|
|
59
|
+
this.callbacks.splice(idx, 1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async acquireToken(init) {
|
|
63
|
+
try {
|
|
64
|
+
const result = await fetch(this.endpoint + "/connect/token", init);
|
|
65
|
+
if (!result.ok) {
|
|
66
|
+
if (result.status === 400) {
|
|
67
|
+
await this.signOut();
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
type: "failure"
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const tokenResult = await result.json();
|
|
74
|
+
const expDate = new Date();
|
|
75
|
+
expDate.setSeconds(new Date().getSeconds() + tokenResult.expires_in);
|
|
76
|
+
await this.storage.storeToken({
|
|
77
|
+
token: tokenResult.access_token,
|
|
78
|
+
refreshToken: tokenResult.refresh_token,
|
|
79
|
+
expirationDate: expDate
|
|
80
|
+
});
|
|
81
|
+
this.notify(true);
|
|
82
|
+
return {
|
|
83
|
+
type: "success"
|
|
84
|
+
};
|
|
85
|
+
} catch (e) {
|
|
86
|
+
console.warn("Cannot call Auth server, error: ", e);
|
|
87
|
+
return {
|
|
88
|
+
type: "networkError"
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
buildSignInRequest(username, password) {
|
|
93
|
+
const data = _extends({
|
|
94
|
+
grant_type: "password",
|
|
95
|
+
scope: this.scopes,
|
|
96
|
+
username: username,
|
|
97
|
+
password: password
|
|
98
|
+
}, this.additionalParams);
|
|
99
|
+
return {
|
|
100
|
+
method: "POST",
|
|
101
|
+
headers: this.prepareHeaders(),
|
|
102
|
+
body: new URLSearchParams(data)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
buildSignInWithFacebookRequest(accessToken) {
|
|
106
|
+
const data = _extends({
|
|
107
|
+
grant_type: "facebook",
|
|
108
|
+
scope: this.scopes,
|
|
109
|
+
assertion: accessToken
|
|
110
|
+
}, this.additionalParams);
|
|
111
|
+
return {
|
|
112
|
+
method: "POST",
|
|
113
|
+
headers: this.prepareHeaders(),
|
|
114
|
+
body: new URLSearchParams(data)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
buildSignInWithOneTimeTokenRequest(token) {
|
|
118
|
+
const data = _extends({
|
|
119
|
+
grant_type: "onetime",
|
|
120
|
+
scope: this.scopes,
|
|
121
|
+
token
|
|
122
|
+
}, this.additionalParams);
|
|
123
|
+
return {
|
|
124
|
+
method: "POST",
|
|
125
|
+
headers: this.prepareHeaders(),
|
|
126
|
+
body: new URLSearchParams(data)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
buildSignInWithGoogleRequest(accessToken) {
|
|
130
|
+
const data = _extends({
|
|
131
|
+
grant_type: "google",
|
|
132
|
+
scope: this.scopes,
|
|
133
|
+
assertion: accessToken
|
|
134
|
+
}, this.additionalParams);
|
|
135
|
+
return {
|
|
136
|
+
method: "POST",
|
|
137
|
+
headers: this.prepareHeaders(),
|
|
138
|
+
body: new URLSearchParams(data)
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
buildSignInWithLinkedInRequest(accessToken) {
|
|
142
|
+
const data = _extends({
|
|
143
|
+
grant_type: "linkedin",
|
|
144
|
+
scope: this.scopes,
|
|
145
|
+
assertion: accessToken
|
|
146
|
+
}, this.additionalParams);
|
|
147
|
+
return {
|
|
148
|
+
method: "POST",
|
|
149
|
+
headers: this.prepareHeaders(),
|
|
150
|
+
body: new URLSearchParams(data)
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
buildRefreshRequest(token) {
|
|
154
|
+
const data = _extends({
|
|
155
|
+
grant_type: "refresh_token",
|
|
156
|
+
scope: this.scopes,
|
|
157
|
+
refresh_token: token.refreshToken || ""
|
|
158
|
+
}, this.additionalParams);
|
|
159
|
+
return {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: this.prepareHeaders(),
|
|
162
|
+
body: new URLSearchParams(data)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
prepareHeaders() {
|
|
166
|
+
const headers = new Headers();
|
|
167
|
+
if (this.clientSecret) {
|
|
168
|
+
const sec = buffer.Buffer.from(`${this.clientId}:${this.clientSecret}`, "binary").toString("base64");
|
|
169
|
+
headers.append("Authorization", "Basic " + sec);
|
|
170
|
+
}
|
|
171
|
+
headers.append("Content-Type", "application/x-www-form-urlencoded");
|
|
172
|
+
return headers;
|
|
173
|
+
}
|
|
174
|
+
notify(isSignedIn) {
|
|
175
|
+
for (const c of this.callbacks){
|
|
176
|
+
c(isSignedIn);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/* eslint-disable-next-line max-params */ constructor(storage, endpoint, clientSecret, clientId, scopes, additionalParams){
|
|
180
|
+
this.storage = storage;
|
|
181
|
+
this.endpoint = endpoint;
|
|
182
|
+
this.clientSecret = clientSecret;
|
|
183
|
+
this.clientId = clientId;
|
|
184
|
+
this.scopes = scopes;
|
|
185
|
+
this.additionalParams = additionalParams;
|
|
186
|
+
this.callbacks = [];
|
|
187
|
+
this.refreshTokenCallbacks = [];
|
|
188
|
+
this.isRefreshingToken = false;
|
|
189
|
+
if (!clientSecret) {
|
|
190
|
+
this.additionalParams = _extends({}, additionalParams, {
|
|
191
|
+
client_id: clientId
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Error thrown when token refresh fails.
|
|
199
|
+
*
|
|
200
|
+
* Indicates that the refresh token is invalid or expired, requiring user to sign in again.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* try {
|
|
205
|
+
* const token = await loginManager.getToken();
|
|
206
|
+
* } catch (error) {
|
|
207
|
+
* if (error instanceof CannotRefreshToken) {
|
|
208
|
+
* console.log('User needs to sign in again');
|
|
209
|
+
* }
|
|
210
|
+
* }
|
|
211
|
+
* ```
|
|
212
|
+
*/ class CannotRefreshToken extends Error {
|
|
213
|
+
constructor(m){
|
|
214
|
+
super(m);
|
|
215
|
+
Object.setPrototypeOf(this, CannotRefreshToken.prototype);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Manages OAuth2 authentication with asynchronous token storage.
|
|
221
|
+
*
|
|
222
|
+
* Extends BaseLoginManager to work with async storage implementations like IndexedDB or remote storage.
|
|
223
|
+
* Handles token refresh, expiration, and authentication state management.
|
|
224
|
+
*
|
|
225
|
+
* @param storage - Token storage implementation
|
|
226
|
+
* @param endpoint - OAuth2 server endpoint
|
|
227
|
+
* @param clientSecret - Client secret for authentication
|
|
228
|
+
* @param clientId - OAuth2 client identifier
|
|
229
|
+
* @param scopes - Space-separated OAuth2 scopes
|
|
230
|
+
* @param additionalParams - Additional OAuth2 parameters
|
|
231
|
+
* @example
|
|
232
|
+
* ```typescript
|
|
233
|
+
* const tokenStorage = new CustomAsyncStorage();
|
|
234
|
+
* const loginManager = new AsyncLoginManager(
|
|
235
|
+
* tokenStorage,
|
|
236
|
+
* 'https://api.example.com',
|
|
237
|
+
* 'client_secret',
|
|
238
|
+
* 'client_id',
|
|
239
|
+
* 'openid profile'
|
|
240
|
+
* );
|
|
241
|
+
* ```
|
|
242
|
+
*/ class AsyncLoginManager extends BaseLoginManager {
|
|
243
|
+
async signOut() {
|
|
244
|
+
await this.storage.resetToken();
|
|
245
|
+
this.notify(false);
|
|
246
|
+
}
|
|
247
|
+
async isSigned() {
|
|
248
|
+
return await this.storage.getToken() !== null;
|
|
249
|
+
}
|
|
250
|
+
async getToken() {
|
|
251
|
+
const token = await this.storage.getToken();
|
|
252
|
+
if (token === null) {
|
|
253
|
+
return null;
|
|
254
|
+
} else if (token.expirationDate < new Date()) {
|
|
255
|
+
if (await this.tryRefreshTokenInternal(token)) {
|
|
256
|
+
var _this;
|
|
257
|
+
var _token;
|
|
258
|
+
return (_token = (_this = await this.storage.getToken()) == null ? void 0 : _this.token) != null ? _token : null;
|
|
259
|
+
} else {
|
|
260
|
+
throw new CannotRefreshToken("Cannot refresh access token after it has expired");
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
return token.token;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async load() {
|
|
267
|
+
const isSignedIn = await this.isSigned();
|
|
268
|
+
this.notify(isSignedIn);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/// <reference types="facebook-js-sdk" />
|
|
273
|
+
/**
|
|
274
|
+
* Integrates Facebook Login SDK for web applications.
|
|
275
|
+
*
|
|
276
|
+
* Handles Facebook authentication flow and provides access tokens for OAuth2 sign-in.
|
|
277
|
+
* Automatically loads Facebook SDK and manages login state.
|
|
278
|
+
*
|
|
279
|
+
* @param facebookAppId - Facebook App ID
|
|
280
|
+
* @param facebookPermissions - Comma-separated Facebook permissions
|
|
281
|
+
* @example
|
|
282
|
+
* ```typescript
|
|
283
|
+
* const facebookClient = new FacebookClient('your-app-id', 'email,public_profile');
|
|
284
|
+
* facebookClient.setup();
|
|
285
|
+
* facebookClient.login((accessToken) => {
|
|
286
|
+
* return loginManager.trySignInWithFacebook(accessToken);
|
|
287
|
+
* });
|
|
288
|
+
* ```
|
|
289
|
+
*/ class FacebookClient {
|
|
290
|
+
get accessToken() {
|
|
291
|
+
return this.token;
|
|
292
|
+
}
|
|
293
|
+
setup(loginCallback) {
|
|
294
|
+
const ref = document.getElementsByTagName("script")[0];
|
|
295
|
+
const id = "facebook-jssdk";
|
|
296
|
+
if (document.getElementById(id)) {
|
|
297
|
+
this.initializeSDK();
|
|
298
|
+
this.getLoginStatus(loginCallback);
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
const js = document.createElement("script");
|
|
302
|
+
js.id = id;
|
|
303
|
+
js.async = true;
|
|
304
|
+
js.src = "//connect.facebook.net/pl_PL/sdk.js";
|
|
305
|
+
if (ref.parentNode != null) {
|
|
306
|
+
ref.parentNode.insertBefore(js, ref);
|
|
307
|
+
}
|
|
308
|
+
js.onload = ()=>{
|
|
309
|
+
this.initializeSDK();
|
|
310
|
+
this.getLoginStatus(loginCallback);
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
login(callback) {
|
|
314
|
+
FB.login((response)=>{
|
|
315
|
+
if (response.status === "connected") {
|
|
316
|
+
this.isSignedIn = true;
|
|
317
|
+
this.token = response.authResponse.accessToken;
|
|
318
|
+
if (callback) {
|
|
319
|
+
callback(response.authResponse.accessToken);
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
this.isSignedIn = false;
|
|
323
|
+
}
|
|
324
|
+
}, {
|
|
325
|
+
scope: this.facebookPermissions
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
getLoginStatus(callback) {
|
|
329
|
+
FB.getLoginStatus((response)=>{
|
|
330
|
+
if (response.status === "connected") {
|
|
331
|
+
this.isSignedIn = true;
|
|
332
|
+
this.token = response.authResponse.accessToken;
|
|
333
|
+
if (callback) {
|
|
334
|
+
callback(response.authResponse.accessToken);
|
|
335
|
+
}
|
|
336
|
+
} else {
|
|
337
|
+
this.isSignedIn = false;
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
initializeSDK() {
|
|
342
|
+
FB.init({
|
|
343
|
+
appId: this.facebookAppId,
|
|
344
|
+
xfbml: true,
|
|
345
|
+
version: "v2.9"
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
constructor(facebookAppId, facebookPermissions){
|
|
349
|
+
this.facebookAppId = facebookAppId;
|
|
350
|
+
this.facebookPermissions = facebookPermissions;
|
|
351
|
+
this.isSignedIn = undefined;
|
|
352
|
+
this.token = "";
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Stores OAuth2 tokens in browser localStorage.
|
|
358
|
+
*
|
|
359
|
+
* Provides persistent token storage that survives browser sessions.
|
|
360
|
+
* Implements SyncTokenStorage interface for synchronous operations.
|
|
361
|
+
*
|
|
362
|
+
* @param tokenKey - localStorage key for access token (default: "token")
|
|
363
|
+
* @param refreshKey - localStorage key for refresh token (default: "refresh_token")
|
|
364
|
+
* @param expiryKey - localStorage key for expiry date (default: "expiration_date")
|
|
365
|
+
* @example
|
|
366
|
+
* ```typescript
|
|
367
|
+
* const storage = new LocalTokenStorage();
|
|
368
|
+
* const loginManager = new SyncLoginManager(storage, endpoint, secret, clientId, scopes);
|
|
369
|
+
* ```
|
|
370
|
+
*/ class LocalTokenStorage {
|
|
371
|
+
getToken() {
|
|
372
|
+
if (this.hasValue(this.tokenKey)) {
|
|
373
|
+
return {
|
|
374
|
+
token: this.getValue(this.tokenKey),
|
|
375
|
+
refreshToken: this.getValue(this.refreshKey),
|
|
376
|
+
expirationDate: new Date(Number(this.getValue(this.expiryKey)))
|
|
377
|
+
};
|
|
378
|
+
} else {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
storeToken(token) {
|
|
383
|
+
this.setValue(this.tokenKey, token.token);
|
|
384
|
+
this.setValue(this.refreshKey, token.refreshToken);
|
|
385
|
+
this.setValue(this.expiryKey, token.expirationDate.getTime().toString());
|
|
386
|
+
}
|
|
387
|
+
resetToken() {
|
|
388
|
+
this.remove(this.tokenKey);
|
|
389
|
+
this.remove(this.refreshKey);
|
|
390
|
+
this.remove(this.expiryKey);
|
|
391
|
+
}
|
|
392
|
+
hasValue(key) {
|
|
393
|
+
return localStorage.getItem(key) !== null;
|
|
394
|
+
}
|
|
395
|
+
getValue(key) {
|
|
396
|
+
return localStorage.getItem(key);
|
|
397
|
+
}
|
|
398
|
+
setValue(key, val) {
|
|
399
|
+
localStorage.setItem(key, val);
|
|
400
|
+
}
|
|
401
|
+
remove(key) {
|
|
402
|
+
localStorage.removeItem(key);
|
|
403
|
+
}
|
|
404
|
+
constructor(tokenKey = "token", refreshKey = "refresh_token", expiryKey = "expiration_date"){
|
|
405
|
+
this.tokenKey = tokenKey;
|
|
406
|
+
this.refreshKey = refreshKey;
|
|
407
|
+
this.expiryKey = expiryKey;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Stores OAuth2 tokens in memory.
|
|
413
|
+
*
|
|
414
|
+
* Provides temporary token storage that clears when the page is refreshed.
|
|
415
|
+
* Implements SyncTokenStorage interface for synchronous operations.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```typescript
|
|
419
|
+
* const storage = new MemoryTokenStorage();
|
|
420
|
+
* const loginManager = new SyncLoginManager(storage, endpoint, secret, clientId, scopes);
|
|
421
|
+
* ```
|
|
422
|
+
*/ class MemoryTokenStorage {
|
|
423
|
+
getToken() {
|
|
424
|
+
return this.token;
|
|
425
|
+
}
|
|
426
|
+
storeToken(token) {
|
|
427
|
+
this.token = {
|
|
428
|
+
token: token.token,
|
|
429
|
+
refreshToken: token.refreshToken,
|
|
430
|
+
expirationDate: token.expirationDate
|
|
431
|
+
};
|
|
432
|
+
return Promise.resolve();
|
|
433
|
+
}
|
|
434
|
+
resetToken() {
|
|
435
|
+
this.token = null;
|
|
436
|
+
return Promise.resolve();
|
|
437
|
+
}
|
|
438
|
+
constructor(){
|
|
439
|
+
this.token = null;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Stores OAuth2 tokens in browser sessionStorage.
|
|
445
|
+
*
|
|
446
|
+
* Provides session-based token storage that clears when the browser tab is closed.
|
|
447
|
+
* Implements SyncTokenStorage interface for synchronous operations.
|
|
448
|
+
*
|
|
449
|
+
* @param tokenKey - sessionStorage key for access token (default: "token")
|
|
450
|
+
* @param refreshKey - sessionStorage key for refresh token (default: "refresh_token")
|
|
451
|
+
* @param expiryKey - sessionStorage key for expiry date (default: "expiration_date")
|
|
452
|
+
* @example
|
|
453
|
+
* ```typescript
|
|
454
|
+
* const storage = new SessionTokenStorage();
|
|
455
|
+
* const loginManager = new SyncLoginManager(storage, endpoint, secret, clientId, scopes);
|
|
456
|
+
* ```
|
|
457
|
+
*/ class SessionTokenStorage {
|
|
458
|
+
getToken() {
|
|
459
|
+
if (this.hasValue(this.tokenKey)) {
|
|
460
|
+
return {
|
|
461
|
+
token: this.getValue(this.tokenKey),
|
|
462
|
+
refreshToken: this.getValue(this.refreshKey),
|
|
463
|
+
expirationDate: new Date(Number(this.getValue(this.expiryKey)))
|
|
464
|
+
};
|
|
465
|
+
} else {
|
|
466
|
+
return null;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
storeToken(token) {
|
|
470
|
+
this.setValue(this.tokenKey, token.token);
|
|
471
|
+
this.setValue(this.refreshKey, token.refreshToken);
|
|
472
|
+
this.setValue(this.expiryKey, token.expirationDate.getTime().toString());
|
|
473
|
+
}
|
|
474
|
+
resetToken() {
|
|
475
|
+
this.remove(this.tokenKey);
|
|
476
|
+
this.remove(this.refreshKey);
|
|
477
|
+
this.remove(this.expiryKey);
|
|
478
|
+
}
|
|
479
|
+
hasValue(key) {
|
|
480
|
+
return sessionStorage.getItem(key) !== null;
|
|
481
|
+
}
|
|
482
|
+
getValue(key) {
|
|
483
|
+
return sessionStorage.getItem(key);
|
|
484
|
+
}
|
|
485
|
+
setValue(key, val) {
|
|
486
|
+
sessionStorage.setItem(key, val);
|
|
487
|
+
}
|
|
488
|
+
remove(key) {
|
|
489
|
+
sessionStorage.removeItem(key);
|
|
490
|
+
}
|
|
491
|
+
constructor(tokenKey = "token", refreshKey = "refresh_token", expiryKey = "expiration_date"){
|
|
492
|
+
this.tokenKey = tokenKey;
|
|
493
|
+
this.refreshKey = refreshKey;
|
|
494
|
+
this.expiryKey = expiryKey;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Manages OAuth2 authentication with synchronous token storage.
|
|
500
|
+
*
|
|
501
|
+
* Extends BaseLoginManager to work with sync storage implementations like localStorage or sessionStorage.
|
|
502
|
+
* Handles token refresh, expiration, and authentication state management.
|
|
503
|
+
*
|
|
504
|
+
* @param storage - Token storage implementation
|
|
505
|
+
* @param endpoint - OAuth2 server endpoint
|
|
506
|
+
* @param clientSecret - Client secret for authentication
|
|
507
|
+
* @param clientId - OAuth2 client identifier
|
|
508
|
+
* @param scopes - Space-separated OAuth2 scopes
|
|
509
|
+
* @param additionalParams - Additional OAuth2 parameters
|
|
510
|
+
* @example
|
|
511
|
+
* ```typescript
|
|
512
|
+
* const tokenStorage = new LocalTokenStorage();
|
|
513
|
+
* const loginManager = new SyncLoginManager(
|
|
514
|
+
* tokenStorage,
|
|
515
|
+
* 'https://api.example.com',
|
|
516
|
+
* 'client_secret',
|
|
517
|
+
* 'client_id',
|
|
518
|
+
* 'openid profile'
|
|
519
|
+
* );
|
|
520
|
+
* ```
|
|
521
|
+
*/ class SyncLoginManager extends BaseLoginManager {
|
|
522
|
+
signOut() {
|
|
523
|
+
this.storage.resetToken();
|
|
524
|
+
this.notify(false);
|
|
525
|
+
}
|
|
526
|
+
isSigned() {
|
|
527
|
+
return this.storage.getToken() !== null;
|
|
528
|
+
}
|
|
529
|
+
async getToken() {
|
|
530
|
+
const token = this.storage.getToken();
|
|
531
|
+
if (token === null) {
|
|
532
|
+
return null;
|
|
533
|
+
} else if (token.expirationDate < new Date()) {
|
|
534
|
+
if (await this.tryRefreshTokenInternal(token)) {
|
|
535
|
+
var _this_storage_getToken;
|
|
536
|
+
var _this_storage_getToken_token;
|
|
537
|
+
return (_this_storage_getToken_token = (_this_storage_getToken = this.storage.getToken()) == null ? void 0 : _this_storage_getToken.token) != null ? _this_storage_getToken_token : null;
|
|
538
|
+
} else {
|
|
539
|
+
throw new CannotRefreshToken("Cannot refresh access token after it has expired");
|
|
540
|
+
}
|
|
541
|
+
} else {
|
|
542
|
+
return token.token;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
exports.AsyncLoginManager = AsyncLoginManager;
|
|
548
|
+
exports.BaseLoginManager = BaseLoginManager;
|
|
549
|
+
exports.CannotRefreshToken = CannotRefreshToken;
|
|
550
|
+
exports.FacebookClient = FacebookClient;
|
|
551
|
+
exports.LocalTokenStorage = LocalTokenStorage;
|
|
552
|
+
exports.MemoryTokenStorage = MemoryTokenStorage;
|
|
553
|
+
exports.SessionTokenStorage = SessionTokenStorage;
|
|
554
|
+
exports.SyncLoginManager = SyncLoginManager;
|
package/index.cjs.mjs
ADDED
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src/index";
|