1
- import { Http , URLSearchParams , Headers } from '@angular/http' ;
2
1
import { Injectable , Optional } from '@angular/core' ;
2
+ import { HttpClient , HttpHeaders } from '@angular/common/http' ;
3
3
import { Observable } from 'rxjs/Observable' ;
4
4
import { Subject } from 'rxjs/Subject' ;
5
+ import { Subscription } from 'rxjs/Subscription' ;
6
+
5
7
import { ValidationHandler , ValidationParams } from './token-validation/validation-handler' ;
6
8
import { UrlHelperService } from './url-helper.service' ;
7
- import { Subscription } from 'rxjs/Subscription' ;
8
9
import { OAuthEvent , OAuthInfoEvent , OAuthErrorEvent , OAuthSuccessEvent } from './events' ;
9
- import { OAuthStorage , LoginOptions , ParsedIdToken } from './types' ;
10
+ import { OAuthStorage , LoginOptions , ParsedIdToken , OidcDiscoveryDoc , TokenResponse , UserInfo } from './types' ;
10
11
import { b64DecodeUnicode } from './base64-helper' ;
11
12
import { AuthConfig } from './auth.config' ;
12
13
@@ -65,7 +66,7 @@ export class OAuthService
65
66
private silentRefreshSubject : string ;
66
67
67
68
constructor (
68
- private http : Http ,
69
+ private http : HttpClient ,
69
70
@Optional ( ) storage : OAuthStorage ,
70
71
@Optional ( ) tokenValidationHandler : ValidationHandler ,
71
72
@Optional ( ) private config : AuthConfig ,
@@ -92,7 +93,6 @@ export class OAuthService
92
93
93
94
this . setupRefreshTimer ( ) ;
94
95
95
-
96
96
}
97
97
98
98
/**
@@ -140,14 +140,13 @@ export class OAuthService
140
140
* @param params Additional parameter to pass
141
141
*/
142
142
public setupAutomaticSilentRefresh ( params : object = { } ) {
143
- this
144
- . events
145
- . filter ( e => e . type === 'token_expires' )
146
- . subscribe ( e => {
147
- this . silentRefresh ( params ) . catch ( _ => {
148
- this . debug ( 'automatic silent refresh did not work' ) ;
149
- } )
150
- } ) ;
143
+ this . events
144
+ . filter ( e => e . type === 'token_expires' )
145
+ . subscribe ( e => {
146
+ this . silentRefresh ( params ) . catch ( _ => {
147
+ this . debug ( 'automatic silent refresh did not work' ) ;
148
+ } ) ;
149
+ } ) ;
151
150
152
151
this . restartRefreshTimerIfStillLoggedIn ( ) ;
153
152
}
@@ -306,7 +305,7 @@ export class OAuthService
306
305
fullUrl = this . issuer || '' ;
307
306
if ( ! fullUrl . endsWith ( '/' ) ) {
308
307
fullUrl += '/' ;
309
- }
308
+ }
310
309
fullUrl += '.well-known/openid-configuration' ;
311
310
}
312
311
@@ -315,7 +314,7 @@ export class OAuthService
315
314
return ;
316
315
}
317
316
318
- this . http . get ( fullUrl ) . map ( r => r . json ( ) ) . subscribe (
317
+ this . http . get < OidcDiscoveryDoc > ( fullUrl ) . subscribe (
319
318
( doc ) => {
320
319
321
320
if ( ! this . validateDiscoveryDocument ( doc ) ) {
@@ -368,7 +367,7 @@ export class OAuthService
368
367
private loadJwks ( ) : Promise < object > {
369
368
return new Promise < object > ( ( resolve , reject ) => {
370
369
if ( this . jwksUri ) {
371
- this . http . get ( this . jwksUri ) . map ( r => r . json ( ) ) . subscribe (
370
+ this . http . get ( this . jwksUri ) . subscribe (
372
371
jwks => {
373
372
this . jwks = jwks ;
374
373
this . eventsSubject . next ( new OAuthSuccessEvent ( 'discovery_document_loaded' ) ) ;
@@ -388,55 +387,55 @@ export class OAuthService
388
387
389
388
}
390
389
391
- private validateDiscoveryDocument ( doc : object ) : boolean {
390
+ private validateDiscoveryDocument ( doc : OidcDiscoveryDoc ) : boolean {
392
391
393
392
let errors : string [ ] ;
394
393
395
- if ( doc [ ' issuer' ] !== this . issuer ) {
394
+ if ( doc . issuer !== this . issuer ) {
396
395
console . error (
397
396
'invalid issuer in discovery document' ,
398
397
'expected: ' + this . issuer ,
399
- 'current: ' + doc [ ' issuer' ]
398
+ 'current: ' + doc . issuer
400
399
) ;
401
400
return false ;
402
401
}
403
402
404
- errors = this . validateUrlFromDiscoveryDocument ( doc [ ' authorization_endpoint' ] ) ;
403
+ errors = this . validateUrlFromDiscoveryDocument ( doc . authorization_endpoint ) ;
405
404
if ( errors . length > 0 ) {
406
405
console . error ( 'error validating authorization_endpoint in discovery document' , errors ) ;
407
406
return false ;
408
407
}
409
408
410
- errors = this . validateUrlFromDiscoveryDocument ( doc [ ' end_session_endpoint' ] ) ;
409
+ errors = this . validateUrlFromDiscoveryDocument ( doc . end_session_endpoint ) ;
411
410
if ( errors . length > 0 ) {
412
411
console . error ( 'error validating end_session_endpoint in discovery document' , errors ) ;
413
412
return false ;
414
413
}
415
414
416
- errors = this . validateUrlFromDiscoveryDocument ( doc [ ' token_endpoint' ] ) ;
415
+ errors = this . validateUrlFromDiscoveryDocument ( doc . token_endpoint ) ;
417
416
if ( errors . length > 0 ) {
418
417
console . error ( 'error validating token_endpoint in discovery document' , errors ) ;
419
418
}
420
419
421
- errors = this . validateUrlFromDiscoveryDocument ( doc [ ' userinfo_endpoint' ] ) ;
420
+ errors = this . validateUrlFromDiscoveryDocument ( doc . userinfo_endpoint ) ;
422
421
if ( errors . length > 0 ) {
423
422
console . error ( 'error validating userinfo_endpoint in discovery document' , errors ) ;
424
423
return false ;
425
424
}
426
425
427
- errors = this . validateUrlFromDiscoveryDocument ( doc [ ' jwks_uri' ] ) ;
426
+ errors = this . validateUrlFromDiscoveryDocument ( doc . jwks_uri ) ;
428
427
if ( errors . length > 0 ) {
429
428
console . error ( 'error validating jwks_uri in discovery document' , errors ) ;
430
429
return false ;
431
430
}
432
431
433
- if ( this . sessionChecksEnabled && ! doc [ ' check_session_iframe' ] ) {
432
+ if ( this . sessionChecksEnabled && ! doc . check_session_iframe ) {
434
433
console . warn (
435
434
'sessionChecksEnabled is activated but discovery document'
436
435
+ ' does not contain a check_session_iframe field' ) ;
437
436
}
438
437
439
- this . sessionChecksEnabled = doc [ ' check_session_iframe' ] ;
438
+ this . sessionChecksEnabled = ! ! doc . check_session_iframe ;
440
439
441
440
return true ;
442
441
}
@@ -458,7 +457,7 @@ export class OAuthService
458
457
public fetchTokenUsingPasswordFlowAndLoadUserProfile (
459
458
userName : string ,
460
459
password : string ,
461
- headers : Headers = new Headers ( ) ) : Promise < object > {
460
+ headers : HttpHeaders = new HttpHeaders ( ) ) : Promise < object > {
462
461
return this
463
462
. fetchTokenUsingPasswordFlow ( userName , password , headers )
464
463
. then ( ( ) => this . loadUserProfile ( ) ) ;
@@ -481,17 +480,17 @@ export class OAuthService
481
480
482
481
return new Promise ( ( resolve , reject ) => {
483
482
484
- let headers = new Headers ( ) ;
485
- headers . set ( 'Authorization' , 'Bearer ' + this . getAccessToken ( ) ) ;
483
+ const headers = new HttpHeaders ( )
484
+ . set ( 'Authorization' , 'Bearer ' + this . getAccessToken ( ) ) ;
486
485
487
- this . http . get ( this . userinfoEndpoint , { headers } ) . map ( r => r . json ( ) ) . subscribe (
488
- ( doc ) => {
489
- this . debug ( 'userinfo received' , doc ) ;
486
+ this . http . get < UserInfo > ( this . userinfoEndpoint , { headers } ) . subscribe (
487
+ ( info ) => {
488
+ this . debug ( 'userinfo received' , info ) ;
490
489
491
490
let existingClaims = this . getIdentityClaims ( ) || { } ;
492
-
491
+
493
492
if ( ! this . skipSubjectCheck ) {
494
- if ( this . oidc && ( ! existingClaims [ 'sub' ] || doc . sub !== existingClaims [ 'sub' ] ) ) {
493
+ if ( this . oidc && ( ! existingClaims [ 'sub' ] || info . sub !== existingClaims [ 'sub' ] ) ) {
495
494
let err = 'if property oidc is true, the received user-id (sub) has to be the user-id '
496
495
+ 'of the user that has logged in with oidc.\n'
497
496
+ 'if you are not using oidc but just oauth2 password flow set oidc to false' ;
@@ -501,11 +500,11 @@ export class OAuthService
501
500
}
502
501
}
503
502
504
- doc = Object . assign ( { } , existingClaims , doc ) ;
503
+ info = Object . assign ( { } , existingClaims , info ) ;
505
504
506
- this . _storage . setItem ( 'id_token_claims_obj' , JSON . stringify ( doc ) ) ;
505
+ this . _storage . setItem ( 'id_token_claims_obj' , JSON . stringify ( info ) ) ;
507
506
this . eventsSubject . next ( new OAuthSuccessEvent ( 'user_profile_loaded' ) ) ;
508
- resolve ( doc ) ;
507
+ resolve ( info ) ;
509
508
} ,
510
509
( err ) => {
511
510
console . error ( 'error loading user info' , err ) ;
@@ -522,7 +521,7 @@ export class OAuthService
522
521
* @param password
523
522
* @param headers Optional additional http-headers.
524
523
*/
525
- public fetchTokenUsingPasswordFlow ( userName : string , password : string , headers : Headers = new Headers ( ) ) : Promise < object > {
524
+ public fetchTokenUsingPasswordFlow ( userName : string , password : string , headers : HttpHeaders = new HttpHeaders ( ) ) : Promise < object > {
526
525
527
526
if ( ! this . validateUrlForHttps ( this . tokenEndpoint ) ) {
528
527
throw new Error ( 'tokenEndpoint must use Http. Also check property requireHttps.' ) ;
@@ -544,7 +543,7 @@ export class OAuthService
544
543
545
544
let params = search . toString ( ) ;
546
545
547
- this . http . post ( this . tokenEndpoint , params , { headers } ) . map ( r => r . json ( ) ) . subscribe (
546
+ this . http . post < TokenResponse > ( this . tokenEndpoint , params , { headers } ) . subscribe (
548
547
( tokenResponse ) => {
549
548
this . debug ( 'tokenResponse' , tokenResponse ) ;
550
549
this . storeAccessTokenResponse ( tokenResponse . access_token , tokenResponse . refresh_token , tokenResponse . expires_in ) ;
@@ -586,12 +585,12 @@ export class OAuthService
586
585
search . set ( 'client_secret' , this . dummyClientSecret ) ;
587
586
}
588
587
589
- let headers = new Headers ( ) ;
590
- headers . set ( 'Content-Type' , 'application/x-www-form-urlencoded' ) ;
588
+ const headers = new HttpHeaders ( )
589
+ . set ( 'Content-Type' , 'application/x-www-form-urlencoded' ) ;
591
590
592
591
let params = search . toString ( ) ;
593
592
594
- this . http . post ( this . tokenEndpoint , params , { headers } ) . map ( r => r . json ( ) ) . subscribe (
593
+ this . http . post < TokenResponse > ( this . tokenEndpoint , params , { headers } ) . subscribe (
595
594
( tokenResponse ) => {
596
595
this . debug ( 'refresh tokenResponse' , tokenResponse ) ;
597
596
this . storeAccessTokenResponse ( tokenResponse . access_token , tokenResponse . refresh_token , tokenResponse . expires_in ) ;
@@ -785,8 +784,7 @@ export class OAuthService
785
784
}
786
785
787
786
private waitForSilentRefreshAfterSessionChange ( ) {
788
- this
789
- . events
787
+ this . events
790
788
. filter ( ( e : OAuthEvent ) =>
791
789
e . type === 'silently_refreshed'
792
790
|| e . type === 'silent_refresh_timeout'
@@ -1396,7 +1394,7 @@ export class OAuthService
1396
1394
this . _storage . removeItem ( 'id_token_expires_at' ) ;
1397
1395
this . _storage . removeItem ( 'id_token_stored_at' ) ;
1398
1396
this . _storage . removeItem ( 'access_token_stored_at' ) ;
1399
-
1397
+
1400
1398
this . silentRefreshSubject = null ;
1401
1399
1402
1400
this . eventsSubject . next ( new OAuthInfoEvent ( 'logout' ) ) ;
@@ -1408,7 +1406,7 @@ export class OAuthService
1408
1406
let logoutUrl : string ;
1409
1407
1410
1408
if ( ! this . validateUrlForHttps ( this . logoutUrl ) ) throw new Error ( 'logoutUrl must use Http. Also check property requireHttps.' ) ;
1411
-
1409
+
1412
1410
// For backward compatibility
1413
1411
if ( this . logoutUrl . indexOf ( '{{' ) > - 1 ) {
1414
1412
logoutUrl = this . logoutUrl . replace ( / \{ \{ i d _ t o k e n \} \} / , id_token ) ;
0 commit comments