@masterteam/gateway-auth 0.0.1 → 0.0.2
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.
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, Injectable, computed, ChangeDetectionStrategy, Component, signal } from '@angular/core';
|
|
3
|
+
import { HttpClient } from '@angular/common/http';
|
|
4
|
+
import { Router, ActivatedRoute } from '@angular/router';
|
|
5
|
+
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
6
|
+
import { of, EMPTY, isObservable, from } from 'rxjs';
|
|
7
|
+
import { mergeMap, catchError, tap } from 'rxjs/operators';
|
|
8
|
+
import * as i2 from '@angular/common';
|
|
9
|
+
import { CommonModule } from '@angular/common';
|
|
10
|
+
import * as i1 from '@angular/forms';
|
|
11
|
+
import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
12
|
+
import { Button } from '@masterteam/components/button';
|
|
13
|
+
import { TextField } from '@masterteam/components/text-field';
|
|
14
|
+
import { Icon } from '@masterteam/icons';
|
|
15
|
+
|
|
1
16
|
const GATEWAY_AUTH_DEVICE_TOKEN = 'web-app';
|
|
2
17
|
const GATEWAY_AUTH_ENDPOINTS = {
|
|
3
18
|
login: 'auth/login',
|
|
@@ -140,9 +155,770 @@ class GatewaySsoSession {
|
|
|
140
155
|
}
|
|
141
156
|
}
|
|
142
157
|
|
|
158
|
+
const GATEWAY_AUTH_OPTIONS = new InjectionToken('GATEWAY_AUTH_OPTIONS', {
|
|
159
|
+
factory: () => ({
|
|
160
|
+
getGatewayApiBaseUrl: () => null,
|
|
161
|
+
deviceToken: 'web-app',
|
|
162
|
+
platform: 'web',
|
|
163
|
+
loginRoute: '/auth/login',
|
|
164
|
+
mfaRoute: '/auth/mfa',
|
|
165
|
+
ssoCallbackPath: '/auth/sso/callback',
|
|
166
|
+
defaultAuthenticatedRoute: '/',
|
|
167
|
+
preserveSsoProvidersOnLogout: true,
|
|
168
|
+
}),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
const AUTH_STATE_DEFAULTS = {
|
|
172
|
+
user: null,
|
|
173
|
+
token: null,
|
|
174
|
+
refreshToken: null,
|
|
175
|
+
accessTokenExpiresAt: null,
|
|
176
|
+
refreshTokenExpiresAt: null,
|
|
177
|
+
loading: false,
|
|
178
|
+
mfaResendLoading: false,
|
|
179
|
+
ssoLoading: false,
|
|
180
|
+
ssoCallbackLoading: false,
|
|
181
|
+
error: null,
|
|
182
|
+
twoFactorRequired: false,
|
|
183
|
+
pendingMfa: null,
|
|
184
|
+
ssoProviders: [],
|
|
185
|
+
};
|
|
186
|
+
function sanitizePersistedAuthState(obj) {
|
|
187
|
+
return {
|
|
188
|
+
...AUTH_STATE_DEFAULTS,
|
|
189
|
+
...(obj ?? {}),
|
|
190
|
+
loading: false,
|
|
191
|
+
mfaResendLoading: false,
|
|
192
|
+
ssoLoading: false,
|
|
193
|
+
ssoCallbackLoading: false,
|
|
194
|
+
error: null,
|
|
195
|
+
twoFactorRequired: false,
|
|
196
|
+
pendingMfa: null,
|
|
197
|
+
ssoProviders: [],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
class Login {
|
|
202
|
+
payload;
|
|
203
|
+
static type = '[Auth] Login';
|
|
204
|
+
constructor(payload) {
|
|
205
|
+
this.payload = payload;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
class VerifyMfa {
|
|
209
|
+
code;
|
|
210
|
+
static type = '[Auth] Verify MFA';
|
|
211
|
+
constructor(code) {
|
|
212
|
+
this.code = code;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
class ResendMfa {
|
|
216
|
+
static type = '[Auth] Resend MFA';
|
|
217
|
+
}
|
|
218
|
+
class LoadSsoProviders {
|
|
219
|
+
static type = '[Auth] Load SSO Providers';
|
|
220
|
+
}
|
|
221
|
+
class StartSso {
|
|
222
|
+
provider;
|
|
223
|
+
static type = '[Auth] Start SSO';
|
|
224
|
+
constructor(provider) {
|
|
225
|
+
this.provider = provider;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
class ExchangeSsoCode {
|
|
229
|
+
code;
|
|
230
|
+
state;
|
|
231
|
+
static type = '[Auth] Exchange SSO Code';
|
|
232
|
+
constructor(code, state) {
|
|
233
|
+
this.code = code;
|
|
234
|
+
this.state = state;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
class LoginSuccess {
|
|
238
|
+
session;
|
|
239
|
+
static type = '[Auth] Login Success';
|
|
240
|
+
constructor(session) {
|
|
241
|
+
this.session = session;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
class LoginFailure {
|
|
245
|
+
error;
|
|
246
|
+
static type = '[Auth] Login Failure';
|
|
247
|
+
constructor(error) {
|
|
248
|
+
this.error = error;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
class Logout {
|
|
252
|
+
remote;
|
|
253
|
+
static type = '[Auth] Logout';
|
|
254
|
+
constructor(remote = false) {
|
|
255
|
+
this.remote = remote;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
class UpdateUserData {
|
|
259
|
+
user;
|
|
260
|
+
static type = '[Auth] Update User Data';
|
|
261
|
+
constructor(user) {
|
|
262
|
+
this.user = user;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
class UpdateTokens {
|
|
266
|
+
tokens;
|
|
267
|
+
static type = '[Auth] Update Tokens';
|
|
268
|
+
constructor(tokens) {
|
|
269
|
+
this.tokens = tokens;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
class ClearError {
|
|
273
|
+
static type = '[Auth] Clear Error';
|
|
274
|
+
}
|
|
275
|
+
class ClearPendingMfa {
|
|
276
|
+
static type = '[Auth] Clear Pending MFA';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
280
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
281
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
282
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
283
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
284
|
+
};
|
|
285
|
+
let GatewayAuthState = class GatewayAuthState {
|
|
286
|
+
http = inject(HttpClient);
|
|
287
|
+
options = inject(GATEWAY_AUTH_OPTIONS);
|
|
288
|
+
router = inject(Router);
|
|
289
|
+
ssoSession = new GatewaySsoSession();
|
|
290
|
+
static user(state) {
|
|
291
|
+
return state.user;
|
|
292
|
+
}
|
|
293
|
+
static loading(state) {
|
|
294
|
+
return state.loading;
|
|
295
|
+
}
|
|
296
|
+
static mfaResendLoading(state) {
|
|
297
|
+
return state.mfaResendLoading;
|
|
298
|
+
}
|
|
299
|
+
static ssoLoading(state) {
|
|
300
|
+
return state.ssoLoading;
|
|
301
|
+
}
|
|
302
|
+
static ssoCallbackLoading(state) {
|
|
303
|
+
return state.ssoCallbackLoading;
|
|
304
|
+
}
|
|
305
|
+
static error(state) {
|
|
306
|
+
return state.error;
|
|
307
|
+
}
|
|
308
|
+
static token(state) {
|
|
309
|
+
return state.token;
|
|
310
|
+
}
|
|
311
|
+
static refreshToken(state) {
|
|
312
|
+
return state.refreshToken;
|
|
313
|
+
}
|
|
314
|
+
static accessTokenExpiresAt(state) {
|
|
315
|
+
return state.accessTokenExpiresAt;
|
|
316
|
+
}
|
|
317
|
+
static refreshTokenExpiresAt(state) {
|
|
318
|
+
return state.refreshTokenExpiresAt;
|
|
319
|
+
}
|
|
320
|
+
static twoFactorRequired(state) {
|
|
321
|
+
return state.twoFactorRequired;
|
|
322
|
+
}
|
|
323
|
+
static pendingMfa(state) {
|
|
324
|
+
return state.pendingMfa;
|
|
325
|
+
}
|
|
326
|
+
static ssoProviders(state) {
|
|
327
|
+
return state.ssoProviders;
|
|
328
|
+
}
|
|
329
|
+
static isAdmin(state) {
|
|
330
|
+
return state.user?.isAdmin || false;
|
|
331
|
+
}
|
|
332
|
+
static userDetails(state) {
|
|
333
|
+
return state.user?.user || null;
|
|
334
|
+
}
|
|
335
|
+
login(ctx, action) {
|
|
336
|
+
ctx.patchState({
|
|
337
|
+
loading: true,
|
|
338
|
+
error: null,
|
|
339
|
+
pendingMfa: null,
|
|
340
|
+
twoFactorRequired: false,
|
|
341
|
+
});
|
|
342
|
+
return this.http
|
|
343
|
+
.post(this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.login), {
|
|
344
|
+
userName: action.payload.userName,
|
|
345
|
+
password: action.payload.password,
|
|
346
|
+
isEncrypted: action.payload.isEncrypted ?? false,
|
|
347
|
+
deviceToken: action.payload.deviceToken || this.deviceToken,
|
|
348
|
+
recaptchaToken: action.payload.recaptchaToken,
|
|
349
|
+
recaptchaAction: action.payload.recaptchaAction,
|
|
350
|
+
})
|
|
351
|
+
.pipe(mergeMap((response) => this.handleLoginResponse(ctx, response.data)), catchError((error) => {
|
|
352
|
+
ctx.dispatch(new LoginFailure(getGatewayErrorMessage(error, 'Login failed')));
|
|
353
|
+
return of(null);
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
verifyMfa(ctx, action) {
|
|
357
|
+
const pendingMfa = ctx.getState().pendingMfa;
|
|
358
|
+
if (!pendingMfa) {
|
|
359
|
+
ctx.dispatch(new LoginFailure('The verification session expired.'));
|
|
360
|
+
this.navigateToLogin();
|
|
361
|
+
return EMPTY;
|
|
362
|
+
}
|
|
363
|
+
ctx.patchState({ loading: true, error: null });
|
|
364
|
+
return this.http
|
|
365
|
+
.post(this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.verifyMfa), {
|
|
366
|
+
userId: pendingMfa.userId,
|
|
367
|
+
tempSessionId: pendingMfa.tempSessionId,
|
|
368
|
+
code: action.code,
|
|
369
|
+
deviceToken: this.deviceToken,
|
|
370
|
+
})
|
|
371
|
+
.pipe(mergeMap((response) => this.handleLoginResponse(ctx, response.data)), catchError((error) => {
|
|
372
|
+
const message = getGatewayErrorMessage(error, 'Invalid verification code');
|
|
373
|
+
const shouldClearMfa = error?.status === 403;
|
|
374
|
+
ctx.patchState({
|
|
375
|
+
loading: false,
|
|
376
|
+
error: message,
|
|
377
|
+
pendingMfa: shouldClearMfa ? null : pendingMfa,
|
|
378
|
+
twoFactorRequired: !shouldClearMfa,
|
|
379
|
+
});
|
|
380
|
+
if (shouldClearMfa) {
|
|
381
|
+
this.navigateToLogin();
|
|
382
|
+
}
|
|
383
|
+
return of(null);
|
|
384
|
+
}));
|
|
385
|
+
}
|
|
386
|
+
resendMfa(ctx) {
|
|
387
|
+
const pendingMfa = ctx.getState().pendingMfa;
|
|
388
|
+
if (!pendingMfa) {
|
|
389
|
+
ctx.dispatch(new LoginFailure('The verification session expired.'));
|
|
390
|
+
this.navigateToLogin();
|
|
391
|
+
return EMPTY;
|
|
392
|
+
}
|
|
393
|
+
ctx.patchState({ mfaResendLoading: true, error: null });
|
|
394
|
+
return this.http
|
|
395
|
+
.post(this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.resendMfa), {
|
|
396
|
+
userId: pendingMfa.userId,
|
|
397
|
+
tempSessionId: pendingMfa.tempSessionId,
|
|
398
|
+
})
|
|
399
|
+
.pipe(tap((response) => {
|
|
400
|
+
ctx.patchState({
|
|
401
|
+
pendingMfa: response.data,
|
|
402
|
+
twoFactorRequired: true,
|
|
403
|
+
mfaResendLoading: false,
|
|
404
|
+
error: null,
|
|
405
|
+
});
|
|
406
|
+
}), catchError((error) => {
|
|
407
|
+
ctx.patchState({
|
|
408
|
+
mfaResendLoading: false,
|
|
409
|
+
error: getGatewayErrorMessage(error, 'Failed to resend code'),
|
|
410
|
+
});
|
|
411
|
+
return of(null);
|
|
412
|
+
}));
|
|
413
|
+
}
|
|
414
|
+
loadSsoProviders(ctx) {
|
|
415
|
+
ctx.patchState({ ssoLoading: true });
|
|
416
|
+
return this.http
|
|
417
|
+
.get(this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.ssoProviders), {
|
|
418
|
+
params: { platform: this.options.platform ?? 'web' },
|
|
419
|
+
})
|
|
420
|
+
.pipe(tap((response) => {
|
|
421
|
+
ctx.patchState({
|
|
422
|
+
ssoProviders: (response.data?.providers ?? []).filter((provider) => provider.enabled),
|
|
423
|
+
ssoLoading: false,
|
|
424
|
+
});
|
|
425
|
+
}), catchError(() => {
|
|
426
|
+
ctx.patchState({
|
|
427
|
+
ssoProviders: [],
|
|
428
|
+
ssoLoading: false,
|
|
429
|
+
});
|
|
430
|
+
return of(null);
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
433
|
+
startSso(ctx, action) {
|
|
434
|
+
if (action.provider.flow !== 'browser_redirect') {
|
|
435
|
+
ctx.patchState({
|
|
436
|
+
error: 'This SSO provider is not available for browser sign-in.',
|
|
437
|
+
});
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
const gatewayApiBaseUrl = this.options.getGatewayApiBaseUrl();
|
|
441
|
+
if (!gatewayApiBaseUrl || typeof window === 'undefined') {
|
|
442
|
+
ctx.patchState({ error: 'SSO is not configured.' });
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
const clientState = this.ssoSession.createAndStoreState();
|
|
446
|
+
const callbackPath = this.options.ssoCallbackPath ?? '/auth/sso/callback';
|
|
447
|
+
const startUrl = buildSsoStartUrl({
|
|
448
|
+
gatewayApiBaseUrl,
|
|
449
|
+
provider: action.provider,
|
|
450
|
+
returnUrl: `${window.location.origin}${callbackPath}`,
|
|
451
|
+
clientState,
|
|
452
|
+
platform: this.options.platform ?? 'web',
|
|
453
|
+
});
|
|
454
|
+
window.location.assign(startUrl);
|
|
455
|
+
}
|
|
456
|
+
exchangeSsoCode(ctx, action) {
|
|
457
|
+
ctx.patchState({ ssoCallbackLoading: true, error: null });
|
|
458
|
+
return this.http
|
|
459
|
+
.post(this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.ssoExchange), {
|
|
460
|
+
code: action.code,
|
|
461
|
+
state: action.state,
|
|
462
|
+
deviceToken: this.deviceToken,
|
|
463
|
+
})
|
|
464
|
+
.pipe(mergeMap((response) => this.handleLoginResponse(ctx, response.data)), catchError((error) => {
|
|
465
|
+
ctx.patchState({
|
|
466
|
+
ssoCallbackLoading: false,
|
|
467
|
+
error: getGatewayErrorMessage(error, 'SSO sign-in failed. Please try again.'),
|
|
468
|
+
});
|
|
469
|
+
return of(null);
|
|
470
|
+
}));
|
|
471
|
+
}
|
|
472
|
+
loginSuccess(ctx, action) {
|
|
473
|
+
return this.handleLoginResponse(ctx, action.session);
|
|
474
|
+
}
|
|
475
|
+
loginFailure(ctx, action) {
|
|
476
|
+
ctx.patchState({
|
|
477
|
+
loading: false,
|
|
478
|
+
ssoCallbackLoading: false,
|
|
479
|
+
error: action.error,
|
|
480
|
+
user: null,
|
|
481
|
+
token: null,
|
|
482
|
+
refreshToken: null,
|
|
483
|
+
accessTokenExpiresAt: null,
|
|
484
|
+
refreshTokenExpiresAt: null,
|
|
485
|
+
pendingMfa: null,
|
|
486
|
+
twoFactorRequired: false,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
logout(ctx, action) {
|
|
490
|
+
const { token, refreshToken, ssoProviders } = ctx.getState();
|
|
491
|
+
this.ssoSession.clearAll();
|
|
492
|
+
this.toObservable(this.options.beforeLocalLogout?.(ctx)).subscribe();
|
|
493
|
+
ctx.patchState({
|
|
494
|
+
...AUTH_STATE_DEFAULTS,
|
|
495
|
+
ssoProviders: this.options.preserveSsoProvidersOnLogout
|
|
496
|
+
? ssoProviders
|
|
497
|
+
: [],
|
|
498
|
+
});
|
|
499
|
+
this.navigateToLogin();
|
|
500
|
+
if (action.remote && token) {
|
|
501
|
+
this.http
|
|
502
|
+
.post(this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.logout), {
|
|
503
|
+
refreshToken,
|
|
504
|
+
deviceToken: this.deviceToken,
|
|
505
|
+
}, {
|
|
506
|
+
headers: {
|
|
507
|
+
Authorization: `Bearer ${token}`,
|
|
508
|
+
noMessage: 'true',
|
|
509
|
+
},
|
|
510
|
+
})
|
|
511
|
+
.pipe(catchError(() => EMPTY))
|
|
512
|
+
.subscribe();
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
updateUserData(ctx, action) {
|
|
516
|
+
ctx.patchState({
|
|
517
|
+
user: action.user,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
updateTokens(ctx, action) {
|
|
521
|
+
const tokenData = mapGatewayTokens(action.tokens);
|
|
522
|
+
const state = ctx.getState();
|
|
523
|
+
const updatedUser = state.user
|
|
524
|
+
? {
|
|
525
|
+
...state.user,
|
|
526
|
+
token: tokenData.accessToken ?? state.user.token,
|
|
527
|
+
accessToken: tokenData.accessToken ?? state.user.accessToken,
|
|
528
|
+
refreshToken: tokenData.refreshToken ?? state.user.refreshToken,
|
|
529
|
+
accessTokenExpiresAt: tokenData.accessTokenExpiresAt ?? undefined,
|
|
530
|
+
refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt ?? undefined,
|
|
531
|
+
}
|
|
532
|
+
: state.user;
|
|
533
|
+
ctx.patchState({
|
|
534
|
+
token: tokenData.accessToken,
|
|
535
|
+
refreshToken: tokenData.refreshToken,
|
|
536
|
+
accessTokenExpiresAt: tokenData.accessTokenExpiresAt,
|
|
537
|
+
refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt,
|
|
538
|
+
user: updatedUser,
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
clearError(ctx) {
|
|
542
|
+
ctx.patchState({ error: null });
|
|
543
|
+
}
|
|
544
|
+
clearPendingMfa(ctx) {
|
|
545
|
+
ctx.patchState({ pendingMfa: null, twoFactorRequired: false });
|
|
546
|
+
}
|
|
547
|
+
handleLoginResponse(ctx, session) {
|
|
548
|
+
if (session.requiresTwoFactor) {
|
|
549
|
+
ctx.patchState({
|
|
550
|
+
user: null,
|
|
551
|
+
token: null,
|
|
552
|
+
refreshToken: null,
|
|
553
|
+
accessTokenExpiresAt: null,
|
|
554
|
+
refreshTokenExpiresAt: null,
|
|
555
|
+
pendingMfa: session.twoFactor,
|
|
556
|
+
twoFactorRequired: true,
|
|
557
|
+
loading: false,
|
|
558
|
+
ssoCallbackLoading: false,
|
|
559
|
+
error: null,
|
|
560
|
+
});
|
|
561
|
+
this.router.navigate([this.options.mfaRoute ?? '/auth/mfa'], {
|
|
562
|
+
replaceUrl: true,
|
|
563
|
+
});
|
|
564
|
+
return of(null);
|
|
565
|
+
}
|
|
566
|
+
if (!hasGatewayTokens(session.tokens)) {
|
|
567
|
+
ctx.dispatch(new LoginFailure('Login failed'));
|
|
568
|
+
return of(null);
|
|
569
|
+
}
|
|
570
|
+
const tokenData = mapGatewayTokens(session.tokens);
|
|
571
|
+
const user = mapGatewayUser(session.user, tokenData, session.delegations);
|
|
572
|
+
ctx.patchState({
|
|
573
|
+
user,
|
|
574
|
+
token: tokenData.accessToken,
|
|
575
|
+
refreshToken: tokenData.refreshToken,
|
|
576
|
+
accessTokenExpiresAt: tokenData.accessTokenExpiresAt,
|
|
577
|
+
refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt,
|
|
578
|
+
loading: false,
|
|
579
|
+
ssoCallbackLoading: false,
|
|
580
|
+
error: null,
|
|
581
|
+
pendingMfa: null,
|
|
582
|
+
twoFactorRequired: false,
|
|
583
|
+
});
|
|
584
|
+
return this.toObservable(this.options.afterLogin?.(session, ctx)).pipe(tap(() => {
|
|
585
|
+
this.router.navigateByUrl(this.resolveAuthenticatedRoute(), {
|
|
586
|
+
replaceUrl: true,
|
|
587
|
+
});
|
|
588
|
+
}));
|
|
589
|
+
}
|
|
590
|
+
get deviceToken() {
|
|
591
|
+
return this.options.deviceToken ?? GATEWAY_AUTH_DEVICE_TOKEN;
|
|
592
|
+
}
|
|
593
|
+
gatewayUrl(path) {
|
|
594
|
+
return buildGatewayUrl(this.options.getGatewayApiBaseUrl(), path);
|
|
595
|
+
}
|
|
596
|
+
navigateToLogin() {
|
|
597
|
+
this.router.navigate([this.options.loginRoute ?? '/auth/login'], {
|
|
598
|
+
replaceUrl: true,
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
resolveAuthenticatedRoute() {
|
|
602
|
+
const tree = this.router.parseUrl(this.router.url);
|
|
603
|
+
const returnUrl = this.sanitizeLocalRoute(tree.queryParams['returnUrl']);
|
|
604
|
+
if (returnUrl !== null) {
|
|
605
|
+
return returnUrl;
|
|
606
|
+
}
|
|
607
|
+
const configuredRoute = typeof this.options.defaultAuthenticatedRoute === 'function'
|
|
608
|
+
? this.options.defaultAuthenticatedRoute()
|
|
609
|
+
: this.options.defaultAuthenticatedRoute;
|
|
610
|
+
return this.sanitizeLocalRoute(configuredRoute) ?? '/';
|
|
611
|
+
}
|
|
612
|
+
sanitizeLocalRoute(route) {
|
|
613
|
+
if (!route) {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
if (/^https?:\/\//i.test(route)) {
|
|
617
|
+
return null;
|
|
618
|
+
}
|
|
619
|
+
return route.startsWith('/') ? route : `/${route}`;
|
|
620
|
+
}
|
|
621
|
+
toObservable(result) {
|
|
622
|
+
if (!result) {
|
|
623
|
+
return of(null);
|
|
624
|
+
}
|
|
625
|
+
if (isObservable(result)) {
|
|
626
|
+
return result;
|
|
627
|
+
}
|
|
628
|
+
if (result instanceof Promise) {
|
|
629
|
+
return from(result);
|
|
630
|
+
}
|
|
631
|
+
return of(result);
|
|
632
|
+
}
|
|
633
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayAuthState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
634
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayAuthState });
|
|
635
|
+
};
|
|
636
|
+
__decorate([
|
|
637
|
+
Action(Login)
|
|
638
|
+
], GatewayAuthState.prototype, "login", null);
|
|
639
|
+
__decorate([
|
|
640
|
+
Action(VerifyMfa)
|
|
641
|
+
], GatewayAuthState.prototype, "verifyMfa", null);
|
|
642
|
+
__decorate([
|
|
643
|
+
Action(ResendMfa)
|
|
644
|
+
], GatewayAuthState.prototype, "resendMfa", null);
|
|
645
|
+
__decorate([
|
|
646
|
+
Action(LoadSsoProviders)
|
|
647
|
+
], GatewayAuthState.prototype, "loadSsoProviders", null);
|
|
648
|
+
__decorate([
|
|
649
|
+
Action(StartSso)
|
|
650
|
+
], GatewayAuthState.prototype, "startSso", null);
|
|
651
|
+
__decorate([
|
|
652
|
+
Action(ExchangeSsoCode)
|
|
653
|
+
], GatewayAuthState.prototype, "exchangeSsoCode", null);
|
|
654
|
+
__decorate([
|
|
655
|
+
Action(LoginSuccess)
|
|
656
|
+
], GatewayAuthState.prototype, "loginSuccess", null);
|
|
657
|
+
__decorate([
|
|
658
|
+
Action(LoginFailure)
|
|
659
|
+
], GatewayAuthState.prototype, "loginFailure", null);
|
|
660
|
+
__decorate([
|
|
661
|
+
Action(Logout)
|
|
662
|
+
], GatewayAuthState.prototype, "logout", null);
|
|
663
|
+
__decorate([
|
|
664
|
+
Action(UpdateUserData)
|
|
665
|
+
], GatewayAuthState.prototype, "updateUserData", null);
|
|
666
|
+
__decorate([
|
|
667
|
+
Action(UpdateTokens)
|
|
668
|
+
], GatewayAuthState.prototype, "updateTokens", null);
|
|
669
|
+
__decorate([
|
|
670
|
+
Action(ClearError)
|
|
671
|
+
], GatewayAuthState.prototype, "clearError", null);
|
|
672
|
+
__decorate([
|
|
673
|
+
Action(ClearPendingMfa)
|
|
674
|
+
], GatewayAuthState.prototype, "clearPendingMfa", null);
|
|
675
|
+
__decorate([
|
|
676
|
+
Selector()
|
|
677
|
+
], GatewayAuthState, "user", null);
|
|
678
|
+
__decorate([
|
|
679
|
+
Selector()
|
|
680
|
+
], GatewayAuthState, "loading", null);
|
|
681
|
+
__decorate([
|
|
682
|
+
Selector()
|
|
683
|
+
], GatewayAuthState, "mfaResendLoading", null);
|
|
684
|
+
__decorate([
|
|
685
|
+
Selector()
|
|
686
|
+
], GatewayAuthState, "ssoLoading", null);
|
|
687
|
+
__decorate([
|
|
688
|
+
Selector()
|
|
689
|
+
], GatewayAuthState, "ssoCallbackLoading", null);
|
|
690
|
+
__decorate([
|
|
691
|
+
Selector()
|
|
692
|
+
], GatewayAuthState, "error", null);
|
|
693
|
+
__decorate([
|
|
694
|
+
Selector()
|
|
695
|
+
], GatewayAuthState, "token", null);
|
|
696
|
+
__decorate([
|
|
697
|
+
Selector()
|
|
698
|
+
], GatewayAuthState, "refreshToken", null);
|
|
699
|
+
__decorate([
|
|
700
|
+
Selector()
|
|
701
|
+
], GatewayAuthState, "accessTokenExpiresAt", null);
|
|
702
|
+
__decorate([
|
|
703
|
+
Selector()
|
|
704
|
+
], GatewayAuthState, "refreshTokenExpiresAt", null);
|
|
705
|
+
__decorate([
|
|
706
|
+
Selector()
|
|
707
|
+
], GatewayAuthState, "twoFactorRequired", null);
|
|
708
|
+
__decorate([
|
|
709
|
+
Selector()
|
|
710
|
+
], GatewayAuthState, "pendingMfa", null);
|
|
711
|
+
__decorate([
|
|
712
|
+
Selector()
|
|
713
|
+
], GatewayAuthState, "ssoProviders", null);
|
|
714
|
+
__decorate([
|
|
715
|
+
Selector()
|
|
716
|
+
], GatewayAuthState, "isAdmin", null);
|
|
717
|
+
__decorate([
|
|
718
|
+
Selector()
|
|
719
|
+
], GatewayAuthState, "userDetails", null);
|
|
720
|
+
GatewayAuthState = __decorate([
|
|
721
|
+
State({
|
|
722
|
+
name: 'auth',
|
|
723
|
+
defaults: AUTH_STATE_DEFAULTS,
|
|
724
|
+
})
|
|
725
|
+
], GatewayAuthState);
|
|
726
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayAuthState, decorators: [{
|
|
727
|
+
type: Injectable
|
|
728
|
+
}], propDecorators: { login: [], verifyMfa: [], resendMfa: [], loadSsoProviders: [], startSso: [], exchangeSsoCode: [], loginSuccess: [], loginFailure: [], logout: [], updateUserData: [], updateTokens: [], clearError: [], clearPendingMfa: [] } });
|
|
729
|
+
|
|
730
|
+
class GatewayAuthFacade {
|
|
731
|
+
store = inject(Store);
|
|
732
|
+
user = select(GatewayAuthState.user);
|
|
733
|
+
loading = select(GatewayAuthState.loading);
|
|
734
|
+
mfaResendLoading = select(GatewayAuthState.mfaResendLoading);
|
|
735
|
+
ssoLoading = select(GatewayAuthState.ssoLoading);
|
|
736
|
+
ssoCallbackLoading = select(GatewayAuthState.ssoCallbackLoading);
|
|
737
|
+
error = select(GatewayAuthState.error);
|
|
738
|
+
token = select(GatewayAuthState.token);
|
|
739
|
+
refreshToken = select(GatewayAuthState.refreshToken);
|
|
740
|
+
accessTokenExpiresAt = select(GatewayAuthState.accessTokenExpiresAt);
|
|
741
|
+
refreshTokenExpiresAt = select(GatewayAuthState.refreshTokenExpiresAt);
|
|
742
|
+
twoFactorRequired = select(GatewayAuthState.twoFactorRequired);
|
|
743
|
+
pendingMfa = select(GatewayAuthState.pendingMfa);
|
|
744
|
+
ssoProviders = select(GatewayAuthState.ssoProviders);
|
|
745
|
+
isAdmin = select(GatewayAuthState.isAdmin);
|
|
746
|
+
userDetails = select(GatewayAuthState.userDetails);
|
|
747
|
+
hasError = computed(() => this.error() !== null, ...(ngDevMode ? [{ debugName: "hasError" }] : /* istanbul ignore next */ []));
|
|
748
|
+
isReady = computed(() => !this.loading() && this.error() === null, ...(ngDevMode ? [{ debugName: "isReady" }] : /* istanbul ignore next */ []));
|
|
749
|
+
userDisplayName = computed(() => this.user()?.user?.displayName || '', ...(ngDevMode ? [{ debugName: "userDisplayName" }] : /* istanbul ignore next */ []));
|
|
750
|
+
userEmail = computed(() => this.user()?.user?.email || '', ...(ngDevMode ? [{ debugName: "userEmail" }] : /* istanbul ignore next */ []));
|
|
751
|
+
hasUser = computed(() => this.user() !== null, ...(ngDevMode ? [{ debugName: "hasUser" }] : /* istanbul ignore next */ []));
|
|
752
|
+
hasPendingMfa = computed(() => this.pendingMfa() !== null, ...(ngDevMode ? [{ debugName: "hasPendingMfa" }] : /* istanbul ignore next */ []));
|
|
753
|
+
isAuthenticated = computed(() => {
|
|
754
|
+
const token = this.token();
|
|
755
|
+
const accessExpiresAt = this.accessTokenExpiresAt();
|
|
756
|
+
if (token && !isExpired(accessExpiresAt)) {
|
|
757
|
+
return true;
|
|
758
|
+
}
|
|
759
|
+
const refreshToken = this.refreshToken();
|
|
760
|
+
const refreshExpiresAt = this.refreshTokenExpiresAt();
|
|
761
|
+
return !!refreshToken && !isExpired(refreshExpiresAt);
|
|
762
|
+
}, ...(ngDevMode ? [{ debugName: "isAuthenticated" }] : /* istanbul ignore next */ []));
|
|
763
|
+
login(loginRequest) {
|
|
764
|
+
this.store.dispatch(new Login(loginRequest));
|
|
765
|
+
}
|
|
766
|
+
verifyMfa(code) {
|
|
767
|
+
this.store.dispatch(new VerifyMfa(code));
|
|
768
|
+
}
|
|
769
|
+
resendMfa() {
|
|
770
|
+
this.store.dispatch(new ResendMfa());
|
|
771
|
+
}
|
|
772
|
+
loadSsoProviders() {
|
|
773
|
+
this.store.dispatch(new LoadSsoProviders());
|
|
774
|
+
}
|
|
775
|
+
startSso(provider) {
|
|
776
|
+
this.store.dispatch(new StartSso(provider));
|
|
777
|
+
}
|
|
778
|
+
exchangeSsoCode(code, state) {
|
|
779
|
+
this.store.dispatch(new ExchangeSsoCode(code, state));
|
|
780
|
+
}
|
|
781
|
+
logout(remote = false) {
|
|
782
|
+
this.store.dispatch(new Logout(remote));
|
|
783
|
+
}
|
|
784
|
+
updateUserData(user) {
|
|
785
|
+
this.store.dispatch(new UpdateUserData(user));
|
|
786
|
+
}
|
|
787
|
+
updateTokens(tokens) {
|
|
788
|
+
this.store.dispatch(new UpdateTokens(tokens));
|
|
789
|
+
}
|
|
790
|
+
clearError() {
|
|
791
|
+
this.store.dispatch(new ClearError());
|
|
792
|
+
}
|
|
793
|
+
clearPendingMfa() {
|
|
794
|
+
this.store.dispatch(new ClearPendingMfa());
|
|
795
|
+
}
|
|
796
|
+
hasRole(role) {
|
|
797
|
+
const userRoles = this.user()?.user?.roles;
|
|
798
|
+
return Array.isArray(userRoles) ? userRoles.includes(role) : false;
|
|
799
|
+
}
|
|
800
|
+
hasGroup(group) {
|
|
801
|
+
const userGroups = this.user()?.user?.groups;
|
|
802
|
+
return Array.isArray(userGroups) ? userGroups.includes(group) : false;
|
|
803
|
+
}
|
|
804
|
+
isTokenExpired() {
|
|
805
|
+
const accessExpiresAt = this.accessTokenExpiresAt();
|
|
806
|
+
return accessExpiresAt ? isExpired(accessExpiresAt) : false;
|
|
807
|
+
}
|
|
808
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayAuthFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
809
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayAuthFacade, providedIn: 'root' });
|
|
810
|
+
}
|
|
811
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayAuthFacade, decorators: [{
|
|
812
|
+
type: Injectable,
|
|
813
|
+
args: [{
|
|
814
|
+
providedIn: 'root',
|
|
815
|
+
}]
|
|
816
|
+
}] });
|
|
817
|
+
|
|
818
|
+
class GatewayMfa {
|
|
819
|
+
auth = inject(GatewayAuthFacade);
|
|
820
|
+
fb = inject(FormBuilder);
|
|
821
|
+
router = inject(Router);
|
|
822
|
+
options = inject(GATEWAY_AUTH_OPTIONS);
|
|
823
|
+
pendingMfa = this.auth.pendingMfa;
|
|
824
|
+
loading = this.auth.loading;
|
|
825
|
+
resendLoading = this.auth.mfaResendLoading;
|
|
826
|
+
error = this.auth.error;
|
|
827
|
+
deliveryChannel = computed(() => this.pendingMfa()?.deliveryChannel || 'your configured channel', ...(ngDevMode ? [{ debugName: "deliveryChannel" }] : /* istanbul ignore next */ []));
|
|
828
|
+
expiresAt = computed(() => this.pendingMfa()?.expiresAtUtc ?? null, ...(ngDevMode ? [{ debugName: "expiresAt" }] : /* istanbul ignore next */ []));
|
|
829
|
+
form = this.fb.group({
|
|
830
|
+
code: ['', [Validators.required, Validators.pattern(/^[0-9]{4,8}$/)]],
|
|
831
|
+
});
|
|
832
|
+
ngOnInit() {
|
|
833
|
+
if (!this.pendingMfa()) {
|
|
834
|
+
this.router.navigate([this.options.loginRoute ?? '/auth/login'], {
|
|
835
|
+
replaceUrl: true,
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
verify() {
|
|
840
|
+
if (this.form.invalid) {
|
|
841
|
+
this.form.markAllAsTouched();
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
const code = this.form.controls.code.value ?? '';
|
|
845
|
+
this.form.reset();
|
|
846
|
+
this.auth.verifyMfa(code);
|
|
847
|
+
}
|
|
848
|
+
resend() {
|
|
849
|
+
this.form.reset();
|
|
850
|
+
this.auth.resendMfa();
|
|
851
|
+
}
|
|
852
|
+
backToLogin() {
|
|
853
|
+
this.auth.clearPendingMfa();
|
|
854
|
+
this.router.navigate([this.options.loginRoute ?? '/auth/login'], {
|
|
855
|
+
replaceUrl: true,
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayMfa, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
859
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: GatewayMfa, isStandalone: true, selector: "mt-gateway-mfa", ngImport: i0, template: "<div\n class=\"min-h-screen w-screen flex items-center justify-center p-6 bg-surface-50\"\n>\n <div\n class=\"w-full max-w-md rounded-xl bg-white p-8 shadow-sm border border-surface-200\"\n >\n <div class=\"flex justify-center mb-6\">\n <div\n class=\"h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center\"\n >\n <mt-icon\n icon=\"security.lock-01\"\n class=\"text-primary text-2xl\"\n ></mt-icon>\n </div>\n </div>\n\n <div class=\"text-center space-y-2 mb-6\">\n <h1 class=\"text-2xl font-semibold text-surface-950\">Verification code</h1>\n <p class=\"text-sm text-surface-600\">\n Enter the code sent through {{ deliveryChannel() }}.\n </p>\n @if (expiresAt(); as expiry) {\n <p class=\"text-xs text-surface-500\">\n Expires at {{ expiry | date: \"shortTime\" }}\n </p>\n }\n </div>\n\n <form [formGroup]=\"form\" (ngSubmit)=\"verify()\" class=\"space-y-4\">\n <mt-text-field\n label=\"Code\"\n formControlName=\"code\"\n [pInputs]=\"{ inputMode: 'numeric', autocomplete: 'one-time-code' }\"\n />\n\n @if (error(); as errorMessage) {\n <p class=\"text-sm text-red-500 text-center\">{{ errorMessage }}</p>\n }\n\n <mt-button\n label=\"Verify\"\n type=\"submit\"\n severity=\"primary\"\n size=\"large\"\n fluid\n [loading]=\"loading()\"\n [disabled]=\"form.invalid || loading()\"\n />\n </form>\n\n <div class=\"flex items-center justify-between gap-3 pt-5\">\n <mt-button\n label=\"Back\"\n type=\"button\"\n text\n [disabled]=\"loading()\"\n (onClick)=\"backToLogin()\"\n />\n <mt-button\n label=\"Resend code\"\n type=\"button\"\n variant=\"outlined\"\n [loading]=\"resendLoading()\"\n [disabled]=\"loading() || resendLoading()\"\n (onClick)=\"resend()\"\n />\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "icon", "iconPosition"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
860
|
+
}
|
|
861
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewayMfa, decorators: [{
|
|
862
|
+
type: Component,
|
|
863
|
+
args: [{ selector: 'mt-gateway-mfa', imports: [CommonModule, ReactiveFormsModule, Button, TextField, Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"min-h-screen w-screen flex items-center justify-center p-6 bg-surface-50\"\n>\n <div\n class=\"w-full max-w-md rounded-xl bg-white p-8 shadow-sm border border-surface-200\"\n >\n <div class=\"flex justify-center mb-6\">\n <div\n class=\"h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center\"\n >\n <mt-icon\n icon=\"security.lock-01\"\n class=\"text-primary text-2xl\"\n ></mt-icon>\n </div>\n </div>\n\n <div class=\"text-center space-y-2 mb-6\">\n <h1 class=\"text-2xl font-semibold text-surface-950\">Verification code</h1>\n <p class=\"text-sm text-surface-600\">\n Enter the code sent through {{ deliveryChannel() }}.\n </p>\n @if (expiresAt(); as expiry) {\n <p class=\"text-xs text-surface-500\">\n Expires at {{ expiry | date: \"shortTime\" }}\n </p>\n }\n </div>\n\n <form [formGroup]=\"form\" (ngSubmit)=\"verify()\" class=\"space-y-4\">\n <mt-text-field\n label=\"Code\"\n formControlName=\"code\"\n [pInputs]=\"{ inputMode: 'numeric', autocomplete: 'one-time-code' }\"\n />\n\n @if (error(); as errorMessage) {\n <p class=\"text-sm text-red-500 text-center\">{{ errorMessage }}</p>\n }\n\n <mt-button\n label=\"Verify\"\n type=\"submit\"\n severity=\"primary\"\n size=\"large\"\n fluid\n [loading]=\"loading()\"\n [disabled]=\"form.invalid || loading()\"\n />\n </form>\n\n <div class=\"flex items-center justify-between gap-3 pt-5\">\n <mt-button\n label=\"Back\"\n type=\"button\"\n text\n [disabled]=\"loading()\"\n (onClick)=\"backToLogin()\"\n />\n <mt-button\n label=\"Resend code\"\n type=\"button\"\n variant=\"outlined\"\n [loading]=\"resendLoading()\"\n [disabled]=\"loading() || resendLoading()\"\n (onClick)=\"resend()\"\n />\n </div>\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
864
|
+
}] });
|
|
865
|
+
|
|
866
|
+
class GatewaySsoCallback {
|
|
867
|
+
route = inject(ActivatedRoute);
|
|
868
|
+
router = inject(Router);
|
|
869
|
+
auth = inject(GatewayAuthFacade);
|
|
870
|
+
options = inject(GATEWAY_AUTH_OPTIONS);
|
|
871
|
+
ssoSession = new GatewaySsoSession();
|
|
872
|
+
loading = this.auth.ssoCallbackLoading;
|
|
873
|
+
exchangeError = this.auth.error;
|
|
874
|
+
callbackError = signal(null, ...(ngDevMode ? [{ debugName: "callbackError" }] : /* istanbul ignore next */ []));
|
|
875
|
+
ngOnInit() {
|
|
876
|
+
const params = this.route.snapshot.queryParamMap;
|
|
877
|
+
const error = params.get('error');
|
|
878
|
+
const errorCode = params.get('errorCode');
|
|
879
|
+
const code = params.get('code');
|
|
880
|
+
const state = params.get('state');
|
|
881
|
+
this.ssoSession.clearCallbackQuery(this.options.ssoCallbackPath ?? '/auth/sso/callback');
|
|
882
|
+
if (!this.ssoSession.consumeExpectedState(state)) {
|
|
883
|
+
this.callbackError.set(this.safeSsoMessage('invalid_state'));
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
if (error) {
|
|
887
|
+
this.callbackError.set(this.safeSsoMessage(errorCode ?? 'sso_failed'));
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
if (!code || !state) {
|
|
891
|
+
this.callbackError.set(this.safeSsoMessage('invalid_state'));
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
this.auth.exchangeSsoCode(code, state);
|
|
895
|
+
}
|
|
896
|
+
retry() {
|
|
897
|
+
this.router.navigate([this.options.loginRoute ?? '/auth/login'], {
|
|
898
|
+
replaceUrl: true,
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
safeSsoMessage(errorCode) {
|
|
902
|
+
const messages = {
|
|
903
|
+
invalid_state: 'The sign-in session expired. Please try again.',
|
|
904
|
+
sso_exchange_expired: 'The sign-in session expired. Please try again.',
|
|
905
|
+
sso_exchange_used: 'This sign-in session was already used. Please try again.',
|
|
906
|
+
sso_user_not_found: 'Your account is not configured for SSO.',
|
|
907
|
+
sso_provisioning_not_allowed: 'Your account is not configured for SSO.',
|
|
908
|
+
};
|
|
909
|
+
return messages[errorCode] ?? 'SSO sign-in failed. Please try again.';
|
|
910
|
+
}
|
|
911
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewaySsoCallback, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
912
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: GatewaySsoCallback, isStandalone: true, selector: "mt-gateway-sso-callback", ngImport: i0, template: "<div\n class=\"min-h-screen w-screen flex items-center justify-center p-6 bg-surface-50\"\n>\n <div\n class=\"w-full max-w-md rounded-xl bg-white p-8 shadow-sm border border-surface-200 text-center\"\n >\n @if (callbackError() || exchangeError(); as errorMessage) {\n <div class=\"space-y-5\">\n <mt-icon\n icon=\"alert.alert-circle\"\n class=\"text-red-500 text-4xl\"\n ></mt-icon>\n <div class=\"space-y-2\">\n <h1 class=\"text-xl font-semibold text-surface-950\">\n SSO sign-in failed\n </h1>\n <p class=\"text-sm text-surface-600\">{{ errorMessage }}</p>\n </div>\n <mt-button\n label=\"Back to sign in\"\n severity=\"primary\"\n (onClick)=\"retry()\"\n ></mt-button>\n </div>\n } @else {\n <div class=\"space-y-5\">\n <mt-icon\n icon=\"general.loading-02\"\n class=\"text-primary text-4xl animate-spin animate-duration-2000\"\n >\n </mt-icon>\n <div class=\"space-y-2\">\n <h1 class=\"text-xl font-semibold text-surface-950\">\n Completing sign-in\n </h1>\n <p class=\"text-sm text-surface-600\">\n Please wait while we finish the secure sign-in.\n </p>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: Icon, selector: "mt-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
913
|
+
}
|
|
914
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: GatewaySsoCallback, decorators: [{
|
|
915
|
+
type: Component,
|
|
916
|
+
args: [{ selector: 'mt-gateway-sso-callback', imports: [CommonModule, Button, Icon], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"min-h-screen w-screen flex items-center justify-center p-6 bg-surface-50\"\n>\n <div\n class=\"w-full max-w-md rounded-xl bg-white p-8 shadow-sm border border-surface-200 text-center\"\n >\n @if (callbackError() || exchangeError(); as errorMessage) {\n <div class=\"space-y-5\">\n <mt-icon\n icon=\"alert.alert-circle\"\n class=\"text-red-500 text-4xl\"\n ></mt-icon>\n <div class=\"space-y-2\">\n <h1 class=\"text-xl font-semibold text-surface-950\">\n SSO sign-in failed\n </h1>\n <p class=\"text-sm text-surface-600\">{{ errorMessage }}</p>\n </div>\n <mt-button\n label=\"Back to sign in\"\n severity=\"primary\"\n (onClick)=\"retry()\"\n ></mt-button>\n </div>\n } @else {\n <div class=\"space-y-5\">\n <mt-icon\n icon=\"general.loading-02\"\n class=\"text-primary text-4xl animate-spin animate-duration-2000\"\n >\n </mt-icon>\n <div class=\"space-y-2\">\n <h1 class=\"text-xl font-semibold text-surface-950\">\n Completing sign-in\n </h1>\n <p class=\"text-sm text-surface-600\">\n Please wait while we finish the secure sign-in.\n </p>\n </div>\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block}\n"] }]
|
|
917
|
+
}] });
|
|
918
|
+
|
|
143
919
|
/**
|
|
144
920
|
* Generated bundle index. Do not edit.
|
|
145
921
|
*/
|
|
146
922
|
|
|
147
|
-
export { GATEWAY_AUTH_DEVICE_TOKEN, GATEWAY_AUTH_ENDPOINTS, GatewaySsoSession, buildGatewayUrl, buildSsoStartUrl, createSecureClientState, getGatewayErrorMessage, hasGatewayTokens, isExpired, mapGatewayTokens, mapGatewayUser, normalizeGatewayBase, resolveApiDateValue };
|
|
923
|
+
export { AUTH_STATE_DEFAULTS, ClearError, ClearPendingMfa, ExchangeSsoCode, GATEWAY_AUTH_DEVICE_TOKEN, GATEWAY_AUTH_ENDPOINTS, GATEWAY_AUTH_OPTIONS, GatewayAuthFacade, GatewayAuthState, GatewayMfa, GatewaySsoCallback, GatewaySsoSession, LoadSsoProviders, Login, LoginFailure, LoginSuccess, Logout, ResendMfa, StartSso, UpdateTokens, UpdateUserData, VerifyMfa, buildGatewayUrl, buildSsoStartUrl, createSecureClientState, getGatewayErrorMessage, hasGatewayTokens, isExpired, mapGatewayTokens, mapGatewayUser, normalizeGatewayBase, resolveApiDateValue, sanitizePersistedAuthState };
|
|
148
924
|
//# sourceMappingURL=masterteam-gateway-auth.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"masterteam-gateway-auth.mjs","sources":["../../../../packages/masterteam/gateway-auth/src/gateway-auth.utils.ts","../../../../packages/masterteam/gateway-auth/src/gateway-sso-session.service.ts","../../../../packages/masterteam/gateway-auth/src/masterteam-gateway-auth.ts"],"sourcesContent":["import {\n GatewayApiDateValue,\n GatewayAuthTokens,\n GatewayMappedTokens,\n GatewayMappedUser,\n GatewayRefreshData,\n GatewaySsoProvider,\n GatewayUserDetails,\n} from './gateway-auth.models';\n\nexport const GATEWAY_AUTH_DEVICE_TOKEN = 'web-app';\n\nexport const GATEWAY_AUTH_ENDPOINTS = {\n login: 'auth/login',\n verifyMfa: 'auth/2fa/verify',\n resendMfa: 'auth/2fa/resend',\n refresh: 'auth/refresh',\n logout: 'auth/logout',\n ssoProviders: 'auth/sso/providers',\n ssoExchange: 'auth/sso/exchange',\n ssoTokenExchange: 'auth/sso/token-exchange',\n nafathStart: (providerKey: string) =>\n `auth/sso/nafath/${encodeURIComponent(providerKey)}/start`,\n nafathStatus: (providerKey: string) =>\n `auth/sso/nafath/${encodeURIComponent(providerKey)}/status`,\n ssoStart: (providerKey: string) =>\n `auth/sso/${encodeURIComponent(providerKey)}/start`,\n} as const;\n\nexport function isExpired(expireAt?: string | null): boolean {\n if (!expireAt) {\n return false;\n }\n\n const timestamp = new Date(expireAt).getTime();\n return !Number.isFinite(timestamp) || timestamp <= Date.now();\n}\n\nexport function resolveApiDateValue(\n value?: GatewayApiDateValue | null,\n): string | null {\n return value?.actualValue ?? value?.rawValue ?? null;\n}\n\nexport function mapGatewayTokens(\n tokens: GatewayAuthTokens | GatewayRefreshData,\n): GatewayMappedTokens {\n return {\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n accessTokenExpiresAt: resolveApiDateValue(tokens.accessTokenExpiresAt),\n refreshTokenExpiresAt: resolveApiDateValue(tokens.refreshTokenExpiresAt),\n };\n}\n\nexport function mapGatewayUser(\n user: GatewayUserDetails,\n tokenData: GatewayMappedTokens,\n delegations?: unknown[],\n): GatewayMappedUser {\n const photo =\n typeof user.photo === 'string' ? { fileName: user.photo } : user.photo;\n const imageFallback = user.image ? { fileName: user.image } : undefined;\n const resolvedPhoto = photo ?? imageFallback;\n\n return {\n user: {\n ...user,\n photo: resolvedPhoto,\n },\n token: tokenData.accessToken,\n accessToken: tokenData.accessToken,\n refreshToken: tokenData.refreshToken,\n accessTokenExpiresAt: tokenData.accessTokenExpiresAt ?? undefined,\n refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt ?? undefined,\n delegations: delegations ?? [],\n twoFactorRequired: false,\n };\n}\n\nexport function hasGatewayTokens(\n tokens?: Partial<GatewayAuthTokens | GatewayRefreshData> | null,\n): boolean {\n return Boolean(tokens?.accessToken && tokens?.refreshToken);\n}\n\nexport function getGatewayErrorMessage(\n error: unknown,\n fallback: string,\n): string {\n const response = error as {\n error?: { message?: string; Message?: string; errors?: { message?: string } };\n message?: string;\n };\n\n return (\n response.error?.message ??\n response.error?.Message ??\n response.error?.errors?.message ??\n response.message ??\n fallback\n );\n}\n\nexport function normalizeGatewayBase(baseUrl?: string | null): string {\n if (!baseUrl) {\n return '';\n }\n\n return baseUrl.replace(/\\/+$/, '');\n}\n\nexport function buildGatewayUrl(\n gatewayApiBaseUrl: string | undefined | null,\n path: string,\n): string {\n if (/^https?:\\/\\//i.test(path)) {\n return path;\n }\n\n const normalizedBase = normalizeGatewayBase(gatewayApiBaseUrl);\n if (!normalizedBase) {\n return path;\n }\n\n const normalizedPath = path.replace(/^\\/+/, '');\n if (normalizedPath.startsWith('api/')) {\n try {\n const base = new URL(normalizedBase);\n return `${base.origin}/${normalizedPath}`;\n } catch {\n return `${normalizedBase}/${normalizedPath}`;\n }\n }\n\n return `${normalizedBase}/${normalizedPath}`;\n}\n\nexport interface BuildSsoStartUrlOptions {\n gatewayApiBaseUrl: string;\n provider: GatewaySsoProvider;\n returnUrl: string;\n clientState: string;\n platform?: 'web' | 'mobile';\n}\n\nexport function buildSsoStartUrl({\n gatewayApiBaseUrl,\n provider,\n returnUrl,\n clientState,\n platform = 'web',\n}: BuildSsoStartUrlOptions): string {\n const startPath = provider.startUrl || GATEWAY_AUTH_ENDPOINTS.ssoStart(provider.key);\n const url = new URL(buildGatewayUrl(gatewayApiBaseUrl, startPath));\n url.searchParams.set('platform', platform);\n url.searchParams.set('returnUrl', returnUrl);\n url.searchParams.set('clientState', clientState);\n return url.toString();\n}\n\nexport function createSecureClientState(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n const bytes = new Uint8Array(16);\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(bytes);\n return Array.from(bytes, (value) => value.toString(16).padStart(2, '0')).join(\n '',\n );\n }\n\n return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;\n}\n\n","import { createSecureClientState } from './gateway-auth.utils';\n\nconst PENDING_SSO_STATE_KEY = 'gatewayAuth.pendingSsoState';\n\nexport class GatewaySsoSession {\n createAndStoreState(): string {\n const state = createSecureClientState();\n this.storage?.setItem(PENDING_SSO_STATE_KEY, state);\n return state;\n }\n\n getPendingState(): string | null {\n return this.storage?.getItem(PENDING_SSO_STATE_KEY) ?? null;\n }\n\n clearPendingState(): void {\n this.storage?.removeItem(PENDING_SSO_STATE_KEY);\n }\n\n consumeExpectedState(state: string | null): boolean {\n const expectedState = this.getPendingState();\n this.clearPendingState();\n return Boolean(state && expectedState && state === expectedState);\n }\n\n clearCallbackQuery(path = '/auth/sso/callback'): void {\n if (typeof window === 'undefined' || !window.history?.replaceState) {\n return;\n }\n\n window.history.replaceState({}, document.title, path);\n }\n\n clearAll(): void {\n this.clearPendingState();\n }\n\n private get storage(): Storage | null {\n if (typeof sessionStorage === 'undefined') {\n return null;\n }\n\n return sessionStorage;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"masterteam-gateway-auth.mjs","sources":["../../../../packages/masterteam/gateway-auth/src/gateway-auth.utils.ts","../../../../packages/masterteam/gateway-auth/src/gateway-sso-session.service.ts","../../../../packages/masterteam/gateway-auth/src/gateway-auth.options.ts","../../../../packages/masterteam/gateway-auth/src/gateway-auth.state.model.ts","../../../../packages/masterteam/gateway-auth/src/gateway-auth.actions.ts","../../../../packages/masterteam/gateway-auth/src/gateway-auth.state.ts","../../../../packages/masterteam/gateway-auth/src/gateway-auth.facade.ts","../../../../packages/masterteam/gateway-auth/src/components/gateway-mfa/gateway-mfa.ts","../../../../packages/masterteam/gateway-auth/src/components/gateway-mfa/gateway-mfa.html","../../../../packages/masterteam/gateway-auth/src/components/gateway-sso-callback/gateway-sso-callback.ts","../../../../packages/masterteam/gateway-auth/src/components/gateway-sso-callback/gateway-sso-callback.html","../../../../packages/masterteam/gateway-auth/src/masterteam-gateway-auth.ts"],"sourcesContent":["import {\n GatewayApiDateValue,\n GatewayAuthTokens,\n GatewayMappedTokens,\n GatewayMappedUser,\n GatewayRefreshData,\n GatewaySsoProvider,\n GatewayUserDetails,\n} from './gateway-auth.models';\n\nexport const GATEWAY_AUTH_DEVICE_TOKEN = 'web-app';\n\nexport const GATEWAY_AUTH_ENDPOINTS = {\n login: 'auth/login',\n verifyMfa: 'auth/2fa/verify',\n resendMfa: 'auth/2fa/resend',\n refresh: 'auth/refresh',\n logout: 'auth/logout',\n ssoProviders: 'auth/sso/providers',\n ssoExchange: 'auth/sso/exchange',\n ssoTokenExchange: 'auth/sso/token-exchange',\n nafathStart: (providerKey: string) =>\n `auth/sso/nafath/${encodeURIComponent(providerKey)}/start`,\n nafathStatus: (providerKey: string) =>\n `auth/sso/nafath/${encodeURIComponent(providerKey)}/status`,\n ssoStart: (providerKey: string) =>\n `auth/sso/${encodeURIComponent(providerKey)}/start`,\n} as const;\n\nexport function isExpired(expireAt?: string | null): boolean {\n if (!expireAt) {\n return false;\n }\n\n const timestamp = new Date(expireAt).getTime();\n return !Number.isFinite(timestamp) || timestamp <= Date.now();\n}\n\nexport function resolveApiDateValue(\n value?: GatewayApiDateValue | null,\n): string | null {\n return value?.actualValue ?? value?.rawValue ?? null;\n}\n\nexport function mapGatewayTokens(\n tokens: GatewayAuthTokens | GatewayRefreshData,\n): GatewayMappedTokens {\n return {\n accessToken: tokens.accessToken,\n refreshToken: tokens.refreshToken,\n accessTokenExpiresAt: resolveApiDateValue(tokens.accessTokenExpiresAt),\n refreshTokenExpiresAt: resolveApiDateValue(tokens.refreshTokenExpiresAt),\n };\n}\n\nexport function mapGatewayUser(\n user: GatewayUserDetails,\n tokenData: GatewayMappedTokens,\n delegations?: unknown[],\n): GatewayMappedUser {\n const photo =\n typeof user.photo === 'string' ? { fileName: user.photo } : user.photo;\n const imageFallback = user.image ? { fileName: user.image } : undefined;\n const resolvedPhoto = photo ?? imageFallback;\n\n return {\n user: {\n ...user,\n photo: resolvedPhoto,\n },\n token: tokenData.accessToken,\n accessToken: tokenData.accessToken,\n refreshToken: tokenData.refreshToken,\n accessTokenExpiresAt: tokenData.accessTokenExpiresAt ?? undefined,\n refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt ?? undefined,\n delegations: delegations ?? [],\n twoFactorRequired: false,\n };\n}\n\nexport function hasGatewayTokens(\n tokens?: Partial<GatewayAuthTokens | GatewayRefreshData> | null,\n): boolean {\n return Boolean(tokens?.accessToken && tokens?.refreshToken);\n}\n\nexport function getGatewayErrorMessage(\n error: unknown,\n fallback: string,\n): string {\n const response = error as {\n error?: {\n message?: string;\n Message?: string;\n errors?: { message?: string };\n };\n message?: string;\n };\n\n return (\n response.error?.message ??\n response.error?.Message ??\n response.error?.errors?.message ??\n response.message ??\n fallback\n );\n}\n\nexport function normalizeGatewayBase(baseUrl?: string | null): string {\n if (!baseUrl) {\n return '';\n }\n\n return baseUrl.replace(/\\/+$/, '');\n}\n\nexport function buildGatewayUrl(\n gatewayApiBaseUrl: string | undefined | null,\n path: string,\n): string {\n if (/^https?:\\/\\//i.test(path)) {\n return path;\n }\n\n const normalizedBase = normalizeGatewayBase(gatewayApiBaseUrl);\n if (!normalizedBase) {\n return path;\n }\n\n const normalizedPath = path.replace(/^\\/+/, '');\n if (normalizedPath.startsWith('api/')) {\n try {\n const base = new URL(normalizedBase);\n return `${base.origin}/${normalizedPath}`;\n } catch {\n return `${normalizedBase}/${normalizedPath}`;\n }\n }\n\n return `${normalizedBase}/${normalizedPath}`;\n}\n\nexport interface BuildSsoStartUrlOptions {\n gatewayApiBaseUrl: string;\n provider: GatewaySsoProvider;\n returnUrl: string;\n clientState: string;\n platform?: 'web' | 'mobile';\n}\n\nexport function buildSsoStartUrl({\n gatewayApiBaseUrl,\n provider,\n returnUrl,\n clientState,\n platform = 'web',\n}: BuildSsoStartUrlOptions): string {\n const startPath =\n provider.startUrl || GATEWAY_AUTH_ENDPOINTS.ssoStart(provider.key);\n const url = new URL(buildGatewayUrl(gatewayApiBaseUrl, startPath));\n url.searchParams.set('platform', platform);\n url.searchParams.set('returnUrl', returnUrl);\n url.searchParams.set('clientState', clientState);\n return url.toString();\n}\n\nexport function createSecureClientState(): string {\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n const bytes = new Uint8Array(16);\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n crypto.getRandomValues(bytes);\n return Array.from(bytes, (value) =>\n value.toString(16).padStart(2, '0'),\n ).join('');\n }\n\n return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;\n}\n","import { createSecureClientState } from './gateway-auth.utils';\n\nconst PENDING_SSO_STATE_KEY = 'gatewayAuth.pendingSsoState';\n\nexport class GatewaySsoSession {\n createAndStoreState(): string {\n const state = createSecureClientState();\n this.storage?.setItem(PENDING_SSO_STATE_KEY, state);\n return state;\n }\n\n getPendingState(): string | null {\n return this.storage?.getItem(PENDING_SSO_STATE_KEY) ?? null;\n }\n\n clearPendingState(): void {\n this.storage?.removeItem(PENDING_SSO_STATE_KEY);\n }\n\n consumeExpectedState(state: string | null): boolean {\n const expectedState = this.getPendingState();\n this.clearPendingState();\n return Boolean(state && expectedState && state === expectedState);\n }\n\n clearCallbackQuery(path = '/auth/sso/callback'): void {\n if (typeof window === 'undefined' || !window.history?.replaceState) {\n return;\n }\n\n window.history.replaceState({}, document.title, path);\n }\n\n clearAll(): void {\n this.clearPendingState();\n }\n\n private get storage(): Storage | null {\n if (typeof sessionStorage === 'undefined') {\n return null;\n }\n\n return sessionStorage;\n }\n}\n","import { InjectionToken } from '@angular/core';\nimport { StateContext } from '@ngxs/store';\nimport { Observable } from 'rxjs';\nimport { GatewayLoginResponse, GatewayPlatform } from './gateway-auth.models';\nimport { AuthStateModel } from './gateway-auth.state.model';\n\nexport type GatewayAuthHookResult =\n | void\n | null\n | Observable<unknown>\n | Promise<unknown>;\n\nexport interface GatewayAuthOptions {\n getGatewayApiBaseUrl: () => string | null | undefined;\n deviceToken?: string;\n platform?: GatewayPlatform;\n loginRoute?: string;\n mfaRoute?: string;\n ssoCallbackPath?: string;\n defaultAuthenticatedRoute?: string | (() => string | null | undefined);\n preserveSsoProvidersOnLogout?: boolean;\n afterLogin?: (\n session: GatewayLoginResponse,\n ctx: StateContext<AuthStateModel>,\n ) => GatewayAuthHookResult;\n beforeLocalLogout?: (\n ctx: StateContext<AuthStateModel>,\n ) => GatewayAuthHookResult;\n}\n\nexport const GATEWAY_AUTH_OPTIONS = new InjectionToken<GatewayAuthOptions>(\n 'GATEWAY_AUTH_OPTIONS',\n {\n factory: () => ({\n getGatewayApiBaseUrl: () => null,\n deviceToken: 'web-app',\n platform: 'web',\n loginRoute: '/auth/login',\n mfaRoute: '/auth/mfa',\n ssoCallbackPath: '/auth/sso/callback',\n defaultAuthenticatedRoute: '/',\n preserveSsoProvidersOnLogout: true,\n }),\n },\n);\n","import {\n GatewayAuthTokens,\n GatewayLoginRequest,\n GatewayLoginResponse,\n GatewayMappedUser,\n GatewayRefreshData,\n GatewayResponse,\n GatewaySsoProvider,\n GatewayTwoFactorChallenge,\n GatewayUserDetails,\n} from './gateway-auth.models';\n\nexport type UserDetails = GatewayUserDetails;\nexport type User = GatewayMappedUser;\nexport type LoginRequest = GatewayLoginRequest;\nexport type ApiDateValue = NonNullable<\n GatewayAuthTokens['accessTokenExpiresAt']\n>;\nexport type AuthTokens = GatewayAuthTokens;\nexport type AuthLoginData = GatewayLoginResponse;\nexport type AuthRefreshData = GatewayRefreshData;\nexport type TwoFactorChallenge = GatewayTwoFactorChallenge;\nexport type SsoProvider = GatewaySsoProvider;\nexport type Response<T> = GatewayResponse<T>;\n\nexport interface AuthStateModel {\n user: User | null;\n token: string | null;\n refreshToken: string | null;\n accessTokenExpiresAt: string | null;\n refreshTokenExpiresAt: string | null;\n loading: boolean;\n mfaResendLoading: boolean;\n ssoLoading: boolean;\n ssoCallbackLoading: boolean;\n error: string | null;\n twoFactorRequired: boolean;\n pendingMfa: TwoFactorChallenge | null;\n ssoProviders: SsoProvider[];\n}\n\nexport const AUTH_STATE_DEFAULTS: AuthStateModel = {\n user: null,\n token: null,\n refreshToken: null,\n accessTokenExpiresAt: null,\n refreshTokenExpiresAt: null,\n loading: false,\n mfaResendLoading: false,\n ssoLoading: false,\n ssoCallbackLoading: false,\n error: null,\n twoFactorRequired: false,\n pendingMfa: null,\n ssoProviders: [],\n};\n\nexport function sanitizePersistedAuthState(\n obj: Partial<AuthStateModel> | null,\n) {\n return {\n ...AUTH_STATE_DEFAULTS,\n ...(obj ?? {}),\n loading: false,\n mfaResendLoading: false,\n ssoLoading: false,\n ssoCallbackLoading: false,\n error: null,\n twoFactorRequired: false,\n pendingMfa: null,\n ssoProviders: [],\n };\n}\n","import {\n AuthLoginData,\n AuthTokens,\n LoginRequest,\n SsoProvider,\n User,\n} from './gateway-auth.state.model';\n\nexport class Login {\n static readonly type = '[Auth] Login';\n constructor(public payload: LoginRequest) {}\n}\n\nexport class VerifyMfa {\n static readonly type = '[Auth] Verify MFA';\n constructor(public code: string) {}\n}\n\nexport class ResendMfa {\n static readonly type = '[Auth] Resend MFA';\n}\n\nexport class LoadSsoProviders {\n static readonly type = '[Auth] Load SSO Providers';\n}\n\nexport class StartSso {\n static readonly type = '[Auth] Start SSO';\n constructor(public provider: SsoProvider) {}\n}\n\nexport class ExchangeSsoCode {\n static readonly type = '[Auth] Exchange SSO Code';\n constructor(\n public code: string,\n public state: string,\n ) {}\n}\n\nexport class LoginSuccess {\n static readonly type = '[Auth] Login Success';\n constructor(public session: AuthLoginData) {}\n}\n\nexport class LoginFailure {\n static readonly type = '[Auth] Login Failure';\n constructor(public error: string) {}\n}\n\nexport class Logout {\n static readonly type = '[Auth] Logout';\n constructor(public remote: boolean = false) {}\n}\n\nexport class UpdateUserData {\n static readonly type = '[Auth] Update User Data';\n constructor(public user: User) {}\n}\n\nexport class UpdateTokens {\n static readonly type = '[Auth] Update Tokens';\n constructor(public tokens: AuthTokens) {}\n}\n\nexport class ClearError {\n static readonly type = '[Auth] Clear Error';\n}\n\nexport class ClearPendingMfa {\n static readonly type = '[Auth] Clear Pending MFA';\n}\n","import { HttpClient } from '@angular/common/http';\nimport { Injectable, inject } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { Action, Selector, State, StateContext } from '@ngxs/store';\nimport { EMPTY, Observable, from, isObservable, of } from 'rxjs';\nimport { catchError, mergeMap, tap } from 'rxjs/operators';\nimport {\n ClearError,\n ClearPendingMfa,\n ExchangeSsoCode,\n LoadSsoProviders,\n Login,\n LoginFailure,\n LoginSuccess,\n Logout,\n ResendMfa,\n StartSso,\n UpdateTokens,\n UpdateUserData,\n VerifyMfa,\n} from './gateway-auth.actions';\nimport {\n GATEWAY_AUTH_OPTIONS,\n GatewayAuthHookResult,\n GatewayAuthOptions,\n} from './gateway-auth.options';\nimport {\n GatewayLoginResponse,\n GatewayResponse,\n GatewaySsoProvidersData,\n GatewayTwoFactorChallenge,\n} from './gateway-auth.models';\nimport {\n buildGatewayUrl,\n buildSsoStartUrl,\n GATEWAY_AUTH_DEVICE_TOKEN,\n GATEWAY_AUTH_ENDPOINTS,\n getGatewayErrorMessage,\n hasGatewayTokens,\n mapGatewayTokens,\n mapGatewayUser,\n} from './gateway-auth.utils';\nimport { GatewaySsoSession } from './gateway-sso-session.service';\nimport {\n AUTH_STATE_DEFAULTS,\n AuthLoginData,\n AuthStateModel,\n SsoProvider,\n User,\n} from './gateway-auth.state.model';\n\n@State<AuthStateModel>({\n name: 'auth',\n defaults: AUTH_STATE_DEFAULTS,\n})\n@Injectable()\nexport class GatewayAuthState {\n private readonly http = inject(HttpClient);\n private readonly options = inject(GATEWAY_AUTH_OPTIONS);\n private readonly router = inject(Router);\n private readonly ssoSession = new GatewaySsoSession();\n\n @Selector()\n static user(state: AuthStateModel): User | null {\n return state.user;\n }\n\n @Selector()\n static loading(state: AuthStateModel): boolean {\n return state.loading;\n }\n\n @Selector()\n static mfaResendLoading(state: AuthStateModel): boolean {\n return state.mfaResendLoading;\n }\n\n @Selector()\n static ssoLoading(state: AuthStateModel): boolean {\n return state.ssoLoading;\n }\n\n @Selector()\n static ssoCallbackLoading(state: AuthStateModel): boolean {\n return state.ssoCallbackLoading;\n }\n\n @Selector()\n static error(state: AuthStateModel): string | null {\n return state.error;\n }\n\n @Selector()\n static token(state: AuthStateModel): string | null {\n return state.token;\n }\n\n @Selector()\n static refreshToken(state: AuthStateModel): string | null {\n return state.refreshToken;\n }\n\n @Selector()\n static accessTokenExpiresAt(state: AuthStateModel): string | null {\n return state.accessTokenExpiresAt;\n }\n\n @Selector()\n static refreshTokenExpiresAt(state: AuthStateModel): string | null {\n return state.refreshTokenExpiresAt;\n }\n\n @Selector()\n static twoFactorRequired(state: AuthStateModel): boolean {\n return state.twoFactorRequired;\n }\n\n @Selector()\n static pendingMfa(state: AuthStateModel) {\n return state.pendingMfa;\n }\n\n @Selector()\n static ssoProviders(state: AuthStateModel): SsoProvider[] {\n return state.ssoProviders;\n }\n\n @Selector()\n static isAdmin(state: AuthStateModel): boolean {\n return state.user?.isAdmin || false;\n }\n\n @Selector()\n static userDetails(state: AuthStateModel) {\n return state.user?.user || null;\n }\n\n @Action(Login)\n login(ctx: StateContext<AuthStateModel>, action: Login) {\n ctx.patchState({\n loading: true,\n error: null,\n pendingMfa: null,\n twoFactorRequired: false,\n });\n\n return this.http\n .post<GatewayResponse<GatewayLoginResponse>>(\n this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.login),\n {\n userName: action.payload.userName,\n password: action.payload.password,\n isEncrypted: action.payload.isEncrypted ?? false,\n deviceToken: action.payload.deviceToken || this.deviceToken,\n recaptchaToken: action.payload.recaptchaToken,\n recaptchaAction: action.payload.recaptchaAction,\n },\n )\n .pipe(\n mergeMap((response) => this.handleLoginResponse(ctx, response.data)),\n catchError((error) => {\n ctx.dispatch(\n new LoginFailure(getGatewayErrorMessage(error, 'Login failed')),\n );\n return of(null);\n }),\n );\n }\n\n @Action(VerifyMfa)\n verifyMfa(ctx: StateContext<AuthStateModel>, action: VerifyMfa) {\n const pendingMfa = ctx.getState().pendingMfa;\n if (!pendingMfa) {\n ctx.dispatch(new LoginFailure('The verification session expired.'));\n this.navigateToLogin();\n return EMPTY;\n }\n\n ctx.patchState({ loading: true, error: null });\n\n return this.http\n .post<GatewayResponse<GatewayLoginResponse>>(\n this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.verifyMfa),\n {\n userId: pendingMfa.userId,\n tempSessionId: pendingMfa.tempSessionId,\n code: action.code,\n deviceToken: this.deviceToken,\n },\n )\n .pipe(\n mergeMap((response) => this.handleLoginResponse(ctx, response.data)),\n catchError((error) => {\n const message = getGatewayErrorMessage(\n error,\n 'Invalid verification code',\n );\n const shouldClearMfa = error?.status === 403;\n ctx.patchState({\n loading: false,\n error: message,\n pendingMfa: shouldClearMfa ? null : pendingMfa,\n twoFactorRequired: !shouldClearMfa,\n });\n if (shouldClearMfa) {\n this.navigateToLogin();\n }\n return of(null);\n }),\n );\n }\n\n @Action(ResendMfa)\n resendMfa(ctx: StateContext<AuthStateModel>) {\n const pendingMfa = ctx.getState().pendingMfa;\n if (!pendingMfa) {\n ctx.dispatch(new LoginFailure('The verification session expired.'));\n this.navigateToLogin();\n return EMPTY;\n }\n\n ctx.patchState({ mfaResendLoading: true, error: null });\n\n return this.http\n .post<GatewayResponse<GatewayTwoFactorChallenge>>(\n this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.resendMfa),\n {\n userId: pendingMfa.userId,\n tempSessionId: pendingMfa.tempSessionId,\n },\n )\n .pipe(\n tap((response) => {\n ctx.patchState({\n pendingMfa: response.data,\n twoFactorRequired: true,\n mfaResendLoading: false,\n error: null,\n });\n }),\n catchError((error) => {\n ctx.patchState({\n mfaResendLoading: false,\n error: getGatewayErrorMessage(error, 'Failed to resend code'),\n });\n return of(null);\n }),\n );\n }\n\n @Action(LoadSsoProviders)\n loadSsoProviders(ctx: StateContext<AuthStateModel>) {\n ctx.patchState({ ssoLoading: true });\n\n return this.http\n .get<GatewayResponse<GatewaySsoProvidersData>>(\n this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.ssoProviders),\n {\n params: { platform: this.options.platform ?? 'web' },\n },\n )\n .pipe(\n tap((response) => {\n ctx.patchState({\n ssoProviders: (response.data?.providers ?? []).filter(\n (provider) => provider.enabled,\n ),\n ssoLoading: false,\n });\n }),\n catchError(() => {\n ctx.patchState({\n ssoProviders: [],\n ssoLoading: false,\n });\n return of(null);\n }),\n );\n }\n\n @Action(StartSso)\n startSso(ctx: StateContext<AuthStateModel>, action: StartSso) {\n if (action.provider.flow !== 'browser_redirect') {\n ctx.patchState({\n error: 'This SSO provider is not available for browser sign-in.',\n });\n return;\n }\n\n const gatewayApiBaseUrl = this.options.getGatewayApiBaseUrl();\n if (!gatewayApiBaseUrl || typeof window === 'undefined') {\n ctx.patchState({ error: 'SSO is not configured.' });\n return;\n }\n\n const clientState = this.ssoSession.createAndStoreState();\n const callbackPath = this.options.ssoCallbackPath ?? '/auth/sso/callback';\n const startUrl = buildSsoStartUrl({\n gatewayApiBaseUrl,\n provider: action.provider,\n returnUrl: `${window.location.origin}${callbackPath}`,\n clientState,\n platform: this.options.platform ?? 'web',\n });\n\n window.location.assign(startUrl);\n }\n\n @Action(ExchangeSsoCode)\n exchangeSsoCode(ctx: StateContext<AuthStateModel>, action: ExchangeSsoCode) {\n ctx.patchState({ ssoCallbackLoading: true, error: null });\n\n return this.http\n .post<GatewayResponse<GatewayLoginResponse>>(\n this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.ssoExchange),\n {\n code: action.code,\n state: action.state,\n deviceToken: this.deviceToken,\n },\n )\n .pipe(\n mergeMap((response) => this.handleLoginResponse(ctx, response.data)),\n catchError((error) => {\n ctx.patchState({\n ssoCallbackLoading: false,\n error: getGatewayErrorMessage(\n error,\n 'SSO sign-in failed. Please try again.',\n ),\n });\n return of(null);\n }),\n );\n }\n\n @Action(LoginSuccess)\n loginSuccess(ctx: StateContext<AuthStateModel>, action: LoginSuccess) {\n return this.handleLoginResponse(ctx, action.session);\n }\n\n @Action(LoginFailure)\n loginFailure(ctx: StateContext<AuthStateModel>, action: LoginFailure) {\n ctx.patchState({\n loading: false,\n ssoCallbackLoading: false,\n error: action.error,\n user: null,\n token: null,\n refreshToken: null,\n accessTokenExpiresAt: null,\n refreshTokenExpiresAt: null,\n pendingMfa: null,\n twoFactorRequired: false,\n });\n }\n\n @Action(Logout)\n logout(ctx: StateContext<AuthStateModel>, action: Logout) {\n const { token, refreshToken, ssoProviders } = ctx.getState();\n this.ssoSession.clearAll();\n this.toObservable(this.options.beforeLocalLogout?.(ctx)).subscribe();\n ctx.patchState({\n ...AUTH_STATE_DEFAULTS,\n ssoProviders: this.options.preserveSsoProvidersOnLogout\n ? ssoProviders\n : [],\n });\n this.navigateToLogin();\n\n if (action.remote && token) {\n this.http\n .post<GatewayResponse<boolean>>(\n this.gatewayUrl(GATEWAY_AUTH_ENDPOINTS.logout),\n {\n refreshToken,\n deviceToken: this.deviceToken,\n },\n {\n headers: {\n Authorization: `Bearer ${token}`,\n noMessage: 'true',\n },\n },\n )\n .pipe(catchError(() => EMPTY))\n .subscribe();\n }\n }\n\n @Action(UpdateUserData)\n updateUserData(ctx: StateContext<AuthStateModel>, action: UpdateUserData) {\n ctx.patchState({\n user: action.user,\n });\n }\n\n @Action(UpdateTokens)\n updateTokens(ctx: StateContext<AuthStateModel>, action: UpdateTokens) {\n const tokenData = mapGatewayTokens(action.tokens);\n const state = ctx.getState();\n const updatedUser = state.user\n ? {\n ...state.user,\n token: tokenData.accessToken ?? state.user.token,\n accessToken: tokenData.accessToken ?? state.user.accessToken,\n refreshToken: tokenData.refreshToken ?? state.user.refreshToken,\n accessTokenExpiresAt: tokenData.accessTokenExpiresAt ?? undefined,\n refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt ?? undefined,\n }\n : state.user;\n\n ctx.patchState({\n token: tokenData.accessToken,\n refreshToken: tokenData.refreshToken,\n accessTokenExpiresAt: tokenData.accessTokenExpiresAt,\n refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt,\n user: updatedUser,\n });\n }\n\n @Action(ClearError)\n clearError(ctx: StateContext<AuthStateModel>) {\n ctx.patchState({ error: null });\n }\n\n @Action(ClearPendingMfa)\n clearPendingMfa(ctx: StateContext<AuthStateModel>) {\n ctx.patchState({ pendingMfa: null, twoFactorRequired: false });\n }\n\n private handleLoginResponse(\n ctx: StateContext<AuthStateModel>,\n session: GatewayLoginResponse | AuthLoginData,\n ): Observable<unknown> {\n if (session.requiresTwoFactor) {\n ctx.patchState({\n user: null,\n token: null,\n refreshToken: null,\n accessTokenExpiresAt: null,\n refreshTokenExpiresAt: null,\n pendingMfa: session.twoFactor,\n twoFactorRequired: true,\n loading: false,\n ssoCallbackLoading: false,\n error: null,\n });\n this.router.navigate([this.options.mfaRoute ?? '/auth/mfa'], {\n replaceUrl: true,\n });\n return of(null);\n }\n\n if (!hasGatewayTokens(session.tokens)) {\n ctx.dispatch(new LoginFailure('Login failed'));\n return of(null);\n }\n\n const tokenData = mapGatewayTokens(session.tokens);\n const user = mapGatewayUser(session.user, tokenData, session.delegations);\n\n ctx.patchState({\n user,\n token: tokenData.accessToken,\n refreshToken: tokenData.refreshToken,\n accessTokenExpiresAt: tokenData.accessTokenExpiresAt,\n refreshTokenExpiresAt: tokenData.refreshTokenExpiresAt,\n loading: false,\n ssoCallbackLoading: false,\n error: null,\n pendingMfa: null,\n twoFactorRequired: false,\n });\n\n return this.toObservable(this.options.afterLogin?.(session, ctx)).pipe(\n tap(() => {\n this.router.navigateByUrl(this.resolveAuthenticatedRoute(), {\n replaceUrl: true,\n });\n }),\n );\n }\n\n private get deviceToken(): string {\n return this.options.deviceToken ?? GATEWAY_AUTH_DEVICE_TOKEN;\n }\n\n private gatewayUrl(path: string): string {\n return buildGatewayUrl(this.options.getGatewayApiBaseUrl(), path);\n }\n\n private navigateToLogin(): void {\n this.router.navigate([this.options.loginRoute ?? '/auth/login'], {\n replaceUrl: true,\n });\n }\n\n private resolveAuthenticatedRoute(): string {\n const tree = this.router.parseUrl(this.router.url);\n const returnUrl = this.sanitizeLocalRoute(\n tree.queryParams['returnUrl'] as string | undefined,\n );\n if (returnUrl !== null) {\n return returnUrl;\n }\n\n const configuredRoute =\n typeof this.options.defaultAuthenticatedRoute === 'function'\n ? this.options.defaultAuthenticatedRoute()\n : this.options.defaultAuthenticatedRoute;\n return this.sanitizeLocalRoute(configuredRoute) ?? '/';\n }\n\n private sanitizeLocalRoute(route?: string | null): string | null {\n if (!route) {\n return null;\n }\n if (/^https?:\\/\\//i.test(route)) {\n return null;\n }\n return route.startsWith('/') ? route : `/${route}`;\n }\n\n private toObservable(result: GatewayAuthHookResult): Observable<unknown> {\n if (!result) {\n return of(null);\n }\n if (isObservable(result)) {\n return result;\n }\n if (result instanceof Promise) {\n return from(result);\n }\n return of(result);\n }\n}\n","import { Injectable, computed, inject } from '@angular/core';\nimport { select, Store } from '@ngxs/store';\nimport {\n ClearError,\n ClearPendingMfa,\n ExchangeSsoCode,\n LoadSsoProviders,\n Login,\n Logout,\n ResendMfa,\n StartSso,\n UpdateTokens,\n UpdateUserData,\n VerifyMfa,\n} from './gateway-auth.actions';\nimport { GatewayAuthState } from './gateway-auth.state';\nimport {\n AuthTokens,\n LoginRequest,\n SsoProvider,\n User,\n} from './gateway-auth.state.model';\nimport { isExpired } from './gateway-auth.utils';\n\n@Injectable({\n providedIn: 'root',\n})\nexport class GatewayAuthFacade {\n private readonly store = inject(Store);\n\n readonly user = select(GatewayAuthState.user);\n readonly loading = select(GatewayAuthState.loading);\n readonly mfaResendLoading = select(GatewayAuthState.mfaResendLoading);\n readonly ssoLoading = select(GatewayAuthState.ssoLoading);\n readonly ssoCallbackLoading = select(GatewayAuthState.ssoCallbackLoading);\n readonly error = select(GatewayAuthState.error);\n readonly token = select(GatewayAuthState.token);\n readonly refreshToken = select(GatewayAuthState.refreshToken);\n readonly accessTokenExpiresAt = select(GatewayAuthState.accessTokenExpiresAt);\n readonly refreshTokenExpiresAt = select(\n GatewayAuthState.refreshTokenExpiresAt,\n );\n readonly twoFactorRequired = select(GatewayAuthState.twoFactorRequired);\n readonly pendingMfa = select(GatewayAuthState.pendingMfa);\n readonly ssoProviders = select(GatewayAuthState.ssoProviders);\n readonly isAdmin = select(GatewayAuthState.isAdmin);\n readonly userDetails = select(GatewayAuthState.userDetails);\n\n readonly hasError = computed(() => this.error() !== null);\n readonly isReady = computed(() => !this.loading() && this.error() === null);\n readonly userDisplayName = computed(\n () => this.user()?.user?.displayName || '',\n );\n readonly userEmail = computed(() => this.user()?.user?.email || '');\n readonly hasUser = computed(() => this.user() !== null);\n readonly hasPendingMfa = computed(() => this.pendingMfa() !== null);\n\n readonly isAuthenticated = computed(() => {\n const token = this.token();\n const accessExpiresAt = this.accessTokenExpiresAt();\n if (token && !isExpired(accessExpiresAt)) {\n return true;\n }\n const refreshToken = this.refreshToken();\n const refreshExpiresAt = this.refreshTokenExpiresAt();\n return !!refreshToken && !isExpired(refreshExpiresAt);\n });\n\n login(loginRequest: LoginRequest): void {\n this.store.dispatch(new Login(loginRequest));\n }\n\n verifyMfa(code: string): void {\n this.store.dispatch(new VerifyMfa(code));\n }\n\n resendMfa(): void {\n this.store.dispatch(new ResendMfa());\n }\n\n loadSsoProviders(): void {\n this.store.dispatch(new LoadSsoProviders());\n }\n\n startSso(provider: SsoProvider): void {\n this.store.dispatch(new StartSso(provider));\n }\n\n exchangeSsoCode(code: string, state: string): void {\n this.store.dispatch(new ExchangeSsoCode(code, state));\n }\n\n logout(remote: boolean = false): void {\n this.store.dispatch(new Logout(remote));\n }\n\n updateUserData(user: User): void {\n this.store.dispatch(new UpdateUserData(user));\n }\n\n updateTokens(tokens: AuthTokens): void {\n this.store.dispatch(new UpdateTokens(tokens));\n }\n\n clearError(): void {\n this.store.dispatch(new ClearError());\n }\n\n clearPendingMfa(): void {\n this.store.dispatch(new ClearPendingMfa());\n }\n\n hasRole(role: string): boolean {\n const userRoles = this.user()?.user?.roles;\n return Array.isArray(userRoles) ? userRoles.includes(role) : false;\n }\n\n hasGroup(group: string): boolean {\n const userGroups = this.user()?.user?.groups;\n return Array.isArray(userGroups) ? userGroups.includes(group) : false;\n }\n\n isTokenExpired(): boolean {\n const accessExpiresAt = this.accessTokenExpiresAt();\n return accessExpiresAt ? isExpired(accessExpiresAt) : false;\n }\n}\n","import { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n computed,\n inject,\n OnInit,\n} from '@angular/core';\nimport { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';\nimport { Router } from '@angular/router';\nimport { Button } from '@masterteam/components/button';\nimport { TextField } from '@masterteam/components/text-field';\nimport { Icon } from '@masterteam/icons';\nimport { GatewayAuthFacade } from '../../gateway-auth.facade';\nimport { GATEWAY_AUTH_OPTIONS } from '../../gateway-auth.options';\n\n@Component({\n selector: 'mt-gateway-mfa',\n imports: [CommonModule, ReactiveFormsModule, Button, TextField, Icon],\n templateUrl: './gateway-mfa.html',\n styleUrls: ['./gateway-mfa.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class GatewayMfa implements OnInit {\n private readonly auth = inject(GatewayAuthFacade);\n private readonly fb = inject(FormBuilder);\n private readonly router = inject(Router);\n private readonly options = inject(GATEWAY_AUTH_OPTIONS);\n\n readonly pendingMfa = this.auth.pendingMfa;\n readonly loading = this.auth.loading;\n readonly resendLoading = this.auth.mfaResendLoading;\n readonly error = this.auth.error;\n\n readonly deliveryChannel = computed(\n () => this.pendingMfa()?.deliveryChannel || 'your configured channel',\n );\n readonly expiresAt = computed(() => this.pendingMfa()?.expiresAtUtc ?? null);\n\n readonly form = this.fb.group({\n code: ['', [Validators.required, Validators.pattern(/^[0-9]{4,8}$/)]],\n });\n\n ngOnInit(): void {\n if (!this.pendingMfa()) {\n this.router.navigate([this.options.loginRoute ?? '/auth/login'], {\n replaceUrl: true,\n });\n }\n }\n\n verify(): void {\n if (this.form.invalid) {\n this.form.markAllAsTouched();\n return;\n }\n\n const code = this.form.controls.code.value ?? '';\n this.form.reset();\n this.auth.verifyMfa(code);\n }\n\n resend(): void {\n this.form.reset();\n this.auth.resendMfa();\n }\n\n backToLogin(): void {\n this.auth.clearPendingMfa();\n this.router.navigate([this.options.loginRoute ?? '/auth/login'], {\n replaceUrl: true,\n });\n }\n}\n","<div\n class=\"min-h-screen w-screen flex items-center justify-center p-6 bg-surface-50\"\n>\n <div\n class=\"w-full max-w-md rounded-xl bg-white p-8 shadow-sm border border-surface-200\"\n >\n <div class=\"flex justify-center mb-6\">\n <div\n class=\"h-12 w-12 rounded-full bg-primary/10 flex items-center justify-center\"\n >\n <mt-icon\n icon=\"security.lock-01\"\n class=\"text-primary text-2xl\"\n ></mt-icon>\n </div>\n </div>\n\n <div class=\"text-center space-y-2 mb-6\">\n <h1 class=\"text-2xl font-semibold text-surface-950\">Verification code</h1>\n <p class=\"text-sm text-surface-600\">\n Enter the code sent through {{ deliveryChannel() }}.\n </p>\n @if (expiresAt(); as expiry) {\n <p class=\"text-xs text-surface-500\">\n Expires at {{ expiry | date: \"shortTime\" }}\n </p>\n }\n </div>\n\n <form [formGroup]=\"form\" (ngSubmit)=\"verify()\" class=\"space-y-4\">\n <mt-text-field\n label=\"Code\"\n formControlName=\"code\"\n [pInputs]=\"{ inputMode: 'numeric', autocomplete: 'one-time-code' }\"\n />\n\n @if (error(); as errorMessage) {\n <p class=\"text-sm text-red-500 text-center\">{{ errorMessage }}</p>\n }\n\n <mt-button\n label=\"Verify\"\n type=\"submit\"\n severity=\"primary\"\n size=\"large\"\n fluid\n [loading]=\"loading()\"\n [disabled]=\"form.invalid || loading()\"\n />\n </form>\n\n <div class=\"flex items-center justify-between gap-3 pt-5\">\n <mt-button\n label=\"Back\"\n type=\"button\"\n text\n [disabled]=\"loading()\"\n (onClick)=\"backToLogin()\"\n />\n <mt-button\n label=\"Resend code\"\n type=\"button\"\n variant=\"outlined\"\n [loading]=\"resendLoading()\"\n [disabled]=\"loading() || resendLoading()\"\n (onClick)=\"resend()\"\n />\n </div>\n </div>\n</div>\n","import { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n Component,\n inject,\n OnInit,\n signal,\n} from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { Button } from '@masterteam/components/button';\nimport { Icon } from '@masterteam/icons';\nimport { GatewayAuthFacade } from '../../gateway-auth.facade';\nimport { GATEWAY_AUTH_OPTIONS } from '../../gateway-auth.options';\nimport { GatewaySsoSession } from '../../gateway-sso-session.service';\n\n@Component({\n selector: 'mt-gateway-sso-callback',\n imports: [CommonModule, Button, Icon],\n templateUrl: './gateway-sso-callback.html',\n styleUrls: ['./gateway-sso-callback.css'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport default class GatewaySsoCallback implements OnInit {\n private readonly route = inject(ActivatedRoute);\n private readonly router = inject(Router);\n private readonly auth = inject(GatewayAuthFacade);\n private readonly options = inject(GATEWAY_AUTH_OPTIONS);\n private readonly ssoSession = new GatewaySsoSession();\n\n readonly loading = this.auth.ssoCallbackLoading;\n readonly exchangeError = this.auth.error;\n readonly callbackError = signal<string | null>(null);\n\n ngOnInit(): void {\n const params = this.route.snapshot.queryParamMap;\n const error = params.get('error');\n const errorCode = params.get('errorCode');\n const code = params.get('code');\n const state = params.get('state');\n\n this.ssoSession.clearCallbackQuery(\n this.options.ssoCallbackPath ?? '/auth/sso/callback',\n );\n\n if (!this.ssoSession.consumeExpectedState(state)) {\n this.callbackError.set(this.safeSsoMessage('invalid_state'));\n return;\n }\n\n if (error) {\n this.callbackError.set(this.safeSsoMessage(errorCode ?? 'sso_failed'));\n return;\n }\n\n if (!code || !state) {\n this.callbackError.set(this.safeSsoMessage('invalid_state'));\n return;\n }\n\n this.auth.exchangeSsoCode(code, state);\n }\n\n retry(): void {\n this.router.navigate([this.options.loginRoute ?? '/auth/login'], {\n replaceUrl: true,\n });\n }\n\n private safeSsoMessage(errorCode: string): string {\n const messages: Record<string, string> = {\n invalid_state: 'The sign-in session expired. Please try again.',\n sso_exchange_expired: 'The sign-in session expired. Please try again.',\n sso_exchange_used:\n 'This sign-in session was already used. Please try again.',\n sso_user_not_found: 'Your account is not configured for SSO.',\n sso_provisioning_not_allowed: 'Your account is not configured for SSO.',\n };\n\n return messages[errorCode] ?? 'SSO sign-in failed. Please try again.';\n }\n}\n","<div\n class=\"min-h-screen w-screen flex items-center justify-center p-6 bg-surface-50\"\n>\n <div\n class=\"w-full max-w-md rounded-xl bg-white p-8 shadow-sm border border-surface-200 text-center\"\n >\n @if (callbackError() || exchangeError(); as errorMessage) {\n <div class=\"space-y-5\">\n <mt-icon\n icon=\"alert.alert-circle\"\n class=\"text-red-500 text-4xl\"\n ></mt-icon>\n <div class=\"space-y-2\">\n <h1 class=\"text-xl font-semibold text-surface-950\">\n SSO sign-in failed\n </h1>\n <p class=\"text-sm text-surface-600\">{{ errorMessage }}</p>\n </div>\n <mt-button\n label=\"Back to sign in\"\n severity=\"primary\"\n (onClick)=\"retry()\"\n ></mt-button>\n </div>\n } @else {\n <div class=\"space-y-5\">\n <mt-icon\n icon=\"general.loading-02\"\n class=\"text-primary text-4xl animate-spin animate-duration-2000\"\n >\n </mt-icon>\n <div class=\"space-y-2\">\n <h1 class=\"text-xl font-semibold text-surface-950\">\n Completing sign-in\n </h1>\n <p class=\"text-sm text-surface-600\">\n Please wait while we finish the secure sign-in.\n </p>\n </div>\n </div>\n }\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masterteam/gateway-auth",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"directory": "../../../dist/masterteam/gateway-auth",
|
|
6
6
|
"linkDirectory": true,
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
|
-
"peerDependencies": {
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"@angular/common": "^21.2.8",
|
|
11
|
+
"@angular/core": "^21.2.8",
|
|
12
|
+
"@angular/forms": "^21.2.8",
|
|
13
|
+
"@angular/router": "^21.2.8",
|
|
14
|
+
"@ngxs/store": "^20.1.0",
|
|
15
|
+
"rxjs": "^7.8.2",
|
|
16
|
+
"@masterteam/components": "^0.0.164",
|
|
17
|
+
"@masterteam/icons": "^0.0.15"
|
|
18
|
+
},
|
|
10
19
|
"repository": {
|
|
11
20
|
"type": "git",
|
|
12
21
|
"url": "https://github.com/MasterteamSA/components.git"
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { InjectionToken, OnInit } from '@angular/core';
|
|
3
|
+
import { StateContext } from '@ngxs/store';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
import * as _masterteam_gateway_auth from '@masterteam/gateway-auth';
|
|
6
|
+
import * as _angular_forms from '@angular/forms';
|
|
7
|
+
|
|
1
8
|
interface GatewayResponse<T> {
|
|
2
9
|
endpoint: string;
|
|
3
10
|
status: number;
|
|
@@ -218,5 +225,245 @@ declare class GatewaySsoSession {
|
|
|
218
225
|
private get storage();
|
|
219
226
|
}
|
|
220
227
|
|
|
221
|
-
|
|
222
|
-
|
|
228
|
+
type UserDetails = GatewayUserDetails;
|
|
229
|
+
type User = GatewayMappedUser;
|
|
230
|
+
type LoginRequest = GatewayLoginRequest;
|
|
231
|
+
type ApiDateValue = NonNullable<GatewayAuthTokens['accessTokenExpiresAt']>;
|
|
232
|
+
type AuthTokens = GatewayAuthTokens;
|
|
233
|
+
type AuthLoginData = GatewayLoginResponse;
|
|
234
|
+
type AuthRefreshData = GatewayRefreshData;
|
|
235
|
+
type TwoFactorChallenge = GatewayTwoFactorChallenge;
|
|
236
|
+
type SsoProvider = GatewaySsoProvider;
|
|
237
|
+
type Response<T> = GatewayResponse<T>;
|
|
238
|
+
interface AuthStateModel {
|
|
239
|
+
user: User | null;
|
|
240
|
+
token: string | null;
|
|
241
|
+
refreshToken: string | null;
|
|
242
|
+
accessTokenExpiresAt: string | null;
|
|
243
|
+
refreshTokenExpiresAt: string | null;
|
|
244
|
+
loading: boolean;
|
|
245
|
+
mfaResendLoading: boolean;
|
|
246
|
+
ssoLoading: boolean;
|
|
247
|
+
ssoCallbackLoading: boolean;
|
|
248
|
+
error: string | null;
|
|
249
|
+
twoFactorRequired: boolean;
|
|
250
|
+
pendingMfa: TwoFactorChallenge | null;
|
|
251
|
+
ssoProviders: SsoProvider[];
|
|
252
|
+
}
|
|
253
|
+
declare const AUTH_STATE_DEFAULTS: AuthStateModel;
|
|
254
|
+
declare function sanitizePersistedAuthState(obj: Partial<AuthStateModel> | null): {
|
|
255
|
+
loading: boolean;
|
|
256
|
+
mfaResendLoading: boolean;
|
|
257
|
+
ssoLoading: boolean;
|
|
258
|
+
ssoCallbackLoading: boolean;
|
|
259
|
+
error: null;
|
|
260
|
+
twoFactorRequired: boolean;
|
|
261
|
+
pendingMfa: null;
|
|
262
|
+
ssoProviders: never[];
|
|
263
|
+
user: User | null;
|
|
264
|
+
token: string | null;
|
|
265
|
+
refreshToken: string | null;
|
|
266
|
+
accessTokenExpiresAt: string | null;
|
|
267
|
+
refreshTokenExpiresAt: string | null;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
type GatewayAuthHookResult = void | null | Observable<unknown> | Promise<unknown>;
|
|
271
|
+
interface GatewayAuthOptions {
|
|
272
|
+
getGatewayApiBaseUrl: () => string | null | undefined;
|
|
273
|
+
deviceToken?: string;
|
|
274
|
+
platform?: GatewayPlatform;
|
|
275
|
+
loginRoute?: string;
|
|
276
|
+
mfaRoute?: string;
|
|
277
|
+
ssoCallbackPath?: string;
|
|
278
|
+
defaultAuthenticatedRoute?: string | (() => string | null | undefined);
|
|
279
|
+
preserveSsoProvidersOnLogout?: boolean;
|
|
280
|
+
afterLogin?: (session: GatewayLoginResponse, ctx: StateContext<AuthStateModel>) => GatewayAuthHookResult;
|
|
281
|
+
beforeLocalLogout?: (ctx: StateContext<AuthStateModel>) => GatewayAuthHookResult;
|
|
282
|
+
}
|
|
283
|
+
declare const GATEWAY_AUTH_OPTIONS: InjectionToken<GatewayAuthOptions>;
|
|
284
|
+
|
|
285
|
+
declare class Login {
|
|
286
|
+
payload: LoginRequest;
|
|
287
|
+
static readonly type = "[Auth] Login";
|
|
288
|
+
constructor(payload: LoginRequest);
|
|
289
|
+
}
|
|
290
|
+
declare class VerifyMfa {
|
|
291
|
+
code: string;
|
|
292
|
+
static readonly type = "[Auth] Verify MFA";
|
|
293
|
+
constructor(code: string);
|
|
294
|
+
}
|
|
295
|
+
declare class ResendMfa {
|
|
296
|
+
static readonly type = "[Auth] Resend MFA";
|
|
297
|
+
}
|
|
298
|
+
declare class LoadSsoProviders {
|
|
299
|
+
static readonly type = "[Auth] Load SSO Providers";
|
|
300
|
+
}
|
|
301
|
+
declare class StartSso {
|
|
302
|
+
provider: SsoProvider;
|
|
303
|
+
static readonly type = "[Auth] Start SSO";
|
|
304
|
+
constructor(provider: SsoProvider);
|
|
305
|
+
}
|
|
306
|
+
declare class ExchangeSsoCode {
|
|
307
|
+
code: string;
|
|
308
|
+
state: string;
|
|
309
|
+
static readonly type = "[Auth] Exchange SSO Code";
|
|
310
|
+
constructor(code: string, state: string);
|
|
311
|
+
}
|
|
312
|
+
declare class LoginSuccess {
|
|
313
|
+
session: AuthLoginData;
|
|
314
|
+
static readonly type = "[Auth] Login Success";
|
|
315
|
+
constructor(session: AuthLoginData);
|
|
316
|
+
}
|
|
317
|
+
declare class LoginFailure {
|
|
318
|
+
error: string;
|
|
319
|
+
static readonly type = "[Auth] Login Failure";
|
|
320
|
+
constructor(error: string);
|
|
321
|
+
}
|
|
322
|
+
declare class Logout {
|
|
323
|
+
remote: boolean;
|
|
324
|
+
static readonly type = "[Auth] Logout";
|
|
325
|
+
constructor(remote?: boolean);
|
|
326
|
+
}
|
|
327
|
+
declare class UpdateUserData {
|
|
328
|
+
user: User;
|
|
329
|
+
static readonly type = "[Auth] Update User Data";
|
|
330
|
+
constructor(user: User);
|
|
331
|
+
}
|
|
332
|
+
declare class UpdateTokens {
|
|
333
|
+
tokens: AuthTokens;
|
|
334
|
+
static readonly type = "[Auth] Update Tokens";
|
|
335
|
+
constructor(tokens: AuthTokens);
|
|
336
|
+
}
|
|
337
|
+
declare class ClearError {
|
|
338
|
+
static readonly type = "[Auth] Clear Error";
|
|
339
|
+
}
|
|
340
|
+
declare class ClearPendingMfa {
|
|
341
|
+
static readonly type = "[Auth] Clear Pending MFA";
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
declare class GatewayAuthState {
|
|
345
|
+
private readonly http;
|
|
346
|
+
private readonly options;
|
|
347
|
+
private readonly router;
|
|
348
|
+
private readonly ssoSession;
|
|
349
|
+
static user(state: AuthStateModel): User | null;
|
|
350
|
+
static loading(state: AuthStateModel): boolean;
|
|
351
|
+
static mfaResendLoading(state: AuthStateModel): boolean;
|
|
352
|
+
static ssoLoading(state: AuthStateModel): boolean;
|
|
353
|
+
static ssoCallbackLoading(state: AuthStateModel): boolean;
|
|
354
|
+
static error(state: AuthStateModel): string | null;
|
|
355
|
+
static token(state: AuthStateModel): string | null;
|
|
356
|
+
static refreshToken(state: AuthStateModel): string | null;
|
|
357
|
+
static accessTokenExpiresAt(state: AuthStateModel): string | null;
|
|
358
|
+
static refreshTokenExpiresAt(state: AuthStateModel): string | null;
|
|
359
|
+
static twoFactorRequired(state: AuthStateModel): boolean;
|
|
360
|
+
static pendingMfa(state: AuthStateModel): GatewayTwoFactorChallenge | null;
|
|
361
|
+
static ssoProviders(state: AuthStateModel): SsoProvider[];
|
|
362
|
+
static isAdmin(state: AuthStateModel): boolean;
|
|
363
|
+
static userDetails(state: AuthStateModel): _masterteam_gateway_auth.GatewayUserDetails | null;
|
|
364
|
+
login(ctx: StateContext<AuthStateModel>, action: Login): Observable<unknown>;
|
|
365
|
+
verifyMfa(ctx: StateContext<AuthStateModel>, action: VerifyMfa): Observable<unknown>;
|
|
366
|
+
resendMfa(ctx: StateContext<AuthStateModel>): Observable<GatewayResponse<GatewayTwoFactorChallenge> | null>;
|
|
367
|
+
loadSsoProviders(ctx: StateContext<AuthStateModel>): Observable<GatewayResponse<GatewaySsoProvidersData> | null>;
|
|
368
|
+
startSso(ctx: StateContext<AuthStateModel>, action: StartSso): void;
|
|
369
|
+
exchangeSsoCode(ctx: StateContext<AuthStateModel>, action: ExchangeSsoCode): Observable<unknown>;
|
|
370
|
+
loginSuccess(ctx: StateContext<AuthStateModel>, action: LoginSuccess): Observable<unknown>;
|
|
371
|
+
loginFailure(ctx: StateContext<AuthStateModel>, action: LoginFailure): void;
|
|
372
|
+
logout(ctx: StateContext<AuthStateModel>, action: Logout): void;
|
|
373
|
+
updateUserData(ctx: StateContext<AuthStateModel>, action: UpdateUserData): void;
|
|
374
|
+
updateTokens(ctx: StateContext<AuthStateModel>, action: UpdateTokens): void;
|
|
375
|
+
clearError(ctx: StateContext<AuthStateModel>): void;
|
|
376
|
+
clearPendingMfa(ctx: StateContext<AuthStateModel>): void;
|
|
377
|
+
private handleLoginResponse;
|
|
378
|
+
private get deviceToken();
|
|
379
|
+
private gatewayUrl;
|
|
380
|
+
private navigateToLogin;
|
|
381
|
+
private resolveAuthenticatedRoute;
|
|
382
|
+
private sanitizeLocalRoute;
|
|
383
|
+
private toObservable;
|
|
384
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GatewayAuthState, never>;
|
|
385
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<GatewayAuthState>;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
declare class GatewayAuthFacade {
|
|
389
|
+
private readonly store;
|
|
390
|
+
readonly user: _angular_core.Signal<_masterteam_gateway_auth.GatewayMappedUser | null>;
|
|
391
|
+
readonly loading: _angular_core.Signal<boolean>;
|
|
392
|
+
readonly mfaResendLoading: _angular_core.Signal<boolean>;
|
|
393
|
+
readonly ssoLoading: _angular_core.Signal<boolean>;
|
|
394
|
+
readonly ssoCallbackLoading: _angular_core.Signal<boolean>;
|
|
395
|
+
readonly error: _angular_core.Signal<string | null>;
|
|
396
|
+
readonly token: _angular_core.Signal<string | null>;
|
|
397
|
+
readonly refreshToken: _angular_core.Signal<string | null>;
|
|
398
|
+
readonly accessTokenExpiresAt: _angular_core.Signal<string | null>;
|
|
399
|
+
readonly refreshTokenExpiresAt: _angular_core.Signal<string | null>;
|
|
400
|
+
readonly twoFactorRequired: _angular_core.Signal<boolean>;
|
|
401
|
+
readonly pendingMfa: _angular_core.Signal<_masterteam_gateway_auth.GatewayTwoFactorChallenge | null>;
|
|
402
|
+
readonly ssoProviders: _angular_core.Signal<_masterteam_gateway_auth.GatewaySsoProvider[]>;
|
|
403
|
+
readonly isAdmin: _angular_core.Signal<boolean>;
|
|
404
|
+
readonly userDetails: _angular_core.Signal<_masterteam_gateway_auth.GatewayUserDetails | null>;
|
|
405
|
+
readonly hasError: _angular_core.Signal<boolean>;
|
|
406
|
+
readonly isReady: _angular_core.Signal<boolean>;
|
|
407
|
+
readonly userDisplayName: _angular_core.Signal<string>;
|
|
408
|
+
readonly userEmail: _angular_core.Signal<string>;
|
|
409
|
+
readonly hasUser: _angular_core.Signal<boolean>;
|
|
410
|
+
readonly hasPendingMfa: _angular_core.Signal<boolean>;
|
|
411
|
+
readonly isAuthenticated: _angular_core.Signal<boolean>;
|
|
412
|
+
login(loginRequest: LoginRequest): void;
|
|
413
|
+
verifyMfa(code: string): void;
|
|
414
|
+
resendMfa(): void;
|
|
415
|
+
loadSsoProviders(): void;
|
|
416
|
+
startSso(provider: SsoProvider): void;
|
|
417
|
+
exchangeSsoCode(code: string, state: string): void;
|
|
418
|
+
logout(remote?: boolean): void;
|
|
419
|
+
updateUserData(user: User): void;
|
|
420
|
+
updateTokens(tokens: AuthTokens): void;
|
|
421
|
+
clearError(): void;
|
|
422
|
+
clearPendingMfa(): void;
|
|
423
|
+
hasRole(role: string): boolean;
|
|
424
|
+
hasGroup(group: string): boolean;
|
|
425
|
+
isTokenExpired(): boolean;
|
|
426
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GatewayAuthFacade, never>;
|
|
427
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<GatewayAuthFacade>;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
declare class GatewayMfa implements OnInit {
|
|
431
|
+
private readonly auth;
|
|
432
|
+
private readonly fb;
|
|
433
|
+
private readonly router;
|
|
434
|
+
private readonly options;
|
|
435
|
+
readonly pendingMfa: _angular_core.Signal<_masterteam_gateway_auth.GatewayTwoFactorChallenge | null>;
|
|
436
|
+
readonly loading: _angular_core.Signal<boolean>;
|
|
437
|
+
readonly resendLoading: _angular_core.Signal<boolean>;
|
|
438
|
+
readonly error: _angular_core.Signal<string | null>;
|
|
439
|
+
readonly deliveryChannel: _angular_core.Signal<string>;
|
|
440
|
+
readonly expiresAt: _angular_core.Signal<string | null>;
|
|
441
|
+
readonly form: _angular_forms.FormGroup<{
|
|
442
|
+
code: _angular_forms.FormControl<string | null>;
|
|
443
|
+
}>;
|
|
444
|
+
ngOnInit(): void;
|
|
445
|
+
verify(): void;
|
|
446
|
+
resend(): void;
|
|
447
|
+
backToLogin(): void;
|
|
448
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GatewayMfa, never>;
|
|
449
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<GatewayMfa, "mt-gateway-mfa", never, {}, {}, never, never, true, never>;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
declare class GatewaySsoCallback implements OnInit {
|
|
453
|
+
private readonly route;
|
|
454
|
+
private readonly router;
|
|
455
|
+
private readonly auth;
|
|
456
|
+
private readonly options;
|
|
457
|
+
private readonly ssoSession;
|
|
458
|
+
readonly loading: _angular_core.Signal<boolean>;
|
|
459
|
+
readonly exchangeError: _angular_core.Signal<string | null>;
|
|
460
|
+
readonly callbackError: _angular_core.WritableSignal<string | null>;
|
|
461
|
+
ngOnInit(): void;
|
|
462
|
+
retry(): void;
|
|
463
|
+
private safeSsoMessage;
|
|
464
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<GatewaySsoCallback, never>;
|
|
465
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<GatewaySsoCallback, "mt-gateway-sso-callback", never, {}, {}, never, never, true, never>;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export { AUTH_STATE_DEFAULTS, ClearError, ClearPendingMfa, ExchangeSsoCode, GATEWAY_AUTH_DEVICE_TOKEN, GATEWAY_AUTH_ENDPOINTS, GATEWAY_AUTH_OPTIONS, GatewayAuthFacade, GatewayAuthState, GatewayMfa, GatewaySsoCallback, GatewaySsoSession, LoadSsoProviders, Login, LoginFailure, LoginSuccess, Logout, ResendMfa, StartSso, UpdateTokens, UpdateUserData, VerifyMfa, buildGatewayUrl, buildSsoStartUrl, createSecureClientState, getGatewayErrorMessage, hasGatewayTokens, isExpired, mapGatewayTokens, mapGatewayUser, normalizeGatewayBase, resolveApiDateValue, sanitizePersistedAuthState };
|
|
469
|
+
export type { ApiDateValue, AuthLoginData, AuthRefreshData, AuthStateModel, AuthTokens, BuildSsoStartUrlOptions, GatewayApiDateValue, GatewayAuthHookResult, GatewayAuthOptions, GatewayAuthTokens, GatewayExternalTokenExchangeRequest, GatewayLoginRequest, GatewayLoginResponse, GatewayLogoutRequest, GatewayMappedTokens, GatewayMappedUser, GatewayNafathStartData, GatewayNafathStartRequest, GatewayNafathStatusData, GatewayNafathStatusRequest, GatewayPlatform, GatewayRefreshData, GatewayRefreshRequest, GatewayResendMfaRequest, GatewayResponse, GatewaySsoExchangeRequest, GatewaySsoFlow, GatewaySsoProtocol, GatewaySsoProvider, GatewaySsoProvidersData, GatewayTwoFactorChallenge, GatewayUserDetails, GatewayVerifyMfaRequest, LoginRequest, Response, SsoProvider, TwoFactorChallenge, User, UserDetails };
|