manfredsteyer / angular-oauth2-oidc

Support for OAuth 2 and OpenId Connect (OIDC) in Angular.
MIT License
1.9k stars 688 forks source link

Error revoking token TypeError: Cannot read property 'toLowerCase' of undefined #794

Open LeoPote opened 4 years ago

LeoPote commented 4 years ago

This error appears when calling revokeTokenAndLogout() trying to logout...

Stackblitz example

I implement a login mechanism with angular-oauth2-oidc and Keycloak 9.0.3. Everything seams to work fine except the logout. If i use the simple method logOut(), I can navigate back to home page without credentials after logout. If i try to use the method revokeTokenAndLogout(),Ii get this error on console:

Error revoking token TypeError: Cannot read property 'toLowerCase' of undefined.

Expected behavior

I am trying to use revokeTokenAndLogout() instead of logOut(), because, if I use logOut(),Ii am redirected to login page but logout is not done because I can go back in the landing page without providing the credentials.

Desktop (please complete the following information):

Error revoking token TypeError: Cannot read property 'toLowerCase' of undefined
    at HttpXsrfInterceptor.intercept (http.js:2790)
    at HttpInterceptorHandler.handle (http.js:1941)
    at HttpInterceptingHandler.handle (http.js:2873)
    at MergeMapSubscriber.project (http.js:1665)
    at MergeMapSubscriber._tryNext (mergeMap.js:46)
    at MergeMapSubscriber._next (mergeMap.js:36)
    at MergeMapSubscriber.next (Subscriber.js:49)
    at Observable._subscribe (subscribeToArray.js:3)
    at Observable._trySubscribe (Observable.js:42)
    at Observable.subscribe (Observable.js:28)
(anonymous) @ angular-oauth2-oidc.js:2374
__tryOrUnsub @ Subscriber.js:183
error @ Subscriber.js:135
_error @ Subscriber.js:75
error @ Subscriber.js:55
notifyError @ OuterSubscriber.js:7
_error @ InnerSubscriber.js:14
error @ Subscriber.js:55
_error @ Subscriber.js:75
error @ Subscriber.js:55
_error @ Subscriber.js:75
error @ Subscriber.js:55
_tryNext @ mergeMap.js:49
_next @ mergeMap.js:36
next @ Subscriber.js:49
(anonymous) @ subscribeToArray.js:3
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
call @ mergeMap.js:21
subscribe @ Observable.js:23
call @ filter.js:13
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
subscribeToResult @ subscribeToResult.js:9
_complete @ combineLatest.js:52
complete @ Subscriber.js:61
(anonymous) @ subscribeToArray.js:5
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
call @ combineLatest.js:26
subscribe @ Observable.js:23
(anonymous) @ angular-oauth2-oidc.js:2369
ZoneAwarePromise @ zone-evergreen.js:872
revokeTokenAndLogout @ angular-oauth2-oidc.js:2348
logout @ header.component.ts:52
HeaderComponent_Template_a_click_20_listener @ header.component.html:30
executeListenerWithErrorHandling @ core.js:21697
wrapListenerIn_markDirtyAndPreventDefault @ core.js:21739
(anonymous) @ platform-browser.js:934
invokeTask @ zone-evergreen.js:400
onInvokeTask @ core.js:41249
invokeTask @ zone-evergreen.js:399
runTask @ zone-evergreen.js:168
invokeTask @ zone-evergreen.js:481
invokeTask @ zone-evergreen.js:1596
globalZoneAwareCallback @ zone-evergreen.js:1622
Show 17 more frames
core.js:5871 ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'toLowerCase' of undefined
TypeError: Cannot read property 'toLowerCase' of undefined
    at HttpXsrfInterceptor.intercept (http.js:2790)
    at HttpInterceptorHandler.handle (http.js:1941)
    at HttpInterceptingHandler.handle (http.js:2873)
    at MergeMapSubscriber.project (http.js:1665)
    at MergeMapSubscriber._tryNext (mergeMap.js:46)
    at MergeMapSubscriber._next (mergeMap.js:36)
    at MergeMapSubscriber.next (Subscriber.js:49)
    at Observable._subscribe (subscribeToArray.js:3)
    at Observable._trySubscribe (Observable.js:42)
    at Observable.subscribe (Observable.js:28)
    at resolvePromise (zone-evergreen.js:793)
    at zone-evergreen.js:707
    at SafeSubscriber._error (angular-oauth2-oidc.js:2376)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.error (Subscriber.js:135)
    at Subscriber._error (Subscriber.js:75)
    at Subscriber.error (Subscriber.js:55)
    at CombineLatestSubscriber.notifyError (OuterSubscriber.js:7)
    at InnerSubscriber._error (InnerSubscriber.js:14)
    at InnerSubscriber.error (Subscriber.js:55)
jhwegener commented 4 years ago

@LeoPote I've the same error here on using revokeTokenAndLogout(). But, I'm really logged out and have no chance to get back to the application.

Desktop (please complete the following information): OS: Mac OS 10.14.6 Browser chrome Angular 9.0.6 Keycloak 9.0.2 "angular-oauth2-oidc": "9.2.0"

cupojavagirl commented 4 years ago

I am facing the same issue and I am getting the exact same error.

I am using: "angular-oauth2-oidc": "9.2.0" Angular: 7.2 Browser: Chrome Keycloak: 8.0.1 OS: Linux

sagaert commented 4 years ago

I've the same error: If I use the logOut() method, I am not really logged out. When I start the login flow again, I will not be redirected to the Security Provider to enter the credentials but I am logged in with the previous user without entering any credentials. When I try using the revokeTokenAndLogout() method I end up with the same error show above. I am using:

vitalrev commented 4 years ago

in my case, i play with flight sample from this repo (angular-oauth2-oidc/projects/sample)... If i start the app with the original configs an try the login and logout with code flow, it works fine...

But, if i switch the auth-code-flow.config.ts issuer and clientId to my keycloak realm and client:

issuer: 'http://localhost:8080/auth/realms/my-realm',
clientId: 'my-client-id',

i'm getting the same error:

TypeError: Cannot read property 'toLowerCase' of undefined
    at HttpXsrfInterceptor.push.../../node_modules/@angular/common/fesm5/http.js.HttpXsrfInterceptor.intercept (http.js:1887)
    at HttpInterceptorHandler.push.../../node_modules/@angular/common/fesm5/http.js.HttpInterceptorHandler.handle (http.js:1285)
    at HttpInterceptingHandler.push.../../node_modules/@angular/common/fesm5/http.js.HttpInterceptingHandler.handle (http.js:1938)
    at MergeMapSubscriber.project (http.js:1105)
    at MergeMapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._tryNext (mergeMap.js:61)
    at MergeMapSubscriber.push.../../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._next (mergeMap.js:51)
    at MergeMapSubscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (Subscriber.js:53)
    at Observable._subscribe (subscribeToArray.js:5)
    at Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable._trySubscribe (Observable.js:43)
    at Observable.push.../../node_modules/rxjs/_esm5/internal/Observable.js.Observable.subscribe (Observable.js:29)
    at resolvePromise (zone.js:836)
    at zone.js:750
    at SafeSubscriber._error (oauth-service.ts:2643)
    at SafeSubscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.__tryOrUnsub (Subscriber.js:192)
    at SafeSubscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.SafeSubscriber.error (Subscriber.js:143)
    at Subscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber._error (Subscriber.js:79)
    at Subscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:59)
    at CombineLatestSubscriber.push.../../node_modules/rxjs/_esm5/internal/OuterSubscriber.js.OuterSubscriber.notifyError (OuterSubscriber.js:13)
    at InnerSubscriber.push.../../node_modules/rxjs/_esm5/internal/InnerSubscriber.js.InnerSubscriber._error (InnerSubscriber.js:18)
    at InnerSubscriber.push.../../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.error (Subscriber.js:59)

In my case, the problem is, that the revocation_endpoint is missing in keycloak descovery document (http://localhost:8080/auth/realms/my-realm/.well-known/openid-configuration)!!! And the OAuthService needs it to revoke access and refresh tokens in:

  public revokeTokenAndLogout(): Promise<any> {
    let revokeEndpoint = this.revocationEndpoint;
    ...
    let revokationParams = params
          .set('token', accessToken)
          .set('token_type_hint', 'access_token');
    revokeAccessToken = this.http.post<void>(
          revokeEndpoint,
          revokationParams,
          { headers }
        );

Keycloak doesn't support revocation_endpoint at the moment, see issue I'm looking for a workaround... any ideas?

Update: as workaround i can call this.oauthService.logOut(); instead of this.oauthService.revokeTokenAndLogout();... and it works with keycloak because it uses .end_session_endpoint supported by Keycloak! Ok, for me enough good workaround.

I hope, my research helps you to fix the error in revokeTokenAndLogout... a simple check if revokeEndpoint is defined, may be ;)

LeoPote commented 4 years ago

Tks vitalrev for your answer, very helpful indeed.

Logout is working for me too, if i am using it in a sigle-tenant architecture, but when i am switching to a multi-tenant architecture, implementing an identity brokering in Keycloak, then logout() is not working properly - meaning that, after i press logout, i am redirected to the multi-tenant login page, but when i chose the tenant where i was logged in before, the login screen of this tenant is not appearing anymore, instead i am redirected in the account i was logged in before. So the logout was not working properly for this architecture.

Probably i should keep on serching how to manage this inside Keycloak config, between different identities i am using there to implement multitenancy with identity brokering.

kalidiagne commented 4 years ago

to solve

TypeError: Cannot read property 'toLowerCase' of undefined on revokeTokenAndLogout,

is necessary to add revocationEndpoint on auth config

iLucas97 commented 4 years ago

Hi Guys, I had the same Issue with WSO2 Identity Provider. I did not solve with setting the revocationEndpoint in auth config.

RogueJay commented 4 years ago

I had to add the revocationEndpoint URL to the authservice after performing the document discovery, because the code doesn't attempt to read it from the auth.config.ts file. It only tries to set it from the document discovery

yaroslavOshyyko commented 3 years ago

setting revocationEndpoint to AuthConfig solved the issue