JWT token claim mapped to internal UUIDs

Most of our use cases seems to have some custom requirement which we are not able to design. So, for example, a guardian has minors associated with his banking account. The guardian in the mobile app. switches to the minor’s view and starts transacting.

My current idea is this.

  1. There is a primary JWT token for the guardian with his ID as claim. Internally it is mapped to multiple minor accounts. The API will return a set of minor UUIDs.
  2. When guardian transacts by passing a minor’s UUID( something like a PPID ? https://curity.io/resources/learn/ppid/ ) but this is in the database ) the guardian will be able to transact.
    UUID is used because they are all unique we cannot spoof a new one.
    But if we were to issue new JWT tokens every time the guardian switches to the minor’s view and transacts we may be issuing too many new tokens. Every time we could issue a new token with the guardian’s ID and Minor’s ID as claims.We have many such minors for a guardian.

Are we ignoring a deeper authorization design here ?

Thanks,
Mohan

One obvious thing I see: why do you need that included into the token? Can’t your backend extract that information based only on guardian ID? Or are you trying to avoid verifying if your guardian can act on minor’s behalf in the backend service? I assume it should be embedded into the business logic, and not only represented in the token

Or are you trying to avoid verifying if your guardian can act on minor’s behalf in the backend service?

If it is possible then we can have a claim in the token. The PII IDs are inside the token and we are trying to find if we can avoid POSTing the IDs back to the API. But we couldn’t include all minor IDs as claims. There are several.

So a general claim indicating that the guardian can transact on behalf of others will be needed. I am not sure if it is a scope or claim. Have read there is no strict definition of what a claim can be. It looks like a permission.

Thanks,
Mohan

Hi Mohan!

This is a great question but what you are looking at is kind of muddy, so let’s see if we can straighten it out and give you a couple of solutions. And it looks from your questions that we need to define a couple of things here as we go :slight_smile:

  1. Switching authorized-account views doesn’t change who is authenticated, so you can’t really issue a new access token without re-authenticating as another user. So that part under your #2 in the original post really isn’t a solution. BTW, let’s stick to “access token” as OAuth describes it; both access tokens and ID tokens are JWTs, so “JWT token” isn’t really focused.

  2. Just to get it out of the way, a “scope” defines a “claim” you want in the token. You can get a visual representation if you look at scope and claim tabs on the security → API settings for an authorization server. Scopes are things you can ask for, claims are the data you get back. Scopes are granted, so any given user may or may not have permission to get a claim.

  3. This seems a bit complicated because you mentioned in your reply that you didn’t want to post the ID for the account being viewed back as part of the request to the API. There isn’t any way around that, because when you make the API call you need to say what you are looking for and if you can access multiple accounts you have to say which one. It has to be a parameter in the call. BTW, you can see this in real life if you have a banking app and you are granted rights to multiple accounts. It seems that maybe you are confusing authorization with telling the API what you want to access?

  4. Okta provides identity management. A lot of information, like an account balance, should never go into the Okta directory. So, assuming that the authenticated user has a “profile” in the datastore for your API, the simplest way to handle the authorization for other accounts is to keep it in that profile. When the API pulls the user profile on a request it can check if the requested account is authorized and what type of access is authorized. This is what @phi1ipp was getting at in his reply.

  5. If you prefer to pass account authorization through the access token we can make that work too. It is authorization information, so it can be argued that it belongs in the access token. The authorized accounts and the type of access can be passed as a custom claim. You can have a custom scope to request this claim too. There are two ways to build the claim:

    A. The first way is to manage all the information on the Okta side. You can add a custom profile attribute (probably a string array) with the ids of the accounts that are authorized. Then you can create a custom claim that uses an Okta expression to get the data from the profile and add the claim to the access token on the way back. Of course, now you need to manage that profile attribute, either manually through the Okta admin interface or via a management application that uses the Okta API.

    B. You can manage the authorization on your side but still insert it into the access token. You would do this by using an “inline hook”: Okta will query your API for the claim information whenever an access token is being created, and then insert that claim into the token before it is sent out.

I hope this has helped :slight_smile: Reply back if you aren’t clear or need something more!

Joel

1 Like

Read your mail a few times. Thanks.
The first access token is the the normal login token. When we ‘step up’ the authorization we can issue
another token access token or replace the normal login token with the additional scope ? I understand the user has to provide some type of credential( like an OTP ? ) for that.
But without this ‘step up’ we assume user needs extra privilege always. This seemed like a special privilege in the Banking system.

Yeah, I know this stuff can be confusing! I think I understand that you want to do this step up. Let’s back up for a moment and make sure we understand authorization servers which issue tokens. Okta only supports one target in a token so generally you want one authorization server per API (the target), and only that API will accept the token. To issue tokens for your banking API, you need an authorization server configured for it.

Okta has two types of authorization servers (you’ll see three in the documentation). The org server issues tokens that target the Okta API, and you cannot configure this server.

Custom servers target your APIs and are fully configurable, your scopes and your claims. There is a “default” server that you always get in your tenant, but it’s actually just a custom server that you can use for an API without having to build the configuration from scratch.

There is a lot going in an authentication flow against one of these servers. At the core it really doesn’t matter which of your authorization servers you authenticate against, you can ask for an ID token and/or an access token. If the flow is followed properly, you end up with an Okta session cookie in your browser and if you go back to ask for a token from any of the authorization servers in the same tenant it will recognize you and you don’t have to provide credentials again. At least until your session ends.

Most of the time I want an Okta API token so that my app can talk to the Okta API and do things like extend the session at Okta while I’m using it. So, I’ll authenticate against the org authorization server and get an ID token (a better picture of who the user is) and the access token for the Okta API. Now I can talk to Okta as the logged in user. Then I’ll turn right around and query the other authorization server or servers for the API tokens I need for my own API or APIs. The user doesn’t see anything, these tokens are just given to me because Okta recognizes the user is already logged in.

So, about that “step up.” You’re absolutely right, you can do it either way. One system I do know is Chase, and in their system you have the authorization for every bank account you are entitled to immediately on login. The system actually uses that to present a list of all the accounts and balances on the home page after login.

But if you want to do a “step up” where the user needs to click a button or something to access the other authorized accounts I would just use scopes. On login I don’t ask for the scope that adds the claim that gives me access in the API, so the API doesn’t look at them. Then If the user requests it, I go back and ask for a new token with that scope. The user won’t be prompted for credentials if they are allowed to request the scope, they are already logged in.

Finally, you need to know that tokens have a short life span and usually expire before the user is finished with the application. There are two reasons for this: first if the token is exposed, it won’t be useful for long. Second, configurations change and that can affect the token so getting a new token frequently reflects any changes.

For this, we ask for a refresh token along side of the access token. It’s not a JWT, it’s just a unique code. It’s faster to use a refresh token to update a previously issued token because you don’t have to deal with the auth-code-flow, etc. When the access token we are using is close to expiring, we go back and ask for a new access token passing in the refresh token. Old refresh tokens had long life spans and that was a security risk. Newer applications always use rotating refresh token where the new access token comes with a new refresh token to update it.

Sorry it’s long, but I want to make sure I’m helping. I don’t know what your situation is, but just in case it is useful to you a lot of this is covered in the Okta API Access Management with OAuth class, with hands on labs.

Thanks. Need to try Okta API Access Management with OAuth class, with hands on labs.

You’re welcome, I teach it, hope to see you there!