@tstdl/base 0.92.158 → 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.
|
@@ -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,53 +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>;
|
|
142
|
+
/**
|
|
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
|
+
*/
|
|
140
148
|
changeSecret(subject: string, currentSecret: string, newSecret: string): Promise<void>;
|
|
141
149
|
/**
|
|
142
|
-
* Initialize a secret reset
|
|
150
|
+
* Initialize a secret reset.
|
|
143
151
|
* @param subject The subject to reset the secret for
|
|
144
152
|
* @param data Additional data for secret reset
|
|
145
153
|
*/
|
|
146
154
|
initResetSecret(subject: string, data: AdditionalInitSecretResetData): Promise<void>;
|
|
147
155
|
/**
|
|
148
|
-
* Reset a secret
|
|
156
|
+
* Reset a secret using a reset token.
|
|
149
157
|
* @param token The secret reset token
|
|
150
158
|
* @param newSecret The new secret
|
|
151
159
|
*/
|
|
152
160
|
resetSecret(token: string, newSecret: string): Promise<void>;
|
|
153
161
|
/**
|
|
154
|
-
* Check a secret for requirements
|
|
162
|
+
* Check a secret for requirements.
|
|
155
163
|
* @param secret The secret to check
|
|
156
164
|
* @returns The result of the check
|
|
157
165
|
*/
|
|
158
166
|
checkSecret(secret: string): Promise<SecretCheckResult>;
|
|
159
|
-
private saveToken;
|
|
160
|
-
private loadToken;
|
|
161
167
|
private setNewToken;
|
|
162
168
|
private refreshLoop;
|
|
163
169
|
private refreshLoopIteration;
|
|
164
170
|
private handleRefreshError;
|
|
171
|
+
private estimatedServerTimestampSeconds;
|
|
172
|
+
private syncClock;
|
|
173
|
+
private saveToken;
|
|
174
|
+
private loadToken;
|
|
175
|
+
private readFromStorage;
|
|
176
|
+
private writeToStorage;
|
|
165
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 });
|
|
@@ -278,11 +292,17 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
278
292
|
}
|
|
279
293
|
});
|
|
280
294
|
}
|
|
295
|
+
/**
|
|
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
|
+
*/
|
|
281
301
|
async changeSecret(subject, currentSecret, newSecret) {
|
|
282
302
|
await this.client.changeSecret({ subject, currentSecret, newSecret });
|
|
283
303
|
}
|
|
284
304
|
/**
|
|
285
|
-
* Initialize a secret reset
|
|
305
|
+
* Initialize a secret reset.
|
|
286
306
|
* @param subject The subject to reset the secret for
|
|
287
307
|
* @param data Additional data for secret reset
|
|
288
308
|
*/
|
|
@@ -290,7 +310,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
290
310
|
await this.client.initSecretReset({ subject, data });
|
|
291
311
|
}
|
|
292
312
|
/**
|
|
293
|
-
* Reset a secret
|
|
313
|
+
* Reset a secret using a reset token.
|
|
294
314
|
* @param token The secret reset token
|
|
295
315
|
* @param newSecret The new secret
|
|
296
316
|
*/
|
|
@@ -298,39 +318,30 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
298
318
|
await this.client.resetSecret({ token, newSecret });
|
|
299
319
|
}
|
|
300
320
|
/**
|
|
301
|
-
* Check a secret for requirements
|
|
321
|
+
* Check a secret for requirements.
|
|
302
322
|
* @param secret The secret to check
|
|
303
323
|
* @returns The result of the check
|
|
304
324
|
*/
|
|
305
325
|
async checkSecret(secret) {
|
|
306
326
|
return await this.client.checkSecret({ secret });
|
|
307
327
|
}
|
|
308
|
-
saveToken(token) {
|
|
309
|
-
if (isNullOrUndefined(token)) {
|
|
310
|
-
localStorage?.removeItem(tokenStorageKey);
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
const serialized = JSON.stringify(token);
|
|
314
|
-
localStorage?.setItem(tokenStorageKey, serialized);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
loadToken() {
|
|
318
|
-
const existingSerializedToken = localStorage?.getItem(tokenStorageKey);
|
|
319
|
-
const token = isString(existingSerializedToken)
|
|
320
|
-
? JSON.parse(existingSerializedToken)
|
|
321
|
-
: undefined;
|
|
322
|
-
this.token.set(token);
|
|
323
|
-
}
|
|
324
328
|
setNewToken(token) {
|
|
325
329
|
this.saveToken(token);
|
|
326
330
|
this.token.set(token);
|
|
327
331
|
this.tokenUpdateBus.publishAndForget(token);
|
|
328
332
|
}
|
|
329
333
|
async refreshLoop() {
|
|
334
|
+
if (this.isLoggedIn()) {
|
|
335
|
+
await this.syncClock();
|
|
336
|
+
}
|
|
330
337
|
while (this.disposeToken.isUnset) {
|
|
331
338
|
try {
|
|
339
|
+
// Use a non-blocking lock to ensure only one tab/instance runs the refresh logic at a time.
|
|
332
340
|
await this.lock.use(0, false, async () => await this.refreshLoopIteration());
|
|
333
|
-
|
|
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]));
|
|
334
345
|
}
|
|
335
346
|
catch {
|
|
336
347
|
await firstValueFrom(race([timer(5000), this.disposeToken, this.forceRefreshToken]));
|
|
@@ -338,22 +349,71 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
338
349
|
}
|
|
339
350
|
}
|
|
340
351
|
async refreshLoopIteration() {
|
|
352
|
+
// Wait for a token to be available or for the service to be disposed.
|
|
341
353
|
const token = await firstValueFrom(race([this.definedToken$, this.disposeToken]));
|
|
342
354
|
if (isUndefined(token)) {
|
|
343
355
|
return;
|
|
344
356
|
}
|
|
345
|
-
|
|
357
|
+
const needsRefresh = this.estimatedServerTimestampSeconds() >= (token.exp - refreshBufferSeconds);
|
|
358
|
+
if (this.forceRefreshToken.isSet || needsRefresh) {
|
|
346
359
|
this.forceRefreshToken.unset();
|
|
347
|
-
await this.refresh();
|
|
360
|
+
await this.refresh(); // Errors are caught by the outer loop
|
|
348
361
|
}
|
|
349
362
|
}
|
|
350
363
|
async handleRefreshError(error) {
|
|
351
364
|
this.logger.error(error);
|
|
352
365
|
this.errorSubject.next(error);
|
|
353
|
-
if ((
|
|
366
|
+
if (unrecoverableErrors.some((errorType) => error instanceof errorType)) {
|
|
354
367
|
await this.logout();
|
|
355
368
|
}
|
|
356
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
|
+
}
|
|
357
417
|
};
|
|
358
418
|
AuthenticationClientService = __decorate([
|
|
359
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;
|