supaapps-auth 2.0.0 → 3.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/dist/index.d.ts +88 -2
- package/dist/index.js +475 -19
- package/package.json +21 -15
- package/.eslintrc +0 -3
- package/.github/workflows/ci.yml +0 -32
- package/.github/workflows/publish-to-npm.yml +0 -30
- package/.prettierrc +0 -7
- package/dist/AuthManager.d.ts +0 -47
- package/dist/AuthManager.js +0 -408
- package/dist/types.d.ts +0 -40
- package/dist/types.js +0 -24
- package/jest.config.js +0 -16
- package/src/AuthManager.ts +0 -542
- package/src/index.ts +0 -2
- package/src/types.ts +0 -45
- package/tests/AuthManager.test.ts +0 -153
- package/tsconfig.json +0 -9
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
name: Publish to NPM
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
tags:
|
|
6
|
-
- "v*"
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
build:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
steps:
|
|
12
|
-
- name: Checkout code
|
|
13
|
-
uses: actions/checkout@v2
|
|
14
|
-
|
|
15
|
-
- name: Use Node.js
|
|
16
|
-
uses: actions/setup-node@v3
|
|
17
|
-
with:
|
|
18
|
-
node-version: lts/*
|
|
19
|
-
registry-url: 'https://registry.npmjs.org'
|
|
20
|
-
|
|
21
|
-
- name: Install dependencies
|
|
22
|
-
run: npm install
|
|
23
|
-
|
|
24
|
-
- name: Build
|
|
25
|
-
run: npm run build
|
|
26
|
-
|
|
27
|
-
- name: Publish to npm
|
|
28
|
-
run: npm publish
|
|
29
|
-
env:
|
|
30
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/.prettierrc
DELETED
package/dist/AuthManager.d.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { AuthManagerEvent, PlatformCheckResponse, UserTokenPayload } from './types';
|
|
2
|
-
export declare class AuthManager {
|
|
3
|
-
private static instance;
|
|
4
|
-
private authServer;
|
|
5
|
-
private realmName;
|
|
6
|
-
private redirectUri;
|
|
7
|
-
private onStateChange;
|
|
8
|
-
private constructor();
|
|
9
|
-
static initialize(authServer: string, realmName: string, redirectUri: string, onStateChange: (event: AuthManagerEvent) => void): AuthManager;
|
|
10
|
-
static getInstance(): AuthManager;
|
|
11
|
-
private tokenToPayload;
|
|
12
|
-
private toBase64Url;
|
|
13
|
-
private generatePKCEPair;
|
|
14
|
-
refreshAccessToken(isInitialization?: boolean): Promise<string>;
|
|
15
|
-
checkAccessToken(isInitilization?: boolean): Promise<string>;
|
|
16
|
-
private isTokenExpired;
|
|
17
|
-
mustBeLoggedIn(): Promise<void>;
|
|
18
|
-
getLoginWithGoogleUri(): string;
|
|
19
|
-
isLoggedIn(): Promise<boolean>;
|
|
20
|
-
getAccessToken(mustBeLoggedIn?: boolean): Promise<string>;
|
|
21
|
-
platformCheck(email: string): Promise<PlatformCheckResponse>;
|
|
22
|
-
verifyEmail(email: string, token: string): Promise<boolean>;
|
|
23
|
-
doPassReset(email: string, token: string, newPassword: string): Promise<boolean>;
|
|
24
|
-
changeEmail(email: string): Promise<boolean>;
|
|
25
|
-
initPasswordReset(email: string): Promise<boolean>;
|
|
26
|
-
/**
|
|
27
|
-
* Updates user account fields. Only sends fields present in the update object.
|
|
28
|
-
* For password, expects: { old: string, new: string }
|
|
29
|
-
*/
|
|
30
|
-
updateAccount(update: {
|
|
31
|
-
firstName?: string;
|
|
32
|
-
lastName?: string;
|
|
33
|
-
email?: string;
|
|
34
|
-
password?: {
|
|
35
|
-
old: string;
|
|
36
|
-
new: string;
|
|
37
|
-
};
|
|
38
|
-
}): Promise<boolean>;
|
|
39
|
-
changePassword(oldPassword: string, newPassword: string, email: string): Promise<boolean>;
|
|
40
|
-
registerUsingEmail(firstName: string, lastName: string, email: string, password: string): Promise<void>;
|
|
41
|
-
private saveTokens;
|
|
42
|
-
loginUsingEmail(email: string, password: string): Promise<void>;
|
|
43
|
-
loginUsingPkce(code: string): Promise<void>;
|
|
44
|
-
logout(): Promise<void>;
|
|
45
|
-
static validateToken(authServer: string, bearerToken: string): Promise<UserTokenPayload>;
|
|
46
|
-
static resetInstance(): void;
|
|
47
|
-
}
|
package/dist/AuthManager.js
DELETED
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.AuthManager = void 0;
|
|
13
|
-
const axios_1 = require("axios");
|
|
14
|
-
const crypto_1 = require("crypto");
|
|
15
|
-
const jsonwebtoken_1 = require("jsonwebtoken"); // Ensure jsonwebtoken is correctly imported
|
|
16
|
-
const types_1 = require("./types");
|
|
17
|
-
class AuthManager {
|
|
18
|
-
constructor(authServer, realmName, redirectUri, onStateChange) {
|
|
19
|
-
this.authServer = authServer;
|
|
20
|
-
this.realmName = realmName;
|
|
21
|
-
this.redirectUri = redirectUri;
|
|
22
|
-
this.onStateChange = onStateChange;
|
|
23
|
-
AuthManager.instance = this;
|
|
24
|
-
}
|
|
25
|
-
static initialize(authServer, realmName, redirectUri, onStateChange) {
|
|
26
|
-
if (!AuthManager.instance) {
|
|
27
|
-
AuthManager.instance = new AuthManager(authServer, realmName, redirectUri, onStateChange);
|
|
28
|
-
AuthManager.instance
|
|
29
|
-
.checkAccessToken(true)
|
|
30
|
-
.then((token) => {
|
|
31
|
-
onStateChange({
|
|
32
|
-
type: types_1.AuthEventType.INITALIZED_IN,
|
|
33
|
-
user: AuthManager.instance.tokenToPayload(token),
|
|
34
|
-
});
|
|
35
|
-
})
|
|
36
|
-
.catch(() => {
|
|
37
|
-
onStateChange({ type: types_1.AuthEventType.INITALIZED_OUT });
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
return AuthManager.instance;
|
|
41
|
-
}
|
|
42
|
-
static getInstance() {
|
|
43
|
-
if (!AuthManager.instance) {
|
|
44
|
-
throw new Error('AuthManager not initialized');
|
|
45
|
-
}
|
|
46
|
-
return AuthManager.instance;
|
|
47
|
-
}
|
|
48
|
-
tokenToPayload(token) {
|
|
49
|
-
return JSON.parse(atob(token.split('.')[1]));
|
|
50
|
-
}
|
|
51
|
-
toBase64Url(base64String) {
|
|
52
|
-
return base64String
|
|
53
|
-
.replace(/\+/g, '-')
|
|
54
|
-
.replace(/\//g, '_')
|
|
55
|
-
.replace(/=+$/, '');
|
|
56
|
-
}
|
|
57
|
-
generatePKCEPair() {
|
|
58
|
-
var _a, _b;
|
|
59
|
-
const verifier = (_a = localStorage.getItem('codeVerifier')) !== null && _a !== void 0 ? _a : this.toBase64Url((0, crypto_1.randomBytes)(32).toString('base64'));
|
|
60
|
-
const challenge = (_b = localStorage.getItem('codeChallenge')) !== null && _b !== void 0 ? _b : this.toBase64Url((0, crypto_1.createHash)('sha256').update(verifier).digest('base64'));
|
|
61
|
-
localStorage.setItem('codeVerifier', verifier);
|
|
62
|
-
localStorage.setItem('codeChallenge', challenge);
|
|
63
|
-
return { verifier, challenge };
|
|
64
|
-
}
|
|
65
|
-
refreshAccessToken() {
|
|
66
|
-
return __awaiter(this, arguments, void 0, function* (isInitialization = false) {
|
|
67
|
-
try {
|
|
68
|
-
const refreshToken = localStorage.getItem('refresh_token');
|
|
69
|
-
if (!refreshToken) {
|
|
70
|
-
throw new Error('No refresh token found');
|
|
71
|
-
}
|
|
72
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/refresh`, {
|
|
73
|
-
refresh_token: refreshToken,
|
|
74
|
-
});
|
|
75
|
-
this.saveTokens(response, true);
|
|
76
|
-
return response.data.access_token;
|
|
77
|
-
}
|
|
78
|
-
catch (error) {
|
|
79
|
-
console.error(`Refresh token error, logging out: ${error}`);
|
|
80
|
-
localStorage.removeItem('access_token');
|
|
81
|
-
localStorage.removeItem('refresh_token');
|
|
82
|
-
if (!isInitialization) {
|
|
83
|
-
// throw refresh fail only if not initialization
|
|
84
|
-
this.onStateChange({ type: types_1.AuthEventType.REFRESH_FAILED });
|
|
85
|
-
}
|
|
86
|
-
throw error;
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
checkAccessToken() {
|
|
91
|
-
return __awaiter(this, arguments, void 0, function* (isInitilization = false) {
|
|
92
|
-
const accessToken = localStorage.getItem('access_token');
|
|
93
|
-
if (accessToken && this.isTokenExpired(accessToken)) {
|
|
94
|
-
return this.refreshAccessToken(isInitilization);
|
|
95
|
-
}
|
|
96
|
-
return accessToken;
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
isTokenExpired(token) {
|
|
100
|
-
const decoded = this.tokenToPayload(token);
|
|
101
|
-
return decoded.exp < Date.now() / 1000;
|
|
102
|
-
}
|
|
103
|
-
mustBeLoggedIn() {
|
|
104
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
-
if (!(yield this.isLoggedIn())) {
|
|
106
|
-
this.onStateChange({
|
|
107
|
-
type: types_1.AuthEventType.FAILED_MUST_LOGIN_CHECK,
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
getLoginWithGoogleUri() {
|
|
113
|
-
const { challenge } = this.generatePKCEPair();
|
|
114
|
-
return `${this.authServer}auth/login_with_google?realm_name=${this.realmName}&redirect_uri=${encodeURIComponent(this.redirectUri)}&code_challenge=${challenge}&code_challenge_method=S256`;
|
|
115
|
-
}
|
|
116
|
-
isLoggedIn() {
|
|
117
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
-
try {
|
|
119
|
-
yield this.checkAccessToken();
|
|
120
|
-
return true;
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
getAccessToken() {
|
|
128
|
-
return __awaiter(this, arguments, void 0, function* (mustBeLoggedIn = false) {
|
|
129
|
-
try {
|
|
130
|
-
return yield this.checkAccessToken();
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
if (mustBeLoggedIn) {
|
|
134
|
-
this.onStateChange({
|
|
135
|
-
type: types_1.AuthEventType.FAILED_MUST_LOGIN_CHECK,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return '';
|
|
139
|
-
}
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
platformCheck(email) {
|
|
143
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/platform_check`, {
|
|
145
|
-
realm_name: this.realmName,
|
|
146
|
-
email,
|
|
147
|
-
});
|
|
148
|
-
if (response.data.error || response.data.errors) {
|
|
149
|
-
throw new Error(response.data.error || response.data.message);
|
|
150
|
-
}
|
|
151
|
-
return response.status === 200
|
|
152
|
-
? response.data
|
|
153
|
-
: { platforms: [] };
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
verifyEmail(email, token) {
|
|
157
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
158
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/verify`, {
|
|
159
|
-
realm_name: this.realmName,
|
|
160
|
-
email,
|
|
161
|
-
token,
|
|
162
|
-
});
|
|
163
|
-
if (response.data.error || response.data.errors) {
|
|
164
|
-
throw new Error(response.data.error || response.data.message);
|
|
165
|
-
}
|
|
166
|
-
return response.status === 200;
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
doPassReset(email, token, newPassword) {
|
|
170
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
171
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/do_pass_reset`, {
|
|
172
|
-
realm_name: this.realmName,
|
|
173
|
-
email,
|
|
174
|
-
token,
|
|
175
|
-
new_password: newPassword,
|
|
176
|
-
});
|
|
177
|
-
if (response.data.error || response.data.errors) {
|
|
178
|
-
throw new Error(response.data.error || response.data.message);
|
|
179
|
-
}
|
|
180
|
-
return response.status === 200;
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
changeEmail(email) {
|
|
184
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
185
|
-
const accessToken = localStorage.getItem('access_token');
|
|
186
|
-
if (!accessToken) {
|
|
187
|
-
throw new Error('Access token not found');
|
|
188
|
-
}
|
|
189
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/change_email`, {
|
|
190
|
-
realm_name: this.realmName,
|
|
191
|
-
email,
|
|
192
|
-
}, {
|
|
193
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
194
|
-
});
|
|
195
|
-
if (response.data.error || response.data.errors) {
|
|
196
|
-
throw new Error(response.data.error || response.data.message);
|
|
197
|
-
}
|
|
198
|
-
return response.status === 200;
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
initPasswordReset(email) {
|
|
202
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
203
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/init_pass_reset`, {
|
|
204
|
-
realm_name: this.realmName,
|
|
205
|
-
email,
|
|
206
|
-
});
|
|
207
|
-
if (response.data.error || response.data.errors) {
|
|
208
|
-
throw new Error(response.data.error || response.data.message);
|
|
209
|
-
}
|
|
210
|
-
return response.status === 200 || response.status === 201;
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Updates user account fields. Only sends fields present in the update object.
|
|
215
|
-
* For password, expects: { old: string, new: string }
|
|
216
|
-
*/
|
|
217
|
-
updateAccount(update) {
|
|
218
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
219
|
-
const accessToken = localStorage.getItem('access_token');
|
|
220
|
-
if (!accessToken) {
|
|
221
|
-
throw new Error('Access token not found');
|
|
222
|
-
}
|
|
223
|
-
// Update name
|
|
224
|
-
if (update.firstName || update.lastName) {
|
|
225
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/update_profile`, Object.assign(Object.assign({ realm_name: this.realmName }, (update.firstName && { first_name: update.firstName })), (update.lastName && { last_name: update.lastName })), {
|
|
226
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
227
|
-
});
|
|
228
|
-
if (response.data.error || response.data.errors) {
|
|
229
|
-
throw new Error(response.data.error || response.data.message);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
// Update email
|
|
233
|
-
if (update.email) {
|
|
234
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/change_email`, {
|
|
235
|
-
realm_name: this.realmName,
|
|
236
|
-
email: update.email,
|
|
237
|
-
}, {
|
|
238
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
239
|
-
});
|
|
240
|
-
if (response.data.error || response.data.errors) {
|
|
241
|
-
throw new Error(response.data.error || response.data.message);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
// Update password
|
|
245
|
-
if (update.password && update.email) {
|
|
246
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/change_pass`, {
|
|
247
|
-
realm_name: this.realmName,
|
|
248
|
-
email: update.email,
|
|
249
|
-
old_password: update.password.old,
|
|
250
|
-
new_password: update.password.new,
|
|
251
|
-
}, {
|
|
252
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
253
|
-
});
|
|
254
|
-
if (response.data.error || response.data.errors) {
|
|
255
|
-
throw new Error(response.data.error || response.data.message);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
else if (update.password && !update.email) {
|
|
259
|
-
throw new Error('Email is required to change password');
|
|
260
|
-
}
|
|
261
|
-
return true;
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
changePassword(oldPassword, newPassword, email) {
|
|
265
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
266
|
-
const accessToken = localStorage.getItem('access_token');
|
|
267
|
-
if (!accessToken) {
|
|
268
|
-
throw new Error('Access token not found');
|
|
269
|
-
}
|
|
270
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/change_pass`, {
|
|
271
|
-
realm_name: this.realmName,
|
|
272
|
-
email,
|
|
273
|
-
old_password: oldPassword,
|
|
274
|
-
new_password: newPassword,
|
|
275
|
-
}, {
|
|
276
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
277
|
-
});
|
|
278
|
-
if (response.data.error || response.data.errors) {
|
|
279
|
-
throw new Error(response.data.error || response.data.message);
|
|
280
|
-
}
|
|
281
|
-
return response.status === 200;
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
registerUsingEmail(firstName, lastName, email, password) {
|
|
285
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
286
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/register`, {
|
|
287
|
-
realm_name: this.realmName,
|
|
288
|
-
first_name: firstName,
|
|
289
|
-
last_name: lastName,
|
|
290
|
-
email,
|
|
291
|
-
password,
|
|
292
|
-
});
|
|
293
|
-
if (response.data.message || response.data.error) {
|
|
294
|
-
throw new Error(response.data.message || response.data.error);
|
|
295
|
-
}
|
|
296
|
-
if (!response.data.access_token) {
|
|
297
|
-
throw new Error('Something went wrong');
|
|
298
|
-
}
|
|
299
|
-
this.saveTokens(response, false);
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
saveTokens(response, byRefresh) {
|
|
303
|
-
localStorage.setItem('access_token', response.data.access_token);
|
|
304
|
-
localStorage.setItem('refresh_token', response.data.refresh_token);
|
|
305
|
-
this.onStateChange({
|
|
306
|
-
type: byRefresh
|
|
307
|
-
? types_1.AuthEventType.USER_UPDATED
|
|
308
|
-
: types_1.AuthEventType.USER_LOGGED_IN,
|
|
309
|
-
user: this.tokenToPayload(response.data.access_token),
|
|
310
|
-
});
|
|
311
|
-
const user = this.tokenToPayload(response.data.access_token);
|
|
312
|
-
localStorage.setItem('user', JSON.stringify(user));
|
|
313
|
-
}
|
|
314
|
-
loginUsingEmail(email, password) {
|
|
315
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
316
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/email/login`, {
|
|
317
|
-
realm_name: this.realmName,
|
|
318
|
-
email,
|
|
319
|
-
password,
|
|
320
|
-
});
|
|
321
|
-
if (response.data.message || response.data.error) {
|
|
322
|
-
throw new Error(response.data.message || response.data.error);
|
|
323
|
-
}
|
|
324
|
-
this.saveTokens(response, false);
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
loginUsingPkce(code) {
|
|
328
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
329
|
-
try {
|
|
330
|
-
const codeVerifier = localStorage.getItem('codeVerifier');
|
|
331
|
-
if (!codeVerifier) {
|
|
332
|
-
throw new Error('Code verifier not found');
|
|
333
|
-
}
|
|
334
|
-
const response = yield axios_1.default.post(`${this.authServer}auth/pkce_exchange`, {
|
|
335
|
-
realm_name: this.realmName,
|
|
336
|
-
code,
|
|
337
|
-
redirect_uri: this.redirectUri,
|
|
338
|
-
code_verifier: codeVerifier,
|
|
339
|
-
});
|
|
340
|
-
this.saveTokens(response, false);
|
|
341
|
-
}
|
|
342
|
-
finally {
|
|
343
|
-
localStorage.removeItem('codeVerifier');
|
|
344
|
-
localStorage.removeItem('codeChallenge');
|
|
345
|
-
}
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
logout() {
|
|
349
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
350
|
-
try {
|
|
351
|
-
const accessToken = localStorage.getItem('access_token');
|
|
352
|
-
if (!accessToken) {
|
|
353
|
-
throw new Error('Access token not found');
|
|
354
|
-
}
|
|
355
|
-
yield axios_1.default.post(`${this.authServer}auth/logout`, {}, {
|
|
356
|
-
headers: { Authorization: `Bearer ${accessToken}` },
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
finally {
|
|
360
|
-
localStorage.removeItem('access_token');
|
|
361
|
-
localStorage.removeItem('refresh_token');
|
|
362
|
-
this.onStateChange({ type: types_1.AuthEventType.USER_LOGGED_OUT });
|
|
363
|
-
}
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
static validateToken(authServer, bearerToken) {
|
|
367
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
368
|
-
var _a;
|
|
369
|
-
// @todo tests missing for this static validation
|
|
370
|
-
// @todo add caching for public key and algo
|
|
371
|
-
const decodedToken = (_a = (0, jsonwebtoken_1.decode)(bearerToken, {
|
|
372
|
-
complete: true,
|
|
373
|
-
})) === null || _a === void 0 ? void 0 : _a.payload;
|
|
374
|
-
if (!decodedToken) {
|
|
375
|
-
throw new Error('Not a valid jwt token');
|
|
376
|
-
}
|
|
377
|
-
const userToken = {
|
|
378
|
-
id: decodedToken.id,
|
|
379
|
-
iss: decodedToken.iss,
|
|
380
|
-
sub: typeof decodedToken.sub === 'string'
|
|
381
|
-
? parseInt(decodedToken.sub)
|
|
382
|
-
: decodedToken.sub,
|
|
383
|
-
first_name: decodedToken.first_name,
|
|
384
|
-
last_name: decodedToken.last_name,
|
|
385
|
-
email: decodedToken.email,
|
|
386
|
-
aud: decodedToken.aud,
|
|
387
|
-
iat: decodedToken.iat,
|
|
388
|
-
exp: decodedToken.exp,
|
|
389
|
-
scopes: decodedToken.scopes,
|
|
390
|
-
realm: decodedToken.realm,
|
|
391
|
-
provider: decodedToken.provider,
|
|
392
|
-
};
|
|
393
|
-
const { data: publicKey } = yield axios_1.default.get(`${authServer}public/public_key`);
|
|
394
|
-
const { data: algo } = yield axios_1.default.get(`${authServer}public/algo`);
|
|
395
|
-
(0, jsonwebtoken_1.verify)(bearerToken, publicKey, { algorithms: [algo] });
|
|
396
|
-
const { data: revokedIds } = yield axios_1.default.get(`${authServer}public/revoked_ids`);
|
|
397
|
-
if (revokedIds.includes(decodedToken.id)) {
|
|
398
|
-
throw new Error('Token is revoked');
|
|
399
|
-
}
|
|
400
|
-
return userToken;
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
static resetInstance() {
|
|
404
|
-
AuthManager.instance = null;
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
exports.AuthManager = AuthManager;
|
|
408
|
-
AuthManager.instance = null;
|
package/dist/types.d.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
export declare enum AuthEventType {
|
|
2
|
-
INITALIZED_IN = "initialized-logged-in",
|
|
3
|
-
INITALIZED_OUT = "initialized-logged-out",
|
|
4
|
-
USER_LOGGED_IN = "user-logged-in",
|
|
5
|
-
USER_LOGGED_OUT = "user-logged-out",
|
|
6
|
-
USER_UPDATED = "user-updated",
|
|
7
|
-
FAILED_MUST_LOGIN_CHECK = "failed-must-login",
|
|
8
|
-
REFRESH_FAILED = "refresh-failed"
|
|
9
|
-
}
|
|
10
|
-
export interface UserTokenPayload {
|
|
11
|
-
id: number;
|
|
12
|
-
iss: string;
|
|
13
|
-
sub: number | string;
|
|
14
|
-
first_name: string;
|
|
15
|
-
last_name: string;
|
|
16
|
-
email: string;
|
|
17
|
-
aud: string;
|
|
18
|
-
iat: number;
|
|
19
|
-
exp: number;
|
|
20
|
-
scopes: string;
|
|
21
|
-
realm: string;
|
|
22
|
-
provider: Platforms;
|
|
23
|
-
}
|
|
24
|
-
export interface AuthManagerEvent {
|
|
25
|
-
type: AuthEventType;
|
|
26
|
-
user?: UserTokenPayload;
|
|
27
|
-
}
|
|
28
|
-
export interface PlatformCheckResponse {
|
|
29
|
-
platform: Platforms[];
|
|
30
|
-
}
|
|
31
|
-
export declare enum Platforms {
|
|
32
|
-
PASSWORD = "password",
|
|
33
|
-
GOOGLE = "google",
|
|
34
|
-
FACEBOOK = "facebook",
|
|
35
|
-
TWITTER = "twitter",
|
|
36
|
-
GITHUB = "github",
|
|
37
|
-
APPLE = "apple",
|
|
38
|
-
LINKEDIN = "linkedin",
|
|
39
|
-
MICROSOFT = "microsoft"
|
|
40
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Platforms = exports.AuthEventType = void 0;
|
|
4
|
-
var AuthEventType;
|
|
5
|
-
(function (AuthEventType) {
|
|
6
|
-
AuthEventType["INITALIZED_IN"] = "initialized-logged-in";
|
|
7
|
-
AuthEventType["INITALIZED_OUT"] = "initialized-logged-out";
|
|
8
|
-
AuthEventType["USER_LOGGED_IN"] = "user-logged-in";
|
|
9
|
-
AuthEventType["USER_LOGGED_OUT"] = "user-logged-out";
|
|
10
|
-
AuthEventType["USER_UPDATED"] = "user-updated";
|
|
11
|
-
AuthEventType["FAILED_MUST_LOGIN_CHECK"] = "failed-must-login";
|
|
12
|
-
AuthEventType["REFRESH_FAILED"] = "refresh-failed";
|
|
13
|
-
})(AuthEventType || (exports.AuthEventType = AuthEventType = {}));
|
|
14
|
-
var Platforms;
|
|
15
|
-
(function (Platforms) {
|
|
16
|
-
Platforms["PASSWORD"] = "password";
|
|
17
|
-
Platforms["GOOGLE"] = "google";
|
|
18
|
-
Platforms["FACEBOOK"] = "facebook";
|
|
19
|
-
Platforms["TWITTER"] = "twitter";
|
|
20
|
-
Platforms["GITHUB"] = "github";
|
|
21
|
-
Platforms["APPLE"] = "apple";
|
|
22
|
-
Platforms["LINKEDIN"] = "linkedin";
|
|
23
|
-
Platforms["MICROSOFT"] = "microsoft";
|
|
24
|
-
})(Platforms || (exports.Platforms = Platforms = {}));
|
package/jest.config.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
testEnvironment: 'jsdom', // Use jsdom environment to run tests
|
|
3
|
-
roots: ['<rootDir>/tests'],
|
|
4
|
-
testMatch: ['**/*.test.ts'], // Matches test files in the tests directory
|
|
5
|
-
transform: {
|
|
6
|
-
'^.+\\.tsx?$': 'ts-jest', // Transform TypeScript files using ts-jest
|
|
7
|
-
},
|
|
8
|
-
setupFilesAfterEnv: ['jest-localstorage-mock'], // Setup local storage mock for all tests
|
|
9
|
-
testEnvironment: 'node', // Use node environment to run tests,
|
|
10
|
-
collectCoverage: true,
|
|
11
|
-
coverageReporters: [
|
|
12
|
-
"text",
|
|
13
|
-
"cobertura"
|
|
14
|
-
]
|
|
15
|
-
};
|
|
16
|
-
|