4

We consider using OpenID Connect with ID tokens for authentication of our public API.

These are the usage scenarios we'd like to cover:

  1. Web UI (single page, client-side JavaScript app)
  2. Command line interface (CLI) used in an interactive session
  3. CLI used non-interactively, e. g. in a CI/CD pipeline
  4. Other API calls executed in a non-interactive session

The idea for (1) and (2) is to use the OIDC implicit grant type, so that the user authenticates interactively (username/password) at our OpenID Connect identity provider and permits the RP (relying party, client) to access the users identity. The identity provider will then issue a short-lived ID token, a refresh token and (optionally?) an access token to the RP.

For (3) and (4) an interactive authentication is out of the question. We'd instead like to issue tokens to the users which allow them to access our API on their behalf. These tokens should be long living, only invalidated when they get deleted in the system.

Still, we want to use JWT just like the ID tokens issued by the identity provider as a carrier of identity information for all API requests internally.

My questions are:

  • Can this be done purely with one of the tokens issued by the OpenID Connect implicit grant type?
  • Can an access token be issued in a long-lived (no expiry, only invalidated by deleting from the system) way and then be exchanged by the client against an ID token?
  • Or is the refresh token the thing to use for exactly that?
  • Or do we have to solve this outside OpenID Connect? Which leaves the question how to resolve opaque tokens from API requests against identity details (JWT) for use in our API/services?
Kavindu Dodanduwa
  • 12,193
  • 3
  • 33
  • 46
Marian
  • 14,759
  • 6
  • 32
  • 44

2 Answers2

1

If you use implicit flow (for Scenarios 1 and 2), you can't use refresh tokens. You need client credentials (client ID and secret) to request for refresh tokens. In the Implicit flow, we don't store any client credentials.

When a client is Public client (SPA,etc..), it is not safe to store client secret in it. So public clients generally use Implicit flow. Implicit flow doesn't support refresh tokens. Some of the OIDC libraries implement Silent token renewal/refresh feature to circumvent the absence of refresh tokens. But there are some limitations with that model (you need to have active session with IDP to get the renewal working without any interruption)

TL;DR -> If a client is public client, use implicit flow (which don't need client secret to get access tokens from IDP). Implicit flow doesn't support refresh tokens.

Can this be done purely with one of the tokens issued by the OpenID Connect implicit grant type?

It is not possible to use refresh tokens with implicit flow. Authorization code flow supports refresh tokens but can't be used with SPA clients. So you need a combination of OAuth 2.0/OIDC flows.

Can an access token be issued in a long-lived (no expiry, only invalidated by deleting from the system) way and then be exchanged by the client against an ID token?

These are two different things:

  • "Invalidated by deleting from the system" : With this we are discussing about Self-Contained tokens vs Reference tokens.

Self-Contained Tokens: These tokens contains all the information required to validate its authenticity in it - for e.g. the issuer details, its validity, etc.. A client don't need to make a back-channel call to STS to confirm the authenticity. These tokens are sometimes hard to revoke and will be valid for the duration as specified in the token.

Reference Tokens: Reference tokens are generally opaque tokens which contains a GUID like identifier in it and no other details. In order to validate the authenticity of these tokens, the client needs to make a back-channel call to STS. One main advantage is it can be easily revoked by deleting the corresponding identifier in STS DB.

  • "exchanged by the client against an ID token Refresh token" - I am assuming you are referring to Refresh tokens instead of ID token. We use Refresh token for this purpose

Or is the refresh token the thing to use for exactly that?

Yes. Refer to the above comments

Or do we have to solve this outside OpenID Connect? Which leaves the question how to resolve opaque tokens from API requests against identity details (JWT) for use in our API/services?

If you use opaque tokens, OIDC/OAuth 2.0 has several endpoint (like UserInfo) to get further information about the user. You can also use Introspection endpoint to know the validity of the token.

(Scenarios 3 and 4): I am not sure how you plan to use this - But for any non-interactive client(which is acting on its own and not behalf of user), you should use client credentials flow.

If the client want to act on behalf of user, you should enable a way for the user to approve this behavior.

Community
  • 1
  • 1
Karthik
  • 3,075
  • 3
  • 31
  • 61
0

I recommend anyone who is interested in OpenID Connect (OIDC) to look into OAuth2 specification. Since OIDC is built up-on OAuth2, it inherits many fundamental features.

First thing to note is Implicit flow does not return a refresh token.

The implicit grant type is used to obtain access tokens (it does not support the issuance of refresh tokens) and is optimized for public clients known to operate a particular redirection URI

If you want to rely on refresh tokens, then you MUST consider this fact.

Can this be done purely with one of the tokens issued by the OpenID Connect implicit grant type?

It depends on the design and exact requirements. But you can indeed build the authentication on top of Id token and use access token for API calls. To validate access tokens, you can use introspection endpoint from API endpoint.

Can an access token be issued in a long-lived (no expiry, only invalidated by deleting from the system) way and then be exchanged by the client against an ID token?

This could be possible depending on the configurations of identity provider expose. But by specification, this should not be done for a client who use implicit flow. And simply because of security reasons. This is the very same reason why implicit flow does not return a refresh token. On the other hand, refresh tokens are the one which can live longer. For example, Google's refresh tokens never expires (reference - 8953983).

Or is the refresh token the thing to use for exactly that?

As mentioned previously, refresh tokens can long-lived. And it can be exchanged for a fresh access token. Returning of the id token for a refresh token will depend on identity provider implementation. For example, Azure AD do return an ID token for refresh token response. But going beyond that, the identity provider can offer a user info endpoint. A good article can be found from this link

Or do we have to solve this outside OpenID Connect? Which leaves the question how to resolve opaque tokens from API requests against identity details (JWT) for use in our API/services?

ID token indeed help to authenticate the end user from client side. But when it comes to validate user from API endpoint, you can think about using introspection endpoint or a user info endpoint. But be mindful, some identity providers do not provider introspection endpoint. At the time of writing this article Azure AD do not expose one (reference - 43378748) but do provide a user info endpoint.

Community
  • 1
  • 1
Kavindu Dodanduwa
  • 12,193
  • 3
  • 33
  • 46