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.15k stars 433 forks source link

Silent renew not working in a new tab #588

Closed GabrielGil closed 4 years ago

GabrielGil commented 4 years ago

Description When a user is logged-in in my app and opens the same app in a new tab, oidcService returns isAuthenticated = false after hitting the timeout. Calling "login" logs in the user directly without authorization.

Logs

This happens when opening a new tab when the first tab is authorized. image

This happens when refreshing a page which is authorized. The only warning: init check session: authWellKnownEndpoints is undefined

image
image

I have configured the frame CSP, the silent-renew.html file is added to the assets array etc. The silent renew frame is actually loading, but the checkSession iframe is empty.

Configuration

{
  "stsServer": "http://localhost:3000",
  "redirect_url": "http://localhost/account/callback",
  "client_id": "octavo",
  "response_type": "code",
  "post_logout_redirect_uri": "http://localhost/account/bye",
  "start_checksession": true,
  "silent_renew": true,
  "silent_renew_url": "http://localhost/silent-renew.html",
  "log_console_warning_active": true,
  "log_console_debug_active": true
}

Versions

remkoboschker commented 4 years ago

The new tab does bot have access to the session storage of the other tab. So you do not have access to any tokens received previously

GabrielGil commented 4 years ago

Thank you for your answer @remkoboschker. I am aware that the session storage is unique to the opened tab. However, I would expect that the silent renew kicks in an attempt to get new tokens from the STS server, where the user is still logged in.

Could maybe one of the code owners confirm this (@damienbod)?

k-schneider commented 4 years ago

This was working in the previous release. It just cropped up in 10.0.15.

GabrielGil commented 4 years ago

You are right @k-schneider. I have checked my app just downgrading to 10.0.14 and I can confirm this issue is a regression. In a new tab, the iframe for silent renew just kicks in directly so users are finely authenticated.

Let me know if any clarification is needed or I can help in any way @damienbod.

koo9 commented 4 years ago

any update on this issue? will downgrade for now.

GabrielGil commented 4 years ago

From what I can see, #599 may have something to do. But there was no release since the one I reported (10.0.15), so we will have to use 10.0.14 for now @koo9.

damienbod commented 4 years ago

I plan to refactor this for version 11. I have 3 use cases, and not sure which is best, or if I should support all with configurtion:

What would you require?

GabrielGil commented 4 years ago

Considering what I know about OIDC, the article about Secure authentication for SPAs by Dennis Stötzel and my personal experience, I believe the best option would be:

  1. A new tab should automatically silent renew, if possible.
  2. Logout of one of the tabs, should logout from the other tabs by using the check session. Once the STS cannot confirm the user is logged in, the tab clears the sessionStorage.

I believe this should be the default behaviour. Otherwise, it'd be possible for a user to log-in in tab1 with user A, logout from the STS, open tab2 and login with userB. Ultimately, the user will face issues on tab1 since the renew will fail at some point.

Thanks for your time. Please, let me know your thoughts and points of view too. :)

remkoboschker commented 4 years ago

I am working on handling a complex registration scenario with our identity provider team. If a user is redirected back to our application after registration, they can be in a new browser instance (for instance webview on mobile after link in email). That means that they have just authenticated for the first time with the idp, but the token validation fails, because there is no local state. I think therefore that an attempt to validate a token when there is no state should trigger a login attempt (and because the idp has just set a session cookie the user need not notice it).

We use refresh tokens in stead of the hidden iframe. Would the iframe solution fix such an issue when silent renew automatically runs in a new tab?

Does this maken sense?

GabrielGil commented 4 years ago

Refresh tokens are nowadays highly discouraged for browser apps. The iframe solution would work fine in your case, as long as you use ChromeTabs (in Android) as webview is also discouraged both for security and performance concerns.

If you follow this pattern @remkoboschker, your users log-in once (ie, in Chrome for Android), and then when tapping "login" in a native app, the idp session will be the same, so will not need to log in again. This way, no client app session is stored anywhere but in memory/session storage. I recommend you give it a look to the last link I shared here regarding secure auth in SPAs where you have more info about this.

This is already working, if you use v10.0.14, and tentatively in the future v11 which @damienbod announced today.

remkoboschker commented 4 years ago

What would need to happen when automatic silent renew fails? Would this trigger a login attempt and cover the first usecase mentioned by @damienbod ?

damienbod commented 4 years ago

@remkoboschker no/ you would need to click login

k-schneider commented 4 years ago

I'd agree with @GabrielGil... a new tab should always try and login via silent refresh (if silent refresh is enabled) and your checksession functionality should be able to handle logging you out of all tabs when your session ends on the STS.

@damienbod what version of Angular will v11 target? Will it work with both Angular v8 and v9?

remkoboschker commented 4 years ago

@GabrielGil thank you, I have read the article.

damienbod commented 4 years ago

@k-schneider haven't decided, I would like to support 8, but also what to move to Angular 9 for the development. But it would make sense to support V8 onwards I think. I also have a lot of V8 projects still.

damienbod commented 4 years ago

This has been refactored fixed and changed in version 11 which we plan to release in the next few days after testing

Greetings Damien

joshcomley commented 3 years ago

@damienbod does your last update last year mean that a new tab should try and use the iframe to silently renew? I can't seem to find a sample that does this, perhaps I am missing something

Edit: to be clear, start-sample-code-flow-auto-login does auto-login on a new tab, but gets the token via redirecting the main app rather than an iframe - is this the expected behaviour?