Retrieving scopes programattically

Not applicable

Hi, i would need to retrieve the scope programmatically during the OAuth authorization code grant flow (btw. I need to do that to verify that an user is allowed to grant required-scopes to an app). Has anyone done that i.e. retrieving scopes programatically? thanks, Antonio

Solved Solved
1 9 793
1 ACCEPTED SOLUTION

Before I answer, Let's set some foundation.

For each API product, the API publisher can specify valid scopes.

To kick off a 3-legged (authorization code) OAuthv2 grant flow, the client app performs a GET on a URL that includes a query param, which specifies a set of one or more scopes. There's another query param that specifies the client id, which refers to a specific set of one or more API products.

Then some redirection happens:

  • a 302 from the Edge proxy to the the login+consent app.
  • Upon successful login/authentication, this happens:
    • the login+consent app calls into an Edge proxy to run the OAuthV2/GenerateAuthorizationCode policy. The login app sends in the requested scopes.
    • Edge validates the request, and if valid, generates a code
    • login app receives the authorization code
    • sends a 302 back to the client, containing the authz code. This 302 points to the Edge proxy. The scopes on the token are identical to those validated and checked during the GenerateAuthorizationCode step.
    • the client app then GETs that URL, which generates an access token

If the scopes sent by the login app into Edge, to request generation of the authorization code, are not valid for the given set of one or more API products that are valid for the client_id, then... the OAuthV2/GenerateAuthorizationCode policy in Edge will send back an error. ("invalid scope" I think). And in this case no authorization code is generated.

ok, given all that.... at which point do you want to query the scopes?

And which actor is doing the querying?

I have built login apps that perform a call into a custom endpoint on the Edge oauth proxy, to inquire "which scopes are available on this client_id"? This way the login+consent app could show a set of checkboxes for all the scopes, and the user could optionally select or deselect those scopes. Then, when the user says "OK" the login+consent app could request a code with a specific set of scopes, which presumably is the intersection of (scopes requested by client app) and (scopes approved by user), which is a formal subset of (scopes available on the API product).

2169-scopes-consent.png

To make that happen you need to expose an endpoint on your oauth proxy that accepts a client_id, and then calls OAuthV2/GetOAuthV2Info with that id, to inquire the product or products, and then determine the scopes of those products. And then send that back to the login app.

View solution in original post

9 REPLIES 9

Before I answer, Let's set some foundation.

For each API product, the API publisher can specify valid scopes.

To kick off a 3-legged (authorization code) OAuthv2 grant flow, the client app performs a GET on a URL that includes a query param, which specifies a set of one or more scopes. There's another query param that specifies the client id, which refers to a specific set of one or more API products.

Then some redirection happens:

  • a 302 from the Edge proxy to the the login+consent app.
  • Upon successful login/authentication, this happens:
    • the login+consent app calls into an Edge proxy to run the OAuthV2/GenerateAuthorizationCode policy. The login app sends in the requested scopes.
    • Edge validates the request, and if valid, generates a code
    • login app receives the authorization code
    • sends a 302 back to the client, containing the authz code. This 302 points to the Edge proxy. The scopes on the token are identical to those validated and checked during the GenerateAuthorizationCode step.
    • the client app then GETs that URL, which generates an access token

If the scopes sent by the login app into Edge, to request generation of the authorization code, are not valid for the given set of one or more API products that are valid for the client_id, then... the OAuthV2/GenerateAuthorizationCode policy in Edge will send back an error. ("invalid scope" I think). And in this case no authorization code is generated.

ok, given all that.... at which point do you want to query the scopes?

And which actor is doing the querying?

I have built login apps that perform a call into a custom endpoint on the Edge oauth proxy, to inquire "which scopes are available on this client_id"? This way the login+consent app could show a set of checkboxes for all the scopes, and the user could optionally select or deselect those scopes. Then, when the user says "OK" the login+consent app could request a code with a specific set of scopes, which presumably is the intersection of (scopes requested by client app) and (scopes approved by user), which is a formal subset of (scopes available on the API product).

2169-scopes-consent.png

To make that happen you need to expose an endpoint on your oauth proxy that accepts a client_id, and then calls OAuthV2/GetOAuthV2Info with that id, to inquire the product or products, and then determine the scopes of those products. And then send that back to the login app.

Hi Dino,

i think this helps.

I have just one more question on your recommendation:

"To make that happen you need to expose an endpoint on your oauth proxy that accepts a client_id, and then calls OAuthV2/GetOAuthV2Info with that id, to inquire the product or products, and then determine the scopes of those products. And then send that back to the login app."

i haven't seen how from that policy is possible to extract product scope. any advice?

thanks lot.

Yes,

I apologize, I have misled you there. What you need is to query the product list for the given client id. Rather than OAuthV2/GetOAuthV2Info , I think you need an AccessEntity policy.

  • OAuthV2/GetOAuthV2Info - queries the client id to get attributes on the client (app)
  • AccessEntity (apiproduct) - can get things like product "scopes", given a client_id
  • AccessEntity (app) - like OAuthV2/GetOAuthV2Info, can get info regarding an app, from a client_id

So really, you need THIS:

<AccessEntity name='AE-Product'>
  <EntityType value='apiproduct' />
  <EntityIdentifier type='consumerkey' ref='parsedRequest.client_id' />
  <!-- result is stored in a variable:  AccessEntity.AE-Product -->
</AccessEntity>

That returns an XML document (I know, I know, ... I feel terrible that AccessEntity returns only XML. I wish it would return JSON. It's an outstanding feature request). Then you parse the XML doc to extract the scopes. What I did for this, is to use a XMLToJSON policy, but just for the scopes. Like this:

<XMLToJSON name='X2J-ProductScopes'>
  <Source>AccessEntity.AE-Product.ApiProduct.Scopes</Source>
  <OutputVariable>productScopes</OutputVariable>
  <Options>
    <RecognizeNumber>true</RecognizeNumber>
    <RecognizeBoolean>true</RecognizeBoolean>
    <RecognizeNull>true</RecognizeNull>
  </Options>
</XMLToJSON> 

suggestion: At this point, use the Trace window to see the value of the productScopes context variable. And then (maybe) a Javascript step like this:

var varname = 'productScopes', // output of XMLToJSON
    $ = JSON.parse(context.getVariable(varname)),
    availableScopes = $.Scopes.Scope || []; // array of scope names

And then you can do what you like with that array.

helpful?

@Dino i am trying what you have suggested me. I am sending the client_id as header parameters (the app consumer key) to a test API with no targets. In the trace window the AccessEntity acitvity shows client_id empty. What i am doing wrong? Also, i do not see any scope as return in the response. WHat also i am doing wrong here?

thanks lot.

if the client_id is in a request header, then you must do this for the AccessEntity

<AccessEntity name='AE-Product'>
  <EntityType value='apiproduct' />
  <EntityIdentifier type='consumerkey' ref='request.header.YOUR_HEADER_NAME' />
  <!-- result is stored in a variable:  AccessEntity.AE-Product -->
</AccessEntity>

..and replace YOUR_HEADER_NAME with the name of the header in the request.

@Dino thanks lot this helps. Although i am not sure what is the context of the Javascript code you mentioned 🙂

it would run in a JS step, after the XMLtoJSON. The flow might look like this:

    <Flow name='inquireApp'>
      <Description>inquire product and scopes by client_id</Description>
      <Request>
        <Step><Name>AE-App</Name></Step>
        <Step>
          <Name>AE-Product</Name>
          <Condition>AccessEntity.AE-App != null</Condition>
        </Step>
        <Step>
          <Name>X2J-ProductScopes</Name>
          <Condition>AccessEntity.AE-App != null</Condition>
        </Step>
        <Step>
          <Name>JS-CheckScopes</Name>
          <Condition>AccessEntity.AE-App != null</Condition>
        </Step>
        ...
        

Not applicable

@Dino

I am trying to get the auth code that is generated by the OAuth. Documentation says its available in the flow variable but flow variable is always returning empty. Any help is greatly appreciated.

I tried your example with Assign Message still this is returning empty.

hi - please don't ask questions in ANSWERS to already-answered questions.

If you want to ask a question, click the "Ask a Question" button.

3901-ask-a-question.png

Also, the details you have provided above are not enough. When you ask your new question, make it clear and complete.

Other users will only be able to help you if you provide enough details and are clear about your question. If you provide too much information, it will overwhelm people. Use the body field to provide the details .

please include:

  1. What specifically are you doing? (include code and policy config here if appropriate)
  2. What are you seeing? (include cut/paste of curl output etc here)
  3. What are you expecting to see? (and characterize the difference between expectations and observations if you can)