Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[question] How to refresh a token from an SPA? / Can we let refresh tokens expire? #1126

Closed
srenatus opened this issue Nov 13, 2017 · 4 comments

Comments

@srenatus
Copy link
Contributor

srenatus commented Nov 13, 2017

Hi there. I've been struggling with this question for some time, so I thought I might reach out to hear y'all's opinion.

Assumptions:

  1. When using Dex from a JS in-browser application, it seems common wisdom to use the Implict Flow.
  2. I want to react to changes of a user's status in the external identity provider (LDAP, SAML, ...) in a timely manner.
  3. I don't want to have the user go to their IdP to re-login annoyingly often.

The Trilemma

  • (2.) and (3.) stand in direct opposition -- if we assume that the act of getting an ID token is the only way for synchronising with the external IdP: if we want to be informed in a time window of 20 minutes, than this means the user has to login every 20 minutes. (Implicit flow: id_token_hint, prompt=none #990 could make this a little less painful for non-interactive connectors, e.g. OIDC/SAML with a session on the IdP.)
  • (1.) means we don't have refresh tokens in the client. (Putting aside that SAML doesn't allow refresh.) Also, refresh tokens don't expire, so it seems incautious to hand them out, e.g. by using the authorization code flow. (Although: search [this post]https://aaronparecki.com/oauth-2-simplified/) for "industry best practice")

Possible ways out?

Extend a token's lifetime without a refresh_token

This could be a way to achieve (1.)-like behaviour without actually handing out refresh tokens.

Dex could support extending an ID token's expiry (or really, give a new one out when given a valid one), for example as follows:

  • Requesting a token from /auth/token using a valid, non-expired ID token could initiate a connector's Refresh() (if implemented), and
    • when successful, return the new ID token
    • if unsupported or failing (e.g. the user doesn't exist anymore, or has been disabled in the external IdP), return 401.

Downside: this seems to be way out of spec -- so, 👎 Although I vaguely remember that google or facebook do something like that, but unless there's a spec, I'd be reluctant to really propose this route.

Restrict refresh_token lifetime

This could overcome (1.) by making it acceptable to hand out refresh tokens.

If refresh tokens expire, they could more easily be handed out to non-confidential clients. The refresh token validity would then drive when the user has to sign in interactively, and until that happens, the client could get a fresh access_token/ID token every 20 minutes. The act of exchanging the refresh token for an ID token is the point in time when external changes (from the IdP) get effective.

Advantage: expiring refresh tokens seem to be in spec and not too uncommon (see e.g. Azure AD).

Disadvantage: there's no Refresh() for the SAML connector (probably among others); which may or may not be an insurmountable problem 😉

Other options?

I must have missed something. How do you, dear reader, approach that problem?

@ericchiang
Copy link
Contributor

This sounds like an access_token and the userinfo endpoint #376

Just an FYI, you'll never be able to do this through SAML. There's no way to re-query a provider.

@srenatus
Copy link
Contributor Author

@srenatus
Copy link
Contributor Author

Just an FYI, you'll never be able to do this through SAML

Yup that's right. Luckily, there's a new option for Azure AD now: using the microsoft connector 😃

@srenatus
Copy link
Contributor Author

Closing this. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants