0

I am implementing a web service with a front end and back end. Everything but the login endpoint requires authentication. For authentication I use Authentik. However, I have trouble wrapping my head around which tokens to give to the user, given Authentik's configuration options.

Currently, my authentication process works as follows:

  1. On login, the user is sent to the OIDC provider's authorization endpoint and comes back with an access_code.
  2. Back end sends the access_code to the token endpoint to retrieve the id_token, access_token and refresh_token.
  3. Back end sends the id_token and refresh_token to the user and discards the access_token (I only need to know if the email address is a company email, which is already included in the id_token). The id_token and refresh_token are stored as cookies (Secure, HttpOnly, SameSite=strict).
  4. Whenever the user makes a request to an endpoint requiring authentication, I check the signature on the id_token, the intended audience (aud) and the expiration time (exp). If those checks pass, I trust the email address in the user-supplied id_token.
  5. If the ID token is expired, I use the refresh_token with the token endpoint to get a new id_token and refresh_token.
  6. If the user logs out by themselves, I use the revocation endpoint to revoke both the refresh_token and the id_token. Afterwards, the cookies are deleted.
  7. If the user needs to be logged out by me (left the company), I remove the user's ability to use their company email with Authentik. Then, the next time the id_token expires, the refresh will fail and the user will not get a new id_token. This means that after one expiration period, the user will be logged out automatically.

I have implemented these steps and the process works quite nicely. I currently do not need to create my own session cookies or sign my own JWTs with a persistent secret, which I would like to keep.

However: Authentik does not provide a way to configure the id_token expiration period. I can only configure that for the access_code, access_token and refresh_token. The lack of documentation on that leads me to believe that I might have misunderstood OIDC.

Could someone enlighten me on this?

EDIT: As a hacky workaround, I've made my backend reject ID tokens that are older than 5 minutes. This is implemented by checking the iat ("issued at") claim. Effectively, my backend now treats ID tokens as having an expiry time of 5 minutes. This perfectly suits my use case. However, I find it confusing that I wasn't able to find a more "proper" solution in OIDC and that I haven't found any guides that highlight this exact problem.

9
  • In #7, why aren't you revoking the ID token and regsitered email? A signed in user even if he left the company will be able to use the unexpired ID token to access the resource.
    – defalt
    Commented Jul 11, 2023 at 11:28
  • @defalt The back end does not have a revocation scheme itself. If it receives a valid ID token, then it treats the user as authenticated. The back end only checks with the OIDC provider when refreshing the ID token. The revocation works by making the ID token short-lived (5-10 minutes) and revoking the refresh token. Then, during the next refresh cycle, the user whose access was revoked will not get another valid ID token.
    – Tim
    Commented Jul 12, 2023 at 12:28
  • But the user still can access the resource for max 10 minutes after being removed from the organization. Is it an acceptable threat for you?
    – defalt
    Commented Jul 12, 2023 at 14:09
  • @defalt Yes, that is acceptable. In fact, that delay is precisely why I was trying to lower the default expiration period of 30 days in the first place. 10 minutes is okay, 30 days is not.
    – Tim
    Commented Jul 13, 2023 at 9:12
  • 1
    "However, I find it confusing that I wasn't able to find a more "proper" solution in OIDC". The solution is there in OIDC, use access token for authorization to API and ID token for identifying the user.
    – defalt
    Commented Jul 26, 2023 at 16:00

1 Answer 1

0

You need access token to limit authorization and roles of the caller and to identify the caller, you need an ID token. Together they build authorization and authentication. If your web service has administration and/or premium APIs to which only certain users get access, you have to give access token to the user so that your APIs can individually validate roles and permissions at the time of being called by the user. As you are discarding access token, I'm assuming your users have equal authorization to access resources of your web service.

You can still improve your session management by not going off-spec from OIDC and for that you do need access token for the following:

If the ID token is expired, I use the refresh_token with the token endpoint to get a new id_token and refresh_token.

  1. You don't have to refresh the access token just to get a fresh ID token. Instead, use access token and call /userinfo endpoint to get the fresh ID token. If the user has been removed from the organization, you won't be able to use that access token to retrieve a new ID token so your web service can immediately clears the session of the user.

  2. Access token can be re-verified live by the identity provider (IdP) by using Token Introspection. So, if the user has been removed from the organization, instead of waiting for the token to get expired, your APIs can use token introspection to know that the access token has been revoked before giving access. This will also prevent a small window of attack in which the user has been removed from the org but its cookies still has unexpired access token which can be used to continue using your service.

  3. Unlike access token, ID token can neither be introspected nor be forcefully revoked.

Note: As token introspection request makes I/O with the IdP, it should be periodically used in cases like if the user was inactive for a while or if the cache of token introspection response has expired. If the access token has already expired, there is no need to make token introspection request for that token.


If the user logs out by themselves, I use the revocation endpoint to revoke both the refresh_token and the id_token. Afterwards, the cookies are deleted.

OIDC has RP-Initiated Logout for this in which when the user initiates logs out, access and refresh token are revoked at the IdP's end, the web service clears cookies of the user and logs out the user on the web app.

If the user needs to be logged out by me (left the company), I remove the user's ability to use their company email

OIDC has Back-Channel Logout for this in which the IdP revokes tokens and issues the logout request to your web service and your web service logs out the user.

Authentik does not provide a way to configure the id_token expiration period. I can only configure that for the access_code, access_token and refresh_token.

Then you should use a short-lived access token and give it to the user.

11
  • "you have to give access token to the user so that your APIs can individually validate roles [...] As you are discarding access token, I'm assuming your users have equal authorization to access resources of your web service." That is not the case. My users have different permissions based on the group that they are in. Those groups are defined in the OIDC provider and are included in the ID token.
    – Tim
    Commented Jul 17, 2023 at 8:47
  • "You don't have to refresh the access token just to get a fresh ID token. Instead, use access token and call /userinfo endpoint to get the fresh ID token." That is not the issue. Whether I refresh via /userinfo or the refresh token does not really matter to me. What matter to me is that my ID token does not expire fast enough.
    – Tim
    Commented Jul 17, 2023 at 8:50
  • "So, if the user has been removed from the organization, instead of waiting for the token to get expired, your APIs can use token introspection to know that the access token has been revoked before giving access." That would require talking to the OIDC provider with every user request, would it not? I am trying to avoid that as that makes my web app much slower.
    – Tim
    Commented Jul 17, 2023 at 8:52
  • "OIDC has Back-Channel Logout for this in which the IdP revokes tokens and issues the logout request to your web service and your web service logs out the user." Hmm, that doesn't seem very elegant. I currently don't have to keep track of user sessions because the JWT ID token in the client's cookies has everything I need. If I have to track "remotely logged-out" users, then that's pretty much the equivalent of maintaining a revocation list. I'm looking for a more "automatic" solution that doesn't require extra state on the web service.
    – Tim
    Commented Jul 17, 2023 at 8:55
  • "Then you should use a short-lived access token and give it to the user." Authentik's access token has the same format as the ID token, so I guess that would work. However, won't that give the user to ability to talk to the OIDC provider in my web apps name? More specifically, is the user even supposed to have access to the access token? I thought the access token was intended for communication between my web service and the OIDC provider / resource provider.
    – Tim
    Commented Jul 17, 2023 at 8:59

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .