Search code examples
oauth-2.0openid-connectokta

How do I request a properly scoped Access Token when the User needs to log in first in order to determine those scopes to request?


Context

A User logs in to my SPA using OIDC. My SPA communicates with its own backend REST API, and I would like to protect access to that API with an OAuth Access Token. The role of the User that logs in will determine which API endpoints they are allowed to access, and in what capacity. The backend API is not the User's data. It is the SPA's own API that has nothing to do with user data. An Admin user will be able to create and read resources via the API, and a Standard user will just be able to read resources via the API. I'm using Okta as my Identity Provider/Auth Server.

Question

My SPA needs to know the user's assigned role before requesting an appropriately scoped Access Token for the backend API. So, I'm thinking that I need to log in the User, inspect the user's role in the ID token, and then somehow make an additional request to the Authorization Server with the proper scopes included (either just read, or read write). But I'm a little confused because I'm not sure what flow I would use to make this additional request (or even if I need to!). I mean, I already get an Access Token bundled with the ID token when the User logs in, but it's not really scoped for the backend API.

I hope that is clear. What is the appropriate action I should take here?

Thanks


Solution

  • Here is a revised answer, since it is a year after the original one, and I guess both of our understandings have moved on a little.

    SCOPES

    The scopes represent the types of data a client application is allowed to access. If different users have rights to different areas of data, the application scopes do not change.

    USE A CLAIM, NOT A SCOPE

    When you want dynamic authorization based on the user identity, the answer is almost always a custom claim, which is just another field in the token. So ideally you want your apps to receive tokens that contain this type of data:

    {
      role: 'admin'
    }
    

    WHERE TO ISSUE THE CLAIM

    • The role should always be included in an access token so that an API can use it for authorization
    • The role could also be included in an id token if the UI needs to use it

    HOW TO ISSUE THE CLAIM VALUE

    This can be done in a couple of different ways:

    • If the role already exists in Okta you may be able to just add the claim for logged in user
    • If the role exists elsewhere, then you may need to reach out from Okta to a Custom API or Database at the time of token issuing

    USER ID TRANSLATION

    In some cases, this can involve translating from the Okta User Id (the subject claim) to your API's own User Id.

    IF YOU CAN'T ISSUE A CUSTOM CLAIM

    Then you can look up the role in your custom API when it first receives the token, then use the value as a custom claim in your API's code, as in my Authorization Write Up. The value of the claim could then be returned to the UI via an API call.