From da1649499376863b0ebf884748176f3b38d91899 Mon Sep 17 00:00:00 2001 From: Dirk Bolte Date: Thu, 24 Sep 2020 17:06:13 +0200 Subject: [PATCH] feat: support JWT response on userinfo endpoint --- projects/lib/src/oauth-service.ts | 73 +++++++++++++++++++------------ 1 file changed, 46 insertions(+), 27 deletions(-) diff --git a/projects/lib/src/oauth-service.ts b/projects/lib/src/oauth-service.ts index 6f0bce0f..45597d15 100644 --- a/projects/lib/src/oauth-service.ts +++ b/projects/lib/src/oauth-service.ts @@ -694,7 +694,7 @@ export class OAuthService extends AuthConfig implements OnDestroy { userName: string, password: string, headers: HttpHeaders = new HttpHeaders() - ): Promise { + ): Promise { return this.fetchTokenUsingPasswordFlow( userName, password, @@ -708,7 +708,7 @@ export class OAuthService extends AuthConfig implements OnDestroy { * When using this with OAuth2 password flow, make sure that the property oidc is set to false. * Otherwise stricter validations take place that make this operation fail. */ - public loadUserProfile(): Promise { + public loadUserProfile(): Promise { if (!this.hasValidAccessToken()) { throw new Error('Can not load User Profile without access_token'); } @@ -725,35 +725,54 @@ export class OAuthService extends AuthConfig implements OnDestroy { ); this.http - .get(this.userinfoEndpoint, { headers }) + .get(this.userinfoEndpoint, { + headers, + observe: 'response', + responseType: 'text' + }) .subscribe( - info => { - this.debug('userinfo received', info); - - const existingClaims = this.getIdentityClaims() || {}; - - if (!this.skipSubjectCheck) { - if ( - this.oidc && - (!existingClaims['sub'] || info.sub !== existingClaims['sub']) - ) { - const err = - 'if property oidc is true, the received user-id (sub) has to be the user-id ' + - 'of the user that has logged in with oidc.\n' + - 'if you are not using oidc but just oauth2 password flow set oidc to false'; - - reject(err); - return; + response => { + this.debug('userinfo received', JSON.stringify(response)); + if ( + response.headers + .get('content-type') + .startsWith('application/json') + ) { + let info = response.body; + const existingClaims = this.getIdentityClaims() || {}; + + if (!this.skipSubjectCheck) { + if ( + this.oidc && + (!existingClaims['sub'] || info.sub !== existingClaims['sub']) + ) { + const err = + 'if property oidc is true, the received user-id (sub) has to be the user-id ' + + 'of the user that has logged in with oidc.\n' + + 'if you are not using oidc but just oauth2 password flow set oidc to false'; + + reject(err); + return; + } } - } - info = Object.assign({}, existingClaims, info); + info = Object.assign({}, existingClaims, info); - this._storage.setItem('id_token_claims_obj', JSON.stringify(info)); - this.eventsSubject.next( - new OAuthSuccessEvent('user_profile_loaded') - ); - resolve(info); + this._storage.setItem( + 'id_token_claims_obj', + JSON.stringify(info) + ); + this.eventsSubject.next( + new OAuthSuccessEvent('user_profile_loaded') + ); + resolve(info); + } else { + this.debug('userinfo is not JSON, treating it as JWE/JWS'); + this.eventsSubject.next( + new OAuthSuccessEvent('user_profile_loaded') + ); + resolve(response.body); + } }, err => { this.logger.error('error loading user info', err);