JWT Policy scopes

Hi. I have been tasked with converting opaque token to jwt. When using oauthv2 gen token policy, the list of allowed scopes as specified in the Product/App are populated. This doesn't seem to be the case when using Generate JWT policy. How do I transfer these scopes to JWT policy? I can add the claim, but so far not seeing how to retrieve this outside of OAuthV2 policy.

Solved Solved
1 6 646
1 ACCEPTED SOLUTION

ok I understand. The variable for the scope is oauthv2accesstoken.POLICYNAME.scope

One thing to be aware of: the value contained within that variable is a SPACE-separated list. Adding a claim into a JWT and referring to a variable that contains a space-separated list.... results in a claim with a string value. It might look like this:

"scope" : "scope1 scope2 scope3"

If you want the scopes to be embedded into the JWT as an array, I don't know a way to do that except to replace those spaces with commas, and set the scope claim to the result of THAT. You can do that with an assignmessage policy:

<AssignMessage name='AM-ReformatProperties'>
  <AssignVariable>
    <Name>COMMA</Name>
    <Value>,</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>SPACE</Name>
    <Value> </Value>
  </AssignVariable>
  <AssignVariable>
    <Name>reformed_scope</Name>
    <Template>{replaceAll(oauthv2accesstoken.POLICYNAME.scope,SPACE,COMMA)}</Template>
  </AssignVariable>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

To see this work, update GenerateJWT to use something like this:

  <AdditionalClaims>
cessToken-CC-NoResponse.access_token'/>
    <Claim name='scope-one-value' ref='oauthv2accesstoken.POLICYNAME.scope'/>
    <Claim name='scope-list' array='true' type='string' ref='reformed_scope'/>
  </AdditionalClaims><br>

Then you would get in the payload of the JWT:

...
"scope-one-value" : "scope1 scope2 scope3",
"scope-list" : ["scope1", "scope2", "scope3"],
...

I have updated the example I cited previously to show how to do the replacement.

View solution in original post

6 REPLIES 6

Coincidentally I recently wrote an article and recorded a screencast on the topic of configuring a token dispensary to issue either opaque token or a JWT. Find it here.

the list of allowed scopes as specified in the Product/App are populated. This doesn't seem to be the case when using Generate JWT policy. How do I transfer these scopes to JWT policy?

I don't think of it as "transferring" anything. The opaque OAuth token has its own associated metadata, this may include scopes or other, custom attributes. The JWT is an independent thing; it has its own claims, which may include non-standard claims like "scopes" or etc. In Apigee, you create them differently. The opaque token with the OAuthV2/GenerateAccessToken policy, and the JWT with the GenerateJWT policy. There is not a motion of "transferring" things in the OAuth token to the JWT.

I can add the claim, but so far not seeing how to retrieve this outside of OAuthV2 policy.

I think what you're saying is... you are using the GenerateJWT policy, and you know how to add a claim with the name ("scopes") that you want. And, you're wondering how to retrieve the list of apiproducts that the clientid is authorized for.

There's a lesser-used option in GenerateAccessToken that tells the policy to NOT generate a response. Instead, it simply sets variables with names of a specific form. For example:

  • oauthv2accesstoken.POLICYNAME.access_token
  • oauthv2accesstoken.POLICYNAME.token_type
  • oauthv2accesstoken.POLICYNAME.expires_in
  • oauthv2accesstoken.POLICYNAME.issued_at
  • oauthv2accesstoken.POLICYNAME.api_product_list_json
  • and so on...

Check the documentation for more details.

So if you want to encode the product list in the JWT, you just need to refer to the appropriate variable. I just updated the example proxy (see first link above) to show how you could do this.

But, I have some other comments. Why do you want to insert the list of api products into the signed JWT? When a later proxy invokes VerifyJWT, the VerifyJWT policy does not check the list of apiproducts. That policy simply verifies the signature on the JWT, and the validity times, and optionally checks the issuer, subject, and audience.

So you need to take care in understanding your expectations and assumptions about what it means to add claims to a JWT when you generate it.

Thnx for reply Dino. I am not looking add the list of api products in claims. I'm looking to populate the scopes claim with those set in the API Product. I am trying to figure out how to retrieve those scopes after running the VerifyAPIKey policy so I can add them to jwt. API management call can retrieve scopes, but docs don't state any scope variable within the UI that is accessible.

Actually let me rephrase a bit. When using opaque tokens, the scopes generated in that token (which my understanding is a list of all scopes used by all the products associated with the API key/app) is the list of scopes I need to populate for jwt. This is what I need to figure out how to retrieve.

ok I understand. The variable for the scope is oauthv2accesstoken.POLICYNAME.scope

One thing to be aware of: the value contained within that variable is a SPACE-separated list. Adding a claim into a JWT and referring to a variable that contains a space-separated list.... results in a claim with a string value. It might look like this:

"scope" : "scope1 scope2 scope3"

If you want the scopes to be embedded into the JWT as an array, I don't know a way to do that except to replace those spaces with commas, and set the scope claim to the result of THAT. You can do that with an assignmessage policy:

<AssignMessage name='AM-ReformatProperties'>
  <AssignVariable>
    <Name>COMMA</Name>
    <Value>,</Value>
  </AssignVariable>
  <AssignVariable>
    <Name>SPACE</Name>
    <Value> </Value>
  </AssignVariable>
  <AssignVariable>
    <Name>reformed_scope</Name>
    <Template>{replaceAll(oauthv2accesstoken.POLICYNAME.scope,SPACE,COMMA)}</Template>
  </AssignVariable>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</AssignMessage>

To see this work, update GenerateJWT to use something like this:

  <AdditionalClaims>
cessToken-CC-NoResponse.access_token'/>
    <Claim name='scope-one-value' ref='oauthv2accesstoken.POLICYNAME.scope'/>
    <Claim name='scope-list' array='true' type='string' ref='reformed_scope'/>
  </AdditionalClaims><br>

Then you would get in the payload of the JWT:

...
"scope-one-value" : "scope1 scope2 scope3",
"scope-list" : ["scope1", "scope2", "scope3"],
...

I have updated the example I cited previously to show how to do the replacement.

Stephen, was this helpful?

yes thank you. I wasn't sure if was good practice to generate an opaque token, extracting parameters and then discarding it to generate a jwt, but your post answered the question.