supaapps-auth 2.0.0-rc.4 → 2.0.0-rc.6
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/AuthManager.d.ts +2 -2
- package/dist/AuthManager.js +27 -16
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/AuthManager.ts +36 -23
- package/src/types.ts +1 -0
- package/tests/AuthManager.test.ts +26 -1
package/dist/AuthManager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthManagerEvent } from './types';
|
|
1
|
+
import { AuthManagerEvent, UserTokenPayload } from './types';
|
|
2
2
|
export declare class AuthManager {
|
|
3
3
|
private static instance;
|
|
4
4
|
private authServer;
|
|
@@ -21,6 +21,6 @@ export declare class AuthManager {
|
|
|
21
21
|
private saveTokens;
|
|
22
22
|
loginUsingPkce(code: string): Promise<void>;
|
|
23
23
|
logout(): Promise<void>;
|
|
24
|
-
static validateToken(authServer: string, bearerToken: string): Promise<
|
|
24
|
+
static validateToken(authServer: string, bearerToken: string): Promise<UserTokenPayload>;
|
|
25
25
|
static resetInstance(): void;
|
|
26
26
|
}
|
package/dist/AuthManager.js
CHANGED
|
@@ -90,7 +90,7 @@ class AuthManager {
|
|
|
90
90
|
checkAccessToken() {
|
|
91
91
|
return __awaiter(this, arguments, void 0, function* (isInitilization = false) {
|
|
92
92
|
const accessToken = localStorage.getItem('access_token');
|
|
93
|
-
if (accessToken
|
|
93
|
+
if (accessToken && this.isTokenExpired(accessToken)) {
|
|
94
94
|
return this.refreshAccessToken(isInitilization);
|
|
95
95
|
}
|
|
96
96
|
return accessToken;
|
|
@@ -192,23 +192,34 @@ class AuthManager {
|
|
|
192
192
|
return __awaiter(this, void 0, void 0, function* () {
|
|
193
193
|
var _a;
|
|
194
194
|
// @todo tests missing for this static validation
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
const { data: publicKey } = yield axios_1.default.get(`${authServer}public/public_key`);
|
|
203
|
-
const { data: algo } = yield axios_1.default.get(`${authServer}public/algo`);
|
|
204
|
-
(0, jsonwebtoken_1.verify)(bearerToken, publicKey, { algorithms: [algo] });
|
|
205
|
-
const { data: revokedIds } = yield axios_1.default.get(`${authServer}public/revoked_ids`);
|
|
206
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
207
|
-
return !revokedIds.includes(decodedToken['id']);
|
|
195
|
+
// @todo add caching for public key and algo
|
|
196
|
+
const decodedToken = (_a = (0, jsonwebtoken_1.decode)(bearerToken, {
|
|
197
|
+
complete: true,
|
|
198
|
+
})) === null || _a === void 0 ? void 0 : _a.payload;
|
|
199
|
+
if (!decodedToken) {
|
|
200
|
+
throw new Error('Not a valid jwt token');
|
|
208
201
|
}
|
|
209
|
-
|
|
210
|
-
|
|
202
|
+
const userToken = {
|
|
203
|
+
id: decodedToken['id'],
|
|
204
|
+
iss: decodedToken['iss'],
|
|
205
|
+
sub: parseInt(decodedToken['sub']),
|
|
206
|
+
first_name: decodedToken['first_name'],
|
|
207
|
+
last_name: decodedToken['last_name'],
|
|
208
|
+
email: decodedToken['email'],
|
|
209
|
+
aud: decodedToken['aud'],
|
|
210
|
+
iat: decodedToken['iat'],
|
|
211
|
+
exp: decodedToken['exp'],
|
|
212
|
+
scopes: decodedToken['scopes'],
|
|
213
|
+
realm: decodedToken['realm'],
|
|
214
|
+
};
|
|
215
|
+
const { data: publicKey } = yield axios_1.default.get(`${authServer}public/public_key`);
|
|
216
|
+
const { data: algo } = yield axios_1.default.get(`${authServer}public/algo`);
|
|
217
|
+
(0, jsonwebtoken_1.verify)(bearerToken, publicKey, { algorithms: [algo] });
|
|
218
|
+
const { data: revokedIds } = yield axios_1.default.get(`${authServer}public/revoked_ids`);
|
|
219
|
+
if (revokedIds.includes(decodedToken['id'])) {
|
|
220
|
+
throw new Error('Token is revoked');
|
|
211
221
|
}
|
|
222
|
+
return userToken;
|
|
212
223
|
});
|
|
213
224
|
}
|
|
214
225
|
static resetInstance() {
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
package/src/AuthManager.ts
CHANGED
|
@@ -124,7 +124,7 @@ export class AuthManager {
|
|
|
124
124
|
|
|
125
125
|
public async checkAccessToken(isInitilization: boolean = false): Promise<string> {
|
|
126
126
|
const accessToken = localStorage.getItem('access_token');
|
|
127
|
-
if (accessToken
|
|
127
|
+
if (accessToken && this.isTokenExpired(accessToken)) {
|
|
128
128
|
return this.refreshAccessToken(isInitilization);
|
|
129
129
|
}
|
|
130
130
|
return accessToken;
|
|
@@ -230,34 +230,47 @@ export class AuthManager {
|
|
|
230
230
|
public static async validateToken(
|
|
231
231
|
authServer: string,
|
|
232
232
|
bearerToken: string,
|
|
233
|
-
): Promise<
|
|
233
|
+
): Promise<UserTokenPayload> {
|
|
234
234
|
// @todo tests missing for this static validation
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
235
|
+
// @todo add caching for public key and algo
|
|
236
|
+
const decodedToken = jwtDecode(bearerToken, {
|
|
237
|
+
complete: true,
|
|
238
|
+
})?.payload;
|
|
239
239
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
if (!decodedToken) {
|
|
241
|
+
throw new Error('Not a valid jwt token');
|
|
242
|
+
}
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
244
|
+
const userToken: UserTokenPayload = {
|
|
245
|
+
id: decodedToken['id'],
|
|
246
|
+
iss: decodedToken['iss'],
|
|
247
|
+
sub: parseInt(decodedToken['sub'] as string),
|
|
248
|
+
first_name: decodedToken['first_name'],
|
|
249
|
+
last_name: decodedToken['last_name'],
|
|
250
|
+
email: decodedToken['email'],
|
|
251
|
+
aud: decodedToken['aud'],
|
|
252
|
+
iat: decodedToken['iat'],
|
|
253
|
+
exp: decodedToken['exp'],
|
|
254
|
+
scopes: decodedToken['scopes'],
|
|
255
|
+
realm: decodedToken['realm'],
|
|
256
|
+
}
|
|
250
257
|
|
|
251
|
-
|
|
258
|
+
const { data: publicKey } = await axios.get(
|
|
259
|
+
`${authServer}public/public_key`,
|
|
260
|
+
);
|
|
261
|
+
const { data: algo } = await axios.get(
|
|
262
|
+
`${authServer}public/algo`,
|
|
263
|
+
);
|
|
252
264
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
jwtVerify(bearerToken, publicKey, { algorithms: [algo] });
|
|
266
|
+
|
|
267
|
+
const { data: revokedIds } = await axios.get(
|
|
268
|
+
`${authServer}public/revoked_ids`,
|
|
269
|
+
);
|
|
270
|
+
if(revokedIds.includes(decodedToken['id'])){
|
|
271
|
+
throw new Error('Token is revoked');
|
|
260
272
|
}
|
|
273
|
+
return userToken;
|
|
261
274
|
}
|
|
262
275
|
|
|
263
276
|
public static resetInstance(): void {
|
package/src/types.ts
CHANGED
|
@@ -12,7 +12,12 @@ const tokenThatWontExpire2 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxM
|
|
|
12
12
|
const tokenThatExpired = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiZmlyc3RfbmFtZSI6IkpvaG4gRG9lIiwibGFzdF9uYW1lIjoiRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJzY29wZXMiOiIvcm9vdC8qIiwiZXhwIjo1MDAsImlkIjoyLCJpc3MiOjEyMywiYXVkIjoidGVzdGluZyJ9.ungpbhHfCM5ZP5oiZ1RnMkJ-NKJI8s3_IPJptjyKHR4';
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
|
|
16
|
+
|
|
15
17
|
describe('AuthManager Tests', () => {
|
|
18
|
+
beforeAll(() => {
|
|
19
|
+
jest.spyOn(localStorage, 'getItem');
|
|
20
|
+
});
|
|
16
21
|
|
|
17
22
|
beforeEach(() => {
|
|
18
23
|
localStorage.clear(); // Clear localStorage before each test
|
|
@@ -72,6 +77,26 @@ describe('AuthManager Tests', () => {
|
|
|
72
77
|
});
|
|
73
78
|
|
|
74
79
|
|
|
80
|
+
describe('AuthManager Tests isolated ', () => {
|
|
81
|
+
it('doesn\'t refresh access token when its not expired', async () => {
|
|
82
|
+
const stateChange = jest.fn();
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
// check that we set localstorage correct
|
|
86
|
+
localStorage.setItem('access_token', tokenThatWontExpire1);
|
|
87
|
+
localStorage.setItem('refresh_token', 'mockRefreshToken');
|
|
88
|
+
|
|
89
|
+
const manager = AuthManager.initialize('http://auth-server.com/', 'example-realm', 'http://myapp.com/callback', stateChange);
|
|
90
|
+
|
|
91
|
+
const currentCallCount = (localStorage.getItem as jest.Mock).mock.calls.length;
|
|
92
|
+
|
|
93
|
+
const token = await manager.getAccessToken();
|
|
94
|
+
|
|
95
|
+
expect(localStorage.getItem).toHaveBeenCalledTimes(currentCallCount + 1);
|
|
96
|
+
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
75
100
|
it('throws an error when no refresh token is found', async () => {
|
|
76
101
|
localStorage.removeItem('refresh_token');
|
|
77
102
|
|
|
@@ -125,4 +150,4 @@ describe('AuthManager Tests', () => {
|
|
|
125
150
|
|
|
126
151
|
|
|
127
152
|
|
|
128
|
-
});
|
|
153
|
+
});
|