@tstdl/base 0.92.157 → 0.92.159
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/authentication/client/authentication.service.d.ts +24 -11
- package/authentication/client/authentication.service.js +118 -55
- package/authentication/server/authentication.api-controller.d.ts +1 -1
- package/authentication/server/authentication.api-controller.js +3 -3
- package/core.js +2 -5
- package/package.json +1 -1
|
@@ -27,6 +27,7 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
|
|
|
27
27
|
private readonly lock;
|
|
28
28
|
private readonly logger;
|
|
29
29
|
private readonly disposeToken;
|
|
30
|
+
private clockOffset;
|
|
30
31
|
/**
|
|
31
32
|
* Observable for authentication errors.
|
|
32
33
|
* Emits when a refresh fails.
|
|
@@ -113,52 +114,64 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
|
|
|
113
114
|
*/
|
|
114
115
|
login(subject: string, secret: string, data?: AuthenticationData): Promise<void>;
|
|
115
116
|
/**
|
|
116
|
-
* Logout
|
|
117
|
+
* Logout from the current session.
|
|
118
|
+
* This will attempt to end the session on the server and then clear local credentials.
|
|
117
119
|
*/
|
|
118
120
|
logout(): Promise<void>;
|
|
119
121
|
/**
|
|
120
|
-
* Force
|
|
122
|
+
* Force an immediate refresh of the token.
|
|
121
123
|
* @param data Additional authentication data
|
|
122
124
|
*/
|
|
123
125
|
requestRefresh(data?: AuthenticationData): void;
|
|
124
126
|
/**
|
|
125
|
-
* Refresh the token
|
|
127
|
+
* Refresh the token.
|
|
126
128
|
* @param data Additional authentication data
|
|
127
129
|
*/
|
|
128
130
|
refresh(data?: AuthenticationData): Promise<void>;
|
|
129
131
|
/**
|
|
130
|
-
* Impersonate a subject
|
|
132
|
+
* Impersonate a subject.
|
|
131
133
|
* @param subject The subject to impersonate
|
|
132
|
-
* @param data Additional authentication data
|
|
134
|
+
* @param data Additional authentication data for the impersonated session
|
|
133
135
|
*/
|
|
134
136
|
impersonate(subject: string, data?: AuthenticationData): Promise<void>;
|
|
135
137
|
/**
|
|
136
|
-
*
|
|
138
|
+
* End impersonation and return to the original user session.
|
|
137
139
|
* @param data Additional authentication data. If not provided, the data from before impersonation is used.
|
|
138
140
|
*/
|
|
139
141
|
unimpersonate(data?: AuthenticationData): Promise<void>;
|
|
140
142
|
/**
|
|
141
|
-
*
|
|
143
|
+
* Change the secret for a subject.
|
|
144
|
+
* @param subject The subject to change the secret for
|
|
145
|
+
* @param currentSecret The current secret
|
|
146
|
+
* @param newSecret The new secret
|
|
147
|
+
*/
|
|
148
|
+
changeSecret(subject: string, currentSecret: string, newSecret: string): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Initialize a secret reset.
|
|
142
151
|
* @param subject The subject to reset the secret for
|
|
143
152
|
* @param data Additional data for secret reset
|
|
144
153
|
*/
|
|
145
154
|
initResetSecret(subject: string, data: AdditionalInitSecretResetData): Promise<void>;
|
|
146
155
|
/**
|
|
147
|
-
* Reset a secret
|
|
156
|
+
* Reset a secret using a reset token.
|
|
148
157
|
* @param token The secret reset token
|
|
149
158
|
* @param newSecret The new secret
|
|
150
159
|
*/
|
|
151
160
|
resetSecret(token: string, newSecret: string): Promise<void>;
|
|
152
161
|
/**
|
|
153
|
-
* Check a secret for requirements
|
|
162
|
+
* Check a secret for requirements.
|
|
154
163
|
* @param secret The secret to check
|
|
155
164
|
* @returns The result of the check
|
|
156
165
|
*/
|
|
157
166
|
checkSecret(secret: string): Promise<SecretCheckResult>;
|
|
158
|
-
private saveToken;
|
|
159
|
-
private loadToken;
|
|
160
167
|
private setNewToken;
|
|
161
168
|
private refreshLoop;
|
|
162
169
|
private refreshLoopIteration;
|
|
163
170
|
private handleRefreshError;
|
|
171
|
+
private estimatedServerTimestampSeconds;
|
|
172
|
+
private syncClock;
|
|
173
|
+
private saveToken;
|
|
174
|
+
private loadToken;
|
|
175
|
+
private readFromStorage;
|
|
176
|
+
private writeToStorage;
|
|
164
177
|
}
|
|
@@ -25,8 +25,10 @@ import { Logger } from '../../logger/index.js';
|
|
|
25
25
|
import { MessageBus } from '../../message-bus/index.js';
|
|
26
26
|
import { computed, signal, toObservable } from '../../signals/api.js';
|
|
27
27
|
import { currentTimestampSeconds } from '../../utils/date-time.js';
|
|
28
|
+
import { formatError } from '../../utils/format-error.js';
|
|
28
29
|
import { timeout } from '../../utils/timing.js';
|
|
29
|
-
import { assertDefinedPass, isDefined, isNullOrUndefined,
|
|
30
|
+
import { assertDefinedPass, isDefined, isNullOrUndefined, isUndefined } from '../../utils/type-guards.js';
|
|
31
|
+
import { millisecondsPerSecond } from '../../utils/units.js';
|
|
30
32
|
import { AUTHENTICATION_API_CLIENT, INITIAL_AUTHENTICATION_DATA } from './tokens.js';
|
|
31
33
|
const tokenStorageKey = 'AuthenticationService:token';
|
|
32
34
|
const authenticationDataStorageKey = 'AuthenticationService:authentication-data';
|
|
@@ -35,6 +37,17 @@ const tokenUpdateBusName = 'AuthenticationService:tokenUpdate';
|
|
|
35
37
|
const loggedOutBusName = 'AuthenticationService:loggedOut';
|
|
36
38
|
const refreshLockResource = 'AuthenticationService:refresh';
|
|
37
39
|
const localStorage = globalThis.localStorage;
|
|
40
|
+
const refreshBufferSeconds = 15;
|
|
41
|
+
const lockTimeout = 10000;
|
|
42
|
+
const logoutTimeout = 150;
|
|
43
|
+
const unrecoverableErrors = [
|
|
44
|
+
InvalidTokenError,
|
|
45
|
+
NotFoundError,
|
|
46
|
+
BadRequestError,
|
|
47
|
+
ForbiddenError,
|
|
48
|
+
NotSupportedError,
|
|
49
|
+
UnauthorizedError,
|
|
50
|
+
];
|
|
38
51
|
/**
|
|
39
52
|
* Handles authentication on client side.
|
|
40
53
|
*
|
|
@@ -58,6 +71,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
58
71
|
lock = inject(Lock, refreshLockResource);
|
|
59
72
|
logger = inject(Logger, 'AuthenticationService');
|
|
60
73
|
disposeToken = new CancellationToken();
|
|
74
|
+
clockOffset = 0;
|
|
61
75
|
/**
|
|
62
76
|
* Observable for authentication errors.
|
|
63
77
|
* Emits when a refresh fails.
|
|
@@ -80,7 +94,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
80
94
|
/** Emits when token is available (not undefined) */
|
|
81
95
|
definedToken$ = this.token$.pipe(filter(isDefined));
|
|
82
96
|
/** Emits when a valid token is available (not undefined and not expired) */
|
|
83
|
-
validToken$ = this.definedToken$.pipe(filter((token) => token.exp >
|
|
97
|
+
validToken$ = this.definedToken$.pipe(filter((token) => token.exp > this.estimatedServerTimestampSeconds()));
|
|
84
98
|
/** Current subject */
|
|
85
99
|
subject$ = toObservable(this.subject);
|
|
86
100
|
/** Emits when subject is available */
|
|
@@ -94,30 +108,16 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
94
108
|
/** Emits when the user logs out */
|
|
95
109
|
loggedOut$ = this.loggedOutBus.allMessages$;
|
|
96
110
|
get authenticationData() {
|
|
97
|
-
|
|
98
|
-
return isNullOrUndefined(data) ? undefined : JSON.parse(data);
|
|
111
|
+
return this.readFromStorage(authenticationDataStorageKey);
|
|
99
112
|
}
|
|
100
113
|
set authenticationData(data) {
|
|
101
|
-
|
|
102
|
-
localStorage?.removeItem(authenticationDataStorageKey);
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
const json = JSON.stringify(data);
|
|
106
|
-
localStorage?.setItem(authenticationDataStorageKey, json);
|
|
107
|
-
}
|
|
114
|
+
this.writeToStorage(authenticationDataStorageKey, data);
|
|
108
115
|
}
|
|
109
116
|
get impersonatorAuthenticationData() {
|
|
110
|
-
|
|
111
|
-
return isNullOrUndefined(data) ? undefined : JSON.parse(data);
|
|
117
|
+
return this.readFromStorage(impersonatorAuthenticationDataStorageKey);
|
|
112
118
|
}
|
|
113
119
|
set impersonatorAuthenticationData(data) {
|
|
114
|
-
|
|
115
|
-
localStorage?.removeItem(impersonatorAuthenticationDataStorageKey);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
const json = JSON.stringify(data);
|
|
119
|
-
localStorage?.setItem(impersonatorAuthenticationDataStorageKey, json);
|
|
120
|
-
}
|
|
120
|
+
this.writeToStorage(impersonatorAuthenticationDataStorageKey, data);
|
|
121
121
|
}
|
|
122
122
|
/**
|
|
123
123
|
* Get current token or throw if not available
|
|
@@ -142,7 +142,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
142
142
|
}
|
|
143
143
|
/** Whether a valid token is available (not undefined and not expired) */
|
|
144
144
|
get hasValidToken() {
|
|
145
|
-
return (this.token()?.exp ?? 0) >
|
|
145
|
+
return (this.token()?.exp ?? 0) > this.estimatedServerTimestampSeconds();
|
|
146
146
|
}
|
|
147
147
|
constructor(initialAuthenticationData) {
|
|
148
148
|
if (isUndefined(this.authenticationData)) {
|
|
@@ -195,26 +195,31 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
195
195
|
if (isDefined(data)) {
|
|
196
196
|
this.setAdditionalData(data);
|
|
197
197
|
}
|
|
198
|
-
const token = await
|
|
198
|
+
const [token] = await Promise.all([
|
|
199
|
+
this.client.login({ subject, secret, data: this.authenticationData }),
|
|
200
|
+
this.syncClock(),
|
|
201
|
+
]);
|
|
199
202
|
this.setNewToken(token);
|
|
200
203
|
}
|
|
201
204
|
/**
|
|
202
|
-
* Logout
|
|
205
|
+
* Logout from the current session.
|
|
206
|
+
* This will attempt to end the session on the server and then clear local credentials.
|
|
203
207
|
*/
|
|
204
208
|
async logout() {
|
|
205
209
|
try {
|
|
206
210
|
await Promise.race([
|
|
207
211
|
this.client.endSession(),
|
|
208
|
-
timeout(
|
|
212
|
+
timeout(logoutTimeout),
|
|
209
213
|
]).catch((error) => this.logger.error(error));
|
|
210
214
|
}
|
|
211
215
|
finally {
|
|
216
|
+
// Always clear the local token, even if the server call fails.
|
|
212
217
|
this.setNewToken(undefined);
|
|
213
218
|
this.loggedOutBus.publishAndForget();
|
|
214
219
|
}
|
|
215
220
|
}
|
|
216
221
|
/**
|
|
217
|
-
* Force
|
|
222
|
+
* Force an immediate refresh of the token.
|
|
218
223
|
* @param data Additional authentication data
|
|
219
224
|
*/
|
|
220
225
|
requestRefresh(data) {
|
|
@@ -224,7 +229,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
224
229
|
this.forceRefreshToken.set();
|
|
225
230
|
}
|
|
226
231
|
/**
|
|
227
|
-
* Refresh the token
|
|
232
|
+
* Refresh the token.
|
|
228
233
|
* @param data Additional authentication data
|
|
229
234
|
*/
|
|
230
235
|
async refresh(data) {
|
|
@@ -232,7 +237,10 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
232
237
|
this.setAdditionalData(data);
|
|
233
238
|
}
|
|
234
239
|
try {
|
|
235
|
-
const token = await
|
|
240
|
+
const [token] = await Promise.all([
|
|
241
|
+
this.client.refresh({ data: this.authenticationData }),
|
|
242
|
+
this.syncClock(),
|
|
243
|
+
]);
|
|
236
244
|
this.setNewToken(token);
|
|
237
245
|
}
|
|
238
246
|
catch (error) {
|
|
@@ -241,12 +249,15 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
241
249
|
}
|
|
242
250
|
}
|
|
243
251
|
/**
|
|
244
|
-
* Impersonate a subject
|
|
252
|
+
* Impersonate a subject.
|
|
245
253
|
* @param subject The subject to impersonate
|
|
246
|
-
* @param data Additional authentication data
|
|
254
|
+
* @param data Additional authentication data for the impersonated session
|
|
247
255
|
*/
|
|
248
256
|
async impersonate(subject, data) {
|
|
249
|
-
|
|
257
|
+
if (this.impersonated()) {
|
|
258
|
+
throw new Error('Already impersonating. Please unimpersonate first.');
|
|
259
|
+
}
|
|
260
|
+
await this.lock.use(lockTimeout, true, async () => {
|
|
250
261
|
this.impersonatorAuthenticationData = this.authenticationData;
|
|
251
262
|
this.authenticationData = data;
|
|
252
263
|
try {
|
|
@@ -254,17 +265,20 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
254
265
|
this.setNewToken(token);
|
|
255
266
|
}
|
|
256
267
|
catch (error) {
|
|
268
|
+
// Rollback authentication data on failure
|
|
269
|
+
this.authenticationData = this.impersonatorAuthenticationData;
|
|
270
|
+
this.impersonatorAuthenticationData = undefined;
|
|
257
271
|
await this.handleRefreshError(error);
|
|
258
272
|
throw error;
|
|
259
273
|
}
|
|
260
274
|
});
|
|
261
275
|
}
|
|
262
276
|
/**
|
|
263
|
-
*
|
|
277
|
+
* End impersonation and return to the original user session.
|
|
264
278
|
* @param data Additional authentication data. If not provided, the data from before impersonation is used.
|
|
265
279
|
*/
|
|
266
280
|
async unimpersonate(data) {
|
|
267
|
-
await this.lock.use(
|
|
281
|
+
await this.lock.use(lockTimeout, true, async () => {
|
|
268
282
|
const newData = data ?? this.impersonatorAuthenticationData;
|
|
269
283
|
try {
|
|
270
284
|
const token = await this.client.unimpersonate({ data: newData });
|
|
@@ -279,7 +293,16 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
279
293
|
});
|
|
280
294
|
}
|
|
281
295
|
/**
|
|
282
|
-
*
|
|
296
|
+
* Change the secret for a subject.
|
|
297
|
+
* @param subject The subject to change the secret for
|
|
298
|
+
* @param currentSecret The current secret
|
|
299
|
+
* @param newSecret The new secret
|
|
300
|
+
*/
|
|
301
|
+
async changeSecret(subject, currentSecret, newSecret) {
|
|
302
|
+
await this.client.changeSecret({ subject, currentSecret, newSecret });
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Initialize a secret reset.
|
|
283
306
|
* @param subject The subject to reset the secret for
|
|
284
307
|
* @param data Additional data for secret reset
|
|
285
308
|
*/
|
|
@@ -287,7 +310,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
287
310
|
await this.client.initSecretReset({ subject, data });
|
|
288
311
|
}
|
|
289
312
|
/**
|
|
290
|
-
* Reset a secret
|
|
313
|
+
* Reset a secret using a reset token.
|
|
291
314
|
* @param token The secret reset token
|
|
292
315
|
* @param newSecret The new secret
|
|
293
316
|
*/
|
|
@@ -295,39 +318,30 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
295
318
|
await this.client.resetSecret({ token, newSecret });
|
|
296
319
|
}
|
|
297
320
|
/**
|
|
298
|
-
* Check a secret for requirements
|
|
321
|
+
* Check a secret for requirements.
|
|
299
322
|
* @param secret The secret to check
|
|
300
323
|
* @returns The result of the check
|
|
301
324
|
*/
|
|
302
325
|
async checkSecret(secret) {
|
|
303
326
|
return await this.client.checkSecret({ secret });
|
|
304
327
|
}
|
|
305
|
-
saveToken(token) {
|
|
306
|
-
if (isNullOrUndefined(token)) {
|
|
307
|
-
localStorage?.removeItem(tokenStorageKey);
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
const serialized = JSON.stringify(token);
|
|
311
|
-
localStorage?.setItem(tokenStorageKey, serialized);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
loadToken() {
|
|
315
|
-
const existingSerializedToken = localStorage?.getItem(tokenStorageKey);
|
|
316
|
-
const token = isString(existingSerializedToken)
|
|
317
|
-
? JSON.parse(existingSerializedToken)
|
|
318
|
-
: undefined;
|
|
319
|
-
this.token.set(token);
|
|
320
|
-
}
|
|
321
328
|
setNewToken(token) {
|
|
322
329
|
this.saveToken(token);
|
|
323
330
|
this.token.set(token);
|
|
324
331
|
this.tokenUpdateBus.publishAndForget(token);
|
|
325
332
|
}
|
|
326
333
|
async refreshLoop() {
|
|
334
|
+
if (this.isLoggedIn()) {
|
|
335
|
+
await this.syncClock();
|
|
336
|
+
}
|
|
327
337
|
while (this.disposeToken.isUnset) {
|
|
328
338
|
try {
|
|
339
|
+
// Use a non-blocking lock to ensure only one tab/instance runs the refresh logic at a time.
|
|
329
340
|
await this.lock.use(0, false, async () => await this.refreshLoopIteration());
|
|
330
|
-
|
|
341
|
+
// Calculate delay until the next refresh check.
|
|
342
|
+
// The buffer ensures we refresh *before* the token actually expires.
|
|
343
|
+
const delay = ((this.token()?.exp ?? 0) - this.estimatedServerTimestampSeconds() - refreshBufferSeconds) * millisecondsPerSecond;
|
|
344
|
+
await firstValueFrom(race([timer(delay), this.disposeToken, this.forceRefreshToken]));
|
|
331
345
|
}
|
|
332
346
|
catch {
|
|
333
347
|
await firstValueFrom(race([timer(5000), this.disposeToken, this.forceRefreshToken]));
|
|
@@ -335,22 +349,71 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
335
349
|
}
|
|
336
350
|
}
|
|
337
351
|
async refreshLoopIteration() {
|
|
352
|
+
// Wait for a token to be available or for the service to be disposed.
|
|
338
353
|
const token = await firstValueFrom(race([this.definedToken$, this.disposeToken]));
|
|
339
354
|
if (isUndefined(token)) {
|
|
340
355
|
return;
|
|
341
356
|
}
|
|
342
|
-
|
|
357
|
+
const needsRefresh = this.estimatedServerTimestampSeconds() >= (token.exp - refreshBufferSeconds);
|
|
358
|
+
if (this.forceRefreshToken.isSet || needsRefresh) {
|
|
343
359
|
this.forceRefreshToken.unset();
|
|
344
|
-
await this.refresh();
|
|
360
|
+
await this.refresh(); // Errors are caught by the outer loop
|
|
345
361
|
}
|
|
346
362
|
}
|
|
347
363
|
async handleRefreshError(error) {
|
|
348
364
|
this.logger.error(error);
|
|
349
365
|
this.errorSubject.next(error);
|
|
350
|
-
if ((
|
|
366
|
+
if (unrecoverableErrors.some((errorType) => error instanceof errorType)) {
|
|
351
367
|
await this.logout();
|
|
352
368
|
}
|
|
353
369
|
}
|
|
370
|
+
estimatedServerTimestampSeconds() {
|
|
371
|
+
return currentTimestampSeconds() + this.clockOffset;
|
|
372
|
+
}
|
|
373
|
+
async syncClock() {
|
|
374
|
+
try {
|
|
375
|
+
const serverTimestamp = await this.client.timestamp();
|
|
376
|
+
this.clockOffset = serverTimestamp - currentTimestampSeconds();
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
this.logger.warn(`Failed to synchronize clock with server: ${formatError(error)}`);
|
|
380
|
+
this.clockOffset = 0;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
saveToken(token) {
|
|
384
|
+
this.writeToStorage(tokenStorageKey, token);
|
|
385
|
+
}
|
|
386
|
+
loadToken() {
|
|
387
|
+
const token = this.readFromStorage(tokenStorageKey);
|
|
388
|
+
this.token.set(token);
|
|
389
|
+
}
|
|
390
|
+
readFromStorage(key) {
|
|
391
|
+
try {
|
|
392
|
+
const serialized = localStorage?.getItem(key);
|
|
393
|
+
if (isNullOrUndefined(serialized)) {
|
|
394
|
+
return undefined;
|
|
395
|
+
}
|
|
396
|
+
return JSON.parse(serialized);
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
this.logger.warn(`Failed to read and parse from localStorage key "${key}": ${formatError(error)}`);
|
|
400
|
+
return undefined;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
writeToStorage(key, value) {
|
|
404
|
+
try {
|
|
405
|
+
if (isUndefined(value)) {
|
|
406
|
+
localStorage?.removeItem(key);
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
const serialized = JSON.stringify(value);
|
|
410
|
+
localStorage?.setItem(key, serialized);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
this.logger.warn(`Failed to write to localStorage key "${key}": ${formatError(error)}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
354
417
|
};
|
|
355
418
|
AuthenticationClientService = __decorate([
|
|
356
419
|
Singleton(),
|
|
@@ -69,7 +69,7 @@ export declare class AuthenticationApiController<AdditionalTokenPayload extends
|
|
|
69
69
|
checkSecret({ parameters }: ApiRequestContext<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'checkSecret'>): Promise<ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'checkSecret'>>;
|
|
70
70
|
/**
|
|
71
71
|
* Get the current server timestamp.
|
|
72
|
-
* @returns The current server timestamp.
|
|
72
|
+
* @returns The current server timestamp in seconds.
|
|
73
73
|
*/
|
|
74
74
|
timestamp(): ApiServerResult<AuthenticationApiDefinition<AdditionalTokenPayload, AuthenticationData, AdditionalInitSecretResetData>, 'timestamp'>;
|
|
75
75
|
protected getTokenResponse({ token, jsonToken, refreshToken, omitImpersonatorRefreshToken, impersonatorRefreshToken, impersonatorRefreshTokenExpiration }: TokenResult<AdditionalTokenPayload>): HttpServerResponse;
|
|
@@ -9,7 +9,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
9
9
|
};
|
|
10
10
|
import { apiController } from '../../api/server/index.js';
|
|
11
11
|
import { HttpServerResponse } from '../../http/server/index.js';
|
|
12
|
-
import {
|
|
12
|
+
import { currentTimestampSeconds } from '../../utils/date-time.js';
|
|
13
13
|
import { assertDefinedPass, isDefined } from '../../utils/type-guards.js';
|
|
14
14
|
import { authenticationApiDefinition, getAuthenticationApiDefinition } from '../authentication.api.js';
|
|
15
15
|
import { AuthenticationService } from './authentication.service.js';
|
|
@@ -138,10 +138,10 @@ let AuthenticationApiController = class AuthenticationApiController {
|
|
|
138
138
|
}
|
|
139
139
|
/**
|
|
140
140
|
* Get the current server timestamp.
|
|
141
|
-
* @returns The current server timestamp.
|
|
141
|
+
* @returns The current server timestamp in seconds.
|
|
142
142
|
*/
|
|
143
143
|
timestamp() {
|
|
144
|
-
return
|
|
144
|
+
return currentTimestampSeconds();
|
|
145
145
|
}
|
|
146
146
|
getTokenResponse({ token, jsonToken, refreshToken, omitImpersonatorRefreshToken, impersonatorRefreshToken, impersonatorRefreshTokenExpiration }) {
|
|
147
147
|
const result = jsonToken.payload;
|
package/core.js
CHANGED
|
@@ -5,7 +5,7 @@ import { LogLevel, Logger } from './logger/index.js';
|
|
|
5
5
|
import { LOG_LEVEL } from './logger/tokens.js';
|
|
6
6
|
import { initializeSignals, setProcessShutdownLogger } from './process-shutdown.js';
|
|
7
7
|
import { timeout } from './utils/timing.js';
|
|
8
|
-
import { assertDefinedPass, isDefined
|
|
8
|
+
import { assertDefinedPass, isDefined } from './utils/type-guards.js';
|
|
9
9
|
if (globalThis.tstdlLoaded == true) {
|
|
10
10
|
console.error(new Error('tstdl seems to be loaded multiple times. This is likely an error as some modules won\'t work as intended this way.'));
|
|
11
11
|
}
|
|
@@ -17,10 +17,7 @@ let _isDevMode = true;
|
|
|
17
17
|
* @deprecated Usage of `getGlobalInjector` should be avoided. Use `Application` scoped injector instead.
|
|
18
18
|
*/
|
|
19
19
|
export function getGlobalInjector() {
|
|
20
|
-
|
|
21
|
-
globalInjector = new Injector('GlobalInjector');
|
|
22
|
-
}
|
|
23
|
-
return globalInjector;
|
|
20
|
+
return globalInjector ??= new Injector('GlobalInjector');
|
|
24
21
|
}
|
|
25
22
|
export function isDevMode() {
|
|
26
23
|
return _isDevMode;
|