console icon indicating copy to clipboard operation
console copied to clipboard

OIDC tokens are not refreshed

Open Adphi opened this issue 3 years ago • 9 comments

I am testing the console authentication using dex as the identity provider. I have configured the openid provider in the console with the following claims: openid,profile,groups,email,offline_access so that the console receives a refresh token. But the token is never actually refreshed and the user is logged out when it expires.

Adphi avatar Feb 07 '23 14:02 Adphi

refresh_token is not supported @Adphi - the user is logged out once the token expires and you are expected to re-login.

This is a feature that we have to implement.

harshavardhana avatar Feb 07 '23 14:02 harshavardhana

@harshavardhana thanks for the quick response.

At which level should it be implemented ? minio-go or console ?

Adphi avatar Feb 07 '23 14:02 Adphi

At which level should it be implemented ? minio-go or console ?

In the console the logic must be implemented.

harshavardhana avatar Feb 07 '23 14:02 harshavardhana

@harshavardhana has there been any progress on supporting refreshing OIDC tokens in MinIO Console?

Here are some good reference materials about using refresh tokens:

  • https://oauth.net/2/grant-types/refresh-token/
    • https://www.rfc-editor.org/rfc/rfc6749#section-1.5
    • https://www.oauth.com/oauth2-servers/access-tokens/refreshing-access-tokens/
    • https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/
  • You can also look at the app oauth2-proxy which already supports token refreshing

thesuperzapper avatar Mar 27 '23 18:03 thesuperzapper

Hey @bexsoft @kaankabalak @harshavardhana @prakashsvmx is there any chance of getting refresh tokens working in MinIO? Without this feature, users are forced to make their OIDC provider issue tokens with very long expires, which is a big security risk.


The general pattern would be that Minio Console will additionally request the offline_access OpenID scope in MINIO_IDENTITY_OPENID_SCOPES.

The only user-facing API change would be the addition of a config like MINIO_IDENTITY_OPENID_REFRESH_INTERVAL which is sort of a "soft expiry" for ID tokens, so if a request presents a valid JWT which is older this age, MinIO tries to use the refresh token to get a new ID token.

  • This means that we can more quickly respond to account revocation without forcing the user to constantly re-auth.
  • If a request is made after the ID token has already expired, MinIO should try and use the refresh token before redirecting the user to a login screen.
  • NOTE: it's not a strict requirement to have this feature, as we could just only refresh the ID token when it expires, but some OpenID providers require a refresh token to be used somewhat frequently, like once every 7 days, to keep it active

Okta has a very comprehensive write-up of how refresh tokens work, and how the various flows work:

  • https://developer.okta.com/docs/guides/refresh-tokens/main/

thesuperzapper avatar May 23 '23 22:05 thesuperzapper

The only user-facing API change would be the addition of a config like MINIO_IDENTITY_OPENID_REFRESH_INTERVAL which is sort of a "soft expiry" for ID tokens, so if a request presents a valid JWT which is older this age, MinIO tries to use the refresh token to get a new ID token.

There is no need for an environment variable for token rotation.

The expiration is already written into the jwt token.

From what I remember when I went through the code, the refresh token returned by the OP is not stored anywhere (e.g. session cookie). The implementation uses the TokenSource from "golang.org/x/oauth2" which already supports token refreshing.

Adphi avatar May 24 '23 06:05 Adphi

@Adphi while we may not need to allow specifying a refresh interval, there is a need to allow users to disable the refresh function of MinIO Console. This is important because not all OpenID providers support refresh tokens, so a variable like MINIO_IDENTITY_OPENID_REFRESH which defaults to false is critical.

thesuperzapper avatar May 24 '23 18:05 thesuperzapper

In terms of implementation, I think we might actually already be storing the refresh token in a cookie called idp-refresh-token, but I can't see any references to it being used to refresh the ID token (without prompting the user).


I know refresh tokens are a bit confusing, so I will provide a basic example of how they work, for reference.

The JWT (id token) issued by the OpenID provider will have an expiry and the refresh token (returned inside the JWT) has separate expiry characteristics from the overall ID token.

For example, consider the case of the following expiry periods:

  • ID Token (JWT): 60 minutes
  • Refresh Token:
    • Minimum Use Interval: 7 days
    • Maximum Chain Lifetime: 90 days
    • Reuse Interval: 30 seconds

In this case, while the overall JWT will expire within 60 minutes, at long as we use the refresh token flow at least once every 7 days, the user will not need to be interrupted (we can use the refresh token flow to get a new JWT without prompting or redirecting the user).

The "maximum chain lifetime" is the maximum possible time (if we keep extending the user's token at least once every "minimum use interval") before the OpenID provider will require a new login.

To understand the "reuse interval", you have to understand that the refresh token is changed each time we use it to generate a new JWT, you can think of it as a grace period during which the same refresh token can be used and get the same refresh token (to handle parallel requests).

thesuperzapper avatar May 24 '23 19:05 thesuperzapper

there is a need to allow users to disable the refresh function of MinIO Console

@thesuperzapper it's quite simple: do not request the offline_access scope.

Adphi avatar May 24 '23 19:05 Adphi