• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

damienbod / angular-auth-oidc-client / 7680333832

27 Jan 2024 06:09PM UTC coverage: 92.562% (-4.5%) from 97.056%
7680333832

Pull #1848

github

web-flow
Merge d3f9d96d0 into 2a2ca062b
Pull Request #1848: moving to strict mode

695 of 818 branches covered (0.0%)

Branch coverage included in aggregate %.

217 of 290 new or added lines in 48 files covered. (74.83%)

11 existing lines in 6 files now uncovered.

2553 of 2691 relevant lines covered (94.87%)

8.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.73
/projects/angular-auth-oidc-client/src/lib/utils/url/url.service.ts
1
import { HttpParams } from '@angular/common/http';
2
import { Injectable } from '@angular/core';
3
import { Observable, of } from 'rxjs';
4
import { map } from 'rxjs/operators';
5
import { AuthOptions } from '../../auth-options';
6
import { OpenIdConfiguration } from '../../config/openid-configuration';
7
import { FlowsDataService } from '../../flows/flows-data.service';
8
import { LoggerService } from '../../logging/logger.service';
9
import { StoragePersistenceService } from '../../storage/storage-persistence.service';
10
import { JwtWindowCryptoService } from '../../validation/jwt-window-crypto.service';
11
import { FlowHelper } from '../flowHelper/flow-helper.service';
12
import { UriEncoder } from './uri-encoder';
13

14
const CALLBACK_PARAMS_TO_CHECK = ['code', 'state', 'token', 'id_token'];
1✔
15
const AUTH0_ENDPOINT = 'auth0.com';
1✔
16

17
@Injectable({ providedIn: 'root' })
18
export class UrlService {
1✔
19
  constructor(
20
    private readonly loggerService: LoggerService,
89✔
21
    private readonly flowsDataService: FlowsDataService,
89✔
22
    private readonly flowHelper: FlowHelper,
89✔
23
    private readonly storagePersistenceService: StoragePersistenceService,
89✔
24
    private readonly jwtWindowCryptoService: JwtWindowCryptoService
89✔
25
  ) {}
26

27
  getUrlParameter(urlToCheck: string, name: string): string {
28
    if (!urlToCheck) {
33✔
29
      return '';
1✔
30
    }
31

32
    if (!name) {
32✔
33
      return '';
1✔
34
    }
35

36
    name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
31✔
37
    const regex = new RegExp('[\\?&#]' + name + '=([^&#]*)');
31✔
38
    const results = regex.exec(urlToCheck);
31✔
39

40
    return results === null ? '' : decodeURIComponent(results[1]);
31✔
41
  }
42

43
  isCallbackFromSts(currentUrl: string): boolean {
44
    return CALLBACK_PARAMS_TO_CHECK.some(
5✔
45
      (x) => !!this.getUrlParameter(currentUrl, x)
14✔
46
    );
47
  }
48

49
  getRefreshSessionSilentRenewUrl(
50
    config: OpenIdConfiguration,
51
    customParams?: { [key: string]: string | number | boolean }
52
  ): Observable<string | null> {
53
    if (this.flowHelper.isCurrentFlowCodeFlow(config)) {
3✔
54
      return this.createUrlCodeFlowWithSilentRenew(config, customParams);
1✔
55
    }
56

57
    return of(this.createUrlImplicitFlowWithSilentRenew(config, customParams));
2✔
58
  }
59

60
  getAuthorizeParUrl(
61
    requestUri: string,
62
    configuration: OpenIdConfiguration
63
  ): string | null {
64
    const authWellKnownEndPoints = this.storagePersistenceService.read(
4✔
65
      'authWellKnownEndPoints',
66
      configuration
67
    );
68

69
    if (!authWellKnownEndPoints) {
4✔
70
      this.loggerService.logError(
1✔
71
        configuration,
72
        'authWellKnownEndpoints is undefined'
73
      );
74

75
      return null;
1✔
76
    }
77

78
    const authorizationEndpoint = authWellKnownEndPoints.authorizationEndpoint;
3✔
79

80
    if (!authorizationEndpoint) {
3✔
81
      this.loggerService.logError(
1✔
82
        configuration,
83
        `Can not create an authorize URL when authorizationEndpoint is '${authorizationEndpoint}'`
84
      );
85

86
      return null;
1✔
87
    }
88

89
    const { clientId } = configuration;
2✔
90

91
    if (!clientId) {
2✔
92
      this.loggerService.logError(
1✔
93
        configuration,
94
        `getAuthorizeParUrl could not add clientId because it was: `,
95
        clientId
96
      );
97

98
      return null;
1✔
99
    }
100

101
    const urlParts = authorizationEndpoint.split('?');
1✔
102
    const authorizationUrl = urlParts[0];
1✔
103
    const existingParams = urlParts[1];
1✔
104
    let params = this.createHttpParams(existingParams);
1✔
105

106
    params = params.set('request_uri', requestUri);
1✔
107
    params = params.append('client_id', clientId);
1✔
108

109
    return `${authorizationUrl}?${params}`;
1✔
110
  }
111

112
  getAuthorizeUrl(
113
    config: OpenIdConfiguration | null,
114
    authOptions?: AuthOptions
115
  ): Observable<string | null> {
116
    if (!config) {
5!
NEW
117
      return of(null);
×
118
    }
119

120
    if (this.flowHelper.isCurrentFlowCodeFlow(config)) {
5✔
121
      return this.createUrlCodeFlowAuthorize(config, authOptions);
3✔
122
    }
123

124
    return of(this.createUrlImplicitFlowAuthorize(config, authOptions) || '');
2✔
125
  }
126

127
  getEndSessionEndpoint(configuration: OpenIdConfiguration): {
128
    url: string;
129
    existingParams: string;
130
  } {
131
    const authWellKnownEndPoints = this.storagePersistenceService.read(
6✔
132
      'authWellKnownEndPoints',
133
      configuration
134
    );
135
    const endSessionEndpoint = authWellKnownEndPoints?.endSessionEndpoint;
6✔
136

137
    if (!endSessionEndpoint) {
6✔
138
      return {
1✔
139
        url: '',
140
        existingParams: '',
141
      };
142
    }
143

144
    const urlParts = endSessionEndpoint.split('?');
5✔
145
    const url = urlParts[0];
5✔
146
    const existingParams = urlParts[1] ?? '';
5✔
147

148
    return {
5✔
149
      url,
150
      existingParams,
151
    };
152
  }
153

154
  getEndSessionUrl(
155
    configuration: OpenIdConfiguration | null,
156
    customParams?: { [p: string]: string | number | boolean }
157
  ): string | null {
158
    if (!configuration) {
7!
NEW
159
      return null;
×
160
    }
161

162
    const idToken = this.storagePersistenceService.getIdToken(configuration);
7✔
163
    const { customParamsEndSessionRequest } = configuration;
7✔
164
    const mergedParams = { ...customParamsEndSessionRequest, ...customParams };
7✔
165

166
    return this.createEndSessionUrl(idToken, configuration, mergedParams);
7✔
167
  }
168

169
  createRevocationEndpointBodyAccessToken(
170
    token: any,
171
    configuration: OpenIdConfiguration
172
  ): string | null {
173
    const clientId = this.getClientId(configuration);
2✔
174

175
    if (!clientId) {
2✔
176
      return null;
1✔
177
    }
178

179
    let params = this.createHttpParams();
1✔
180

181
    params = params.set('client_id', clientId);
1✔
182
    params = params.set('token', token);
1✔
183
    params = params.set('token_type_hint', 'access_token');
1✔
184

185
    return params.toString();
1✔
186
  }
187

188
  createRevocationEndpointBodyRefreshToken(
189
    token: any,
190
    configuration: OpenIdConfiguration
191
  ): string | null {
192
    const clientId = this.getClientId(configuration);
2✔
193

194
    if (!clientId) {
2✔
195
      return null;
1✔
196
    }
197

198
    let params = this.createHttpParams();
1✔
199

200
    params = params.set('client_id', clientId);
1✔
201
    params = params.set('token', token);
1✔
202
    params = params.set('token_type_hint', 'refresh_token');
1✔
203

204
    return params.toString();
1✔
205
  }
206

207
  getRevocationEndpointUrl(configuration: OpenIdConfiguration): string | null {
208
    const authWellKnownEndPoints = this.storagePersistenceService.read(
4✔
209
      'authWellKnownEndPoints',
210
      configuration
211
    );
212
    const revocationEndpoint = authWellKnownEndPoints?.revocationEndpoint;
4✔
213

214
    if (!revocationEndpoint) {
4✔
215
      return null;
2✔
216
    }
217

218
    const urlParts = revocationEndpoint.split('?');
2✔
219

220
    return urlParts[0];
2✔
221
  }
222

223
  createBodyForCodeFlowCodeRequest(
224
    code: string,
225
    configuration: OpenIdConfiguration,
226
    customTokenParams?: { [p: string]: string | number | boolean }
227
  ): string | null {
228
    const clientId = this.getClientId(configuration);
7✔
229

230
    if (!clientId) {
7✔
231
      return null;
2✔
232
    }
233

234
    let params = this.createHttpParams();
5✔
235

236
    params = params.set('grant_type', 'authorization_code');
5✔
237
    params = params.set('client_id', clientId);
5✔
238

239
    if (!configuration.disablePkce) {
5✔
240
      const codeVerifier = this.flowsDataService.getCodeVerifier(configuration);
5✔
241

242
      if (!codeVerifier) {
5✔
243
        this.loggerService.logError(
1✔
244
          configuration,
245
          `CodeVerifier is not set `,
246
          codeVerifier
247
        );
248

249
        return null;
1✔
250
      }
251

252
      params = params.set('code_verifier', codeVerifier);
4✔
253
    }
254

255
    params = params.set('code', code);
4✔
256

257
    if (customTokenParams) {
4✔
258
      params = this.appendCustomParams({ ...customTokenParams }, params);
1✔
259
    }
260

261
    const silentRenewUrl = this.getSilentRenewUrl(configuration);
4✔
262

263
    if (
4✔
264
      this.flowsDataService.isSilentRenewRunning(configuration) &&
6✔
265
      silentRenewUrl
266
    ) {
267
      params = params.set('redirect_uri', silentRenewUrl);
2✔
268

269
      return params.toString();
2✔
270
    }
271

272
    const redirectUrl = this.getRedirectUrl(configuration);
2✔
273

274
    if (!redirectUrl) {
2✔
275
      return null;
1✔
276
    }
277

278
    params = params.set('redirect_uri', redirectUrl);
1✔
279

280
    return params.toString();
1✔
281
  }
282

283
  createBodyForCodeFlowRefreshTokensRequest(
284
    refreshToken: string,
285
    configuration: OpenIdConfiguration,
286
    customParamsRefresh?: { [key: string]: string | number | boolean }
287
  ): string | null {
288
    const clientId = this.getClientId(configuration);
3✔
289

290
    if (!clientId) {
3✔
291
      return null;
1✔
292
    }
293

294
    let params = this.createHttpParams();
2✔
295

296
    params = params.set('grant_type', 'refresh_token');
2✔
297
    params = params.set('client_id', clientId);
2✔
298
    params = params.set('refresh_token', refreshToken);
2✔
299

300
    if (customParamsRefresh) {
2✔
301
      params = this.appendCustomParams({ ...customParamsRefresh }, params);
1✔
302
    }
303

304
    return params.toString();
2✔
305
  }
306

307
  createBodyForParCodeFlowRequest(
308
    configuration: OpenIdConfiguration,
309
    authOptions?: AuthOptions
310
  ): Observable<string | null> {
311
    const redirectUrl = this.getRedirectUrl(configuration, authOptions);
5✔
312

313
    if (!redirectUrl) {
5✔
314
      return of(null);
1✔
315
    }
316

317
    const state =
318
      this.flowsDataService.getExistingOrCreateAuthStateControl(configuration);
4✔
319
    const nonce = this.flowsDataService.createNonce(configuration);
4✔
320

321
    this.loggerService.logDebug(
4✔
322
      configuration,
323
      'Authorize created. adding myautostate: ' + state
324
    );
325

326
    // code_challenge with "S256"
327
    const codeVerifier =
328
      this.flowsDataService.createCodeVerifier(configuration);
4✔
329

330
    return this.jwtWindowCryptoService.generateCodeChallenge(codeVerifier).pipe(
4✔
331
      map((codeChallenge: string) => {
332
        const {
333
          clientId,
334
          responseType,
335
          scope,
336
          hdParam,
337
          customParamsAuthRequest,
338
        } = configuration;
4✔
339
        let params = this.createHttpParams('');
4✔
340

341
        params = params.set('client_id', clientId ?? '');
4!
342
        params = params.append('redirect_uri', redirectUrl);
4✔
343
        params = params.append('response_type', responseType ?? '');
4!
344
        params = params.append('scope', scope ?? '');
4!
345
        params = params.append('nonce', nonce);
4✔
346
        params = params.append('state', state);
4✔
347
        params = params.append('code_challenge', codeChallenge);
4✔
348
        params = params.append('code_challenge_method', 'S256');
4✔
349

350
        if (hdParam) {
4✔
351
          params = params.append('hd', hdParam);
3✔
352
        }
353

354
        if (customParamsAuthRequest) {
4✔
355
          params = this.appendCustomParams(
2✔
356
            { ...customParamsAuthRequest },
357
            params
358
          );
359
        }
360

361
        if (authOptions?.customParams) {
4✔
362
          params = this.appendCustomParams(
1✔
363
            { ...authOptions.customParams },
364
            params
365
          );
366
        }
367

368
        return params.toString();
4✔
369
      })
370
    );
371
  }
372

373
  getPostLogoutRedirectUrl(configuration: OpenIdConfiguration): string | null {
374
    const { postLogoutRedirectUri } = configuration;
6✔
375

376
    if (!postLogoutRedirectUri) {
6✔
377
      this.loggerService.logError(
1✔
378
        configuration,
379
        `could not get postLogoutRedirectUri, was: `,
380
        postLogoutRedirectUri
381
      );
382

383
      return null;
1✔
384
    }
385

386
    return postLogoutRedirectUri;
5✔
387
  }
388

389
  private createEndSessionUrl(
390
    idTokenHint: string,
391
    configuration: OpenIdConfiguration,
392
    customParamsEndSession?: { [p: string]: string | number | boolean }
393
  ): string | null {
394
    // Auth0 needs a special logout url
395
    // See https://auth0.com/docs/api/authentication#logout
396

397
    if (this.isAuth0Endpoint(configuration)) {
7✔
398
      return this.composeAuth0Endpoint(configuration);
1✔
399
    }
400

401
    const { url, existingParams } = this.getEndSessionEndpoint(configuration);
6✔
402

403
    if (!url) {
6✔
404
      return null;
1✔
405
    }
406

407
    let params = this.createHttpParams(existingParams);
5✔
408

409
    if (!!idTokenHint) {
5✔
410
      params = params.set('id_token_hint', idTokenHint);
4✔
411
    }
412

413
    const postLogoutRedirectUri = this.getPostLogoutRedirectUrl(configuration);
5✔
414

415
    if (postLogoutRedirectUri) {
5✔
416
      params = params.append('post_logout_redirect_uri', postLogoutRedirectUri);
4✔
417
    }
418

419
    if (customParamsEndSession) {
5✔
420
      params = this.appendCustomParams({ ...customParamsEndSession }, params);
5✔
421
    }
422

423
    return `${url}?${params}`;
5✔
424
  }
425

426
  private createAuthorizeUrl(
427
    codeChallenge: string,
428
    redirectUrl: string,
429
    nonce: string,
430
    state: string,
431
    configuration: OpenIdConfiguration,
432
    prompt?: string,
433
    customRequestParams?: { [key: string]: string | number | boolean }
434
  ): string {
435
    const authWellKnownEndPoints = this.storagePersistenceService.read(
23✔
436
      'authWellKnownEndPoints',
437
      configuration
438
    );
439
    const authorizationEndpoint = authWellKnownEndPoints?.authorizationEndpoint;
23✔
440

441
    if (!authorizationEndpoint) {
23✔
442
      this.loggerService.logError(
2✔
443
        configuration,
444
        `Can not create an authorize URL when authorizationEndpoint is '${authorizationEndpoint}'`
445
      );
446

447
      return '';
2✔
448
    }
449

450
    const { clientId, responseType, scope, hdParam, customParamsAuthRequest } =
451
      configuration;
21✔
452

453
    if (!clientId) {
21✔
454
      this.loggerService.logError(
1✔
455
        configuration,
456
        `createAuthorizeUrl could not add clientId because it was: `,
457
        clientId
458
      );
459

460
      return '';
1✔
461
    }
462

463
    if (!responseType) {
20✔
464
      this.loggerService.logError(
1✔
465
        configuration,
466
        `createAuthorizeUrl could not add responseType because it was: `,
467
        responseType
468
      );
469

470
      return '';
1✔
471
    }
472

473
    if (!scope) {
19✔
474
      this.loggerService.logError(
1✔
475
        configuration,
476
        `createAuthorizeUrl could not add scope because it was: `,
477
        scope
478
      );
479

480
      return '';
1✔
481
    }
482

483
    const urlParts = authorizationEndpoint.split('?');
18✔
484
    const authorizationUrl = urlParts[0];
18✔
485
    const existingParams = urlParts[1];
18✔
486
    let params = this.createHttpParams(existingParams);
18✔
487

488
    params = params.set('client_id', clientId);
18✔
489
    params = params.append('redirect_uri', redirectUrl);
18✔
490
    params = params.append('response_type', responseType);
18✔
491
    params = params.append('scope', scope);
18✔
492
    params = params.append('nonce', nonce);
18✔
493
    params = params.append('state', state);
18✔
494

495
    if (this.flowHelper.isCurrentFlowCodeFlow(configuration)) {
18✔
496
      params = params.append('code_challenge', codeChallenge);
3✔
497
      params = params.append('code_challenge_method', 'S256');
3✔
498
    }
499

500
    const mergedParams = { ...customParamsAuthRequest, ...customRequestParams };
18✔
501

502
    if (Object.keys(mergedParams).length > 0) {
18✔
503
      params = this.appendCustomParams({ ...mergedParams }, params);
9✔
504
    }
505

506
    if (prompt) {
18✔
507
      params = this.overWriteParam(params, 'prompt', prompt);
5✔
508
    }
509

510
    if (hdParam) {
18✔
511
      params = params.append('hd', hdParam);
1✔
512
    }
513

514
    return `${authorizationUrl}?${params}`;
18✔
515
  }
516

517
  private createUrlImplicitFlowWithSilentRenew(
518
    configuration: OpenIdConfiguration,
519
    customParams?: { [key: string]: string | number | boolean }
520
  ): string | null {
521
    const state =
522
      this.flowsDataService.getExistingOrCreateAuthStateControl(configuration);
3✔
523
    const nonce = this.flowsDataService.createNonce(configuration);
3✔
524
    const silentRenewUrl = this.getSilentRenewUrl(configuration);
3✔
525

526
    if (!silentRenewUrl) {
3✔
527
      return null;
1✔
528
    }
529

530
    this.loggerService.logDebug(
2✔
531
      configuration,
532
      'RefreshSession created. adding myautostate: ',
533
      state
534
    );
535

536
    const authWellKnownEndPoints = this.storagePersistenceService.read(
2✔
537
      'authWellKnownEndPoints',
538
      configuration
539
    );
540

541
    if (authWellKnownEndPoints) {
2✔
542
      return this.createAuthorizeUrl(
1✔
543
        '',
544
        silentRenewUrl,
545
        nonce,
546
        state,
547
        configuration,
548
        'none',
549
        customParams
550
      );
551
    }
552

553
    this.loggerService.logError(
1✔
554
      configuration,
555
      'authWellKnownEndpoints is undefined'
556
    );
557

558
    return null;
1✔
559
  }
560

561
  private createUrlCodeFlowWithSilentRenew(
562
    configuration: OpenIdConfiguration,
563
    customParams?: { [key: string]: string | number | boolean }
564
  ): Observable<string> {
565
    const state =
566
      this.flowsDataService.getExistingOrCreateAuthStateControl(configuration);
3✔
567
    const nonce = this.flowsDataService.createNonce(configuration);
3✔
568

569
    this.loggerService.logDebug(
3✔
570
      configuration,
571
      'RefreshSession created. adding myautostate: ' + state
572
    );
573

574
    // code_challenge with "S256"
575
    const codeVerifier =
576
      this.flowsDataService.createCodeVerifier(configuration);
3✔
577

578
    return this.jwtWindowCryptoService.generateCodeChallenge(codeVerifier).pipe(
3✔
579
      map((codeChallenge: string) => {
580
        const silentRenewUrl = this.getSilentRenewUrl(configuration);
3✔
581

582
        if (!silentRenewUrl) {
3✔
583
          return '';
1✔
584
        }
585

586
        const authWellKnownEndPoints = this.storagePersistenceService.read(
2✔
587
          'authWellKnownEndPoints',
588
          configuration
589
        );
590

591
        if (authWellKnownEndPoints) {
2✔
592
          return this.createAuthorizeUrl(
1✔
593
            codeChallenge,
594
            silentRenewUrl,
595
            nonce,
596
            state,
597
            configuration,
598
            'none',
599
            customParams
600
          );
601
        }
602

603
        this.loggerService.logWarning(
1✔
604
          configuration,
605
          'authWellKnownEndpoints is undefined'
606
        );
607

608
        return '';
1✔
609
      })
610
    );
611
  }
612

613
  private createUrlImplicitFlowAuthorize(
614
    configuration: OpenIdConfiguration,
615
    authOptions?: AuthOptions
616
  ): string | null {
617
    const state =
618
      this.flowsDataService.getExistingOrCreateAuthStateControl(configuration);
3✔
619
    const nonce = this.flowsDataService.createNonce(configuration);
3✔
620

621
    this.loggerService.logDebug(
3✔
622
      configuration,
623
      'Authorize created. adding myautostate: ' + state
624
    );
625

626
    const redirectUrl = this.getRedirectUrl(configuration, authOptions);
3✔
627

628
    if (!redirectUrl) {
3✔
629
      return null;
1✔
630
    }
631

632
    const authWellKnownEndPoints = this.storagePersistenceService.read(
2✔
633
      'authWellKnownEndPoints',
634
      configuration
635
    );
636

637
    if (authWellKnownEndPoints) {
2✔
638
      const { customParams } = authOptions || {};
1✔
639

640
      return this.createAuthorizeUrl(
1✔
641
        '',
642
        redirectUrl,
643
        nonce,
644
        state,
645
        configuration,
646
        '',
647
        customParams
648
      );
649
    }
650

651
    this.loggerService.logError(
1✔
652
      configuration,
653
      'authWellKnownEndpoints is undefined'
654
    );
655

656
    return null;
1✔
657
  }
658

659
  private createUrlCodeFlowAuthorize(
660
    config: OpenIdConfiguration,
661
    authOptions?: AuthOptions
662
  ): Observable<string | null> {
663
    const state =
664
      this.flowsDataService.getExistingOrCreateAuthStateControl(config);
7✔
665
    const nonce = this.flowsDataService.createNonce(config);
7✔
666

667
    this.loggerService.logDebug(
7✔
668
      config,
669
      'Authorize created. adding myautostate: ' + state
670
    );
671

672
    const redirectUrl = this.getRedirectUrl(config, authOptions);
7✔
673

674
    if (!redirectUrl) {
7✔
675
      return of(null);
2✔
676
    }
677

678
    return this.getCodeChallenge(config).pipe(
5✔
679
      map((codeChallenge: string) => {
680
        const authWellKnownEndPoints = this.storagePersistenceService.read(
5✔
681
          'authWellKnownEndPoints',
682
          config
683
        );
684

685
        if (authWellKnownEndPoints) {
5✔
686
          const { customParams } = authOptions || {};
3✔
687

688
          return this.createAuthorizeUrl(
3✔
689
            codeChallenge,
690
            redirectUrl,
691
            nonce,
692
            state,
693
            config,
694
            '',
695
            customParams
696
          );
697
        }
698

699
        this.loggerService.logError(
2✔
700
          config,
701
          'authWellKnownEndpoints is undefined'
702
        );
703

704
        return '';
2✔
705
      })
706
    );
707
  }
708

709
  private getCodeChallenge(config: OpenIdConfiguration): Observable<string> {
710
    if (config.disablePkce) {
5✔
711
      return of('');
1✔
712
    }
713

714
    // code_challenge with "S256"
715
    const codeVerifier = this.flowsDataService.createCodeVerifier(config);
4✔
716

717
    return this.jwtWindowCryptoService.generateCodeChallenge(codeVerifier);
4✔
718
  }
719

720
  private getRedirectUrl(
721
    configuration: OpenIdConfiguration,
722
    authOptions?: AuthOptions
723
  ): string | null {
724
    let { redirectUrl } = configuration;
19✔
725

726
    if (authOptions?.redirectUrl) {
19✔
727
      // override by redirectUrl from authOptions
728
      redirectUrl = authOptions.redirectUrl;
1✔
729
    }
730

731
    if (!redirectUrl) {
19✔
732
      this.loggerService.logError(
5✔
733
        configuration,
734
        `could not get redirectUrl, was: `,
735
        redirectUrl
736
      );
737

738
      return null;
5✔
739
    }
740

741
    return redirectUrl;
14✔
742
  }
743

744
  private getSilentRenewUrl(configuration: OpenIdConfiguration): string | null {
745
    const { silentRenewUrl } = configuration;
10✔
746

747
    if (!silentRenewUrl) {
10✔
748
      this.loggerService.logError(
4✔
749
        configuration,
750
        `could not get silentRenewUrl, was: `,
751
        silentRenewUrl
752
      );
753

754
      return null;
4✔
755
    }
756

757
    return silentRenewUrl;
6✔
758
  }
759

760
  private getClientId(configuration: OpenIdConfiguration): string | null {
761
    const { clientId } = configuration;
14✔
762

763
    if (!clientId) {
14✔
764
      this.loggerService.logError(
5✔
765
        configuration,
766
        `could not get clientId, was: `,
767
        clientId
768
      );
769

770
      return null;
5✔
771
    }
772

773
    return clientId;
9✔
774
  }
775

776
  private appendCustomParams(
777
    customParams: { [key: string]: string | number | boolean },
778
    params: HttpParams
779
  ): HttpParams {
780
    for (const [key, value] of Object.entries({ ...customParams })) {
19✔
781
      params = params.append(key, value.toString());
27✔
782
    }
783

784
    return params;
19✔
785
  }
786

787
  private overWriteParam(
788
    params: HttpParams,
789
    key: string,
790
    value: string | number | boolean
791
  ): HttpParams {
792
    return params.set(key, value);
5✔
793
  }
794

795
  private createHttpParams(existingParams?: string): HttpParams {
796
    existingParams = existingParams ?? '';
37✔
797

798
    return new HttpParams({
37✔
799
      fromString: existingParams,
800
      encoder: new UriEncoder(),
801
    });
802
  }
803

804
  private isAuth0Endpoint(configuration: OpenIdConfiguration): boolean {
805
    const { authority, useCustomAuth0Domain } = configuration;
7✔
806

807
    if (!authority) {
7✔
808
      return false;
6✔
809
    }
810

811
    return authority.endsWith(AUTH0_ENDPOINT) || Boolean(useCustomAuth0Domain);
1!
812
  }
813

814
  private composeAuth0Endpoint(configuration: OpenIdConfiguration): string {
815
    // format: https://YOUR_DOMAIN/v2/logout?client_id=YOUR_CLIENT_ID&returnTo=LOGOUT_URL
816
    const { authority, clientId } = configuration;
1✔
817
    const postLogoutRedirectUrl = this.getPostLogoutRedirectUrl(configuration);
1✔
818

819
    return `${authority}/v2/logout?client_id=${clientId}&returnTo=${postLogoutRedirectUrl}`;
1✔
820
  }
821
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc