damienbod / angular-auth-oidc-client

npm package for OpenID Connect, OAuth Code Flow with PKCE, Refresh tokens, Implicit Flow
https://www.npmjs.com/package/angular-auth-oidc-client
MIT License
1.12k stars 422 forks source link

[Bug]: isAuthenticated(), getUserData(), etc. emit snapshot instead of real stream #1846

Open Spinnenzunge opened 9 months ago

Spinnenzunge commented 9 months ago

Version

16.0.1

Please provide a link to a minimal reproduction of the bug

https://github.com/damienbod/angular-auth-oidc-client/tree/main/projects/sample-code-flow-standalone

Please provide the exception or error you saw

Methods like `isAuthenticated()`, `getUserData()`, `getPayloadFromIdToken()`, etc. do not really emit new values when authentication state changes. Instead they emit a snapshot that is returned as an observable.

Steps to reproduce the behavior

- Checkout https://github.com/damienbod/angular-auth-oidc-client/
- Start sample-code-flow-standalone
- Change from `isAuthenticated$` to `isAuthenticated()` in `NavigationComponent`
- Login
- Header does not change, because isAuthenticated() does not emit new value if authentication state changes

A clear and concise description of what you expected to happen.

Methods like `isAuthenticated()`, `getUserData()`, `getPayloadFromIdToken()`, etc. should emit a stream instead of a snapshot in form of an observable.

Additional context

No response

Spinnenzunge commented 7 months ago

Changed title and description as my initial issue was a bit confusing.

dbl81 commented 4 months ago

same problem here

FabianGosebrink commented 4 months ago

When you call the methods again, do they emit the correct value?

dbl81 commented 4 months ago

When you call the methods again, do they emit the correct value?

Yes, but you have to "re-subscribe" in order to get the correct value, it doesnt stream the "new" value. I use it in the ngOnInit of the app.component in order to show / not show user's initials in the upper right corner. If I reload the app (F5), isAuthenticated emit the correct value.

Subscribing to isAuthenticated() means to me:

  1. at first you are not authenticated -> initiallly it emits false
  2. after login -> it emits true
  3. logout -> it emits false
  4. ...and so on...

Did I misunderstand the use of isAuthenticated()?

I'm using:

FabianGosebrink commented 4 months ago

The intention of the method was: You call it, you get the value when you want it, once. We also have the other stream which should emit the value like a stream. So you can choose on your end what you want.

dbl81 commented 4 months ago

Please read the next post.

Thank you for your support.

The problem with isAuthenticated$ comes up when you change route (it doesnt matter if it's protected or not by a AutoLoginPartialRoutesGuard) or you refresh the page, because the next value emitted is again false, even if I'm still authenticated (I can surf protected routes).

So in my case:

  1. isAuthenticated$ subscribed in app.component -> first value false (I mean the value of the property isAuthenticated of the AuthenticatedResult object)
  2. hit a protected route by AutoLoginPartialRoutesGuard -> redirect to keycloak to login
  3. after a successful login, redirect back to app callback route -> isAuthenticated$ emits true value
  4. change route to anything else (protected or not) -> isAuthenticated$ emits false value

I'm using a single config.

dbl81 commented 4 months ago

I dont know exactly how, but I solved my problem...now I have to investigate why it works now.

Again thank you for your support.

Spinnenzunge commented 3 months ago

The intention of the method was: You call it, you get the value when you want it, once. We also have the other stream which should emit the value like a stream. So you can choose on your end what you want.

The Problem is that the other streams only exists for isAuthenticated$ and userData$ not for e.g. resolved id token payload. So if we do want to have an observable that acts like a real stream for subscription we would need to create our own one by switchMapping getPayloadFromIdToken() on e.g. isAuthenticated$ or something like that. This is of course possible but would appreciate it if the lib public api would work like that out of the gate, especially if it is already typed as an observable

FabianGosebrink commented 3 months ago

We can implement that. However, currently I do not even have time to breathe. We are accepting PRs and when I find time, I will have a look into it :)