Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Scope not respected in OAuthV2 GenerateAccessToken operation

Hello,

I have a OAuthv2 policy with the following -

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 name="OA2-GenerateAccessToken" continueOnError="false" enabled="true">
    <DisplayName>OA2-GenerateAccessToken</DisplayName>
    <Scope>request.formparam.scope</Scope>
    <Operation>GenerateAccessToken</Operation>
    <ExpiresIn ref="verifyapikey.VAK-IdentifyConsumer.apiproduct.expires_in">1800000</ExpiresIn>
    <!-- 30 minutes. -->
    <RefreshTokenExpiresIn>28800000</RefreshTokenExpiresIn>
    <!-- 8 hours -->
    <SupportedGrantTypes>
        <GrantType>authorization_code</GrantType>
    </SupportedGrantTypes>
    <GrantType>public.accesstoken.grant_type</GrantType>
    <GenerateResponse enabled="true"/>
</OAuthV2>

As you can see above, I'm requesting Scope in the operation by providing

<Scope>request.formparam.scope</Scope>

This is basically Step 2 of the 3-legged OAuth operation where the authorization code is exchanged for an access_token.

The scope is a formparam as you can see -

The curl of this request is below (sensitive details masked)

curl --location --request POST 'https://example.com/auth-test/v1/accesstoken' --header 'Accept: application/json' --header 'Authorization: Basic 123==' --header 'Content-Type: application/x-www-form-urlencoded' --data-urlencode 'grant_type=authorization_code' --data-urlencode 'code=zMnsJMGd' --data-urlencode 'scope=actionShipmentDelete'

However, when Apigee generates the access_token it does not seem to respect the Scope requested in the above operation, instead it has generated the access_token with the master list of all scopes included in the API Product.

I verified this by building a accesstoken/validate endpoint which is a OAuthv2 policy with VerifyAccessToken operation -

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 name="OA2-ValidateFormParamToken" continueOnError="false" enabled="true">
    <DisplayName>Validate Form Param OAuth2 Token</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>VerifyAccessToken</Operation>
    <AccessTokenPrefix>Bearer</AccessTokenPrefix>
    <Scope>actionShipmentCreate</Scope>
    <SupportedGrantTypes/>
    <GenerateResponse enabled="false"/>
    <AccessToken>public.access_token</AccessToken>
    <Tokens/>
</OAuthV2>

As you can see I'm restricting the scope of this policy to

<Scope>actionShipmentCreate</Scope>

and I'm expecting this policy to fail but it passes as the acces_token is minted with master scopes.

How can I have Apigee use the scope that I provide in the GenerateAccessToken operation through a HTTP parameter?

Solved Solved
0 9 602
1 ACCEPTED SOLUTION

I think maybe your expectations are not quite correct.

You are showing a request to redeem a code for a token. This is the 3-legged flow, in which

  • a client app requests /authorization, passing client credentials
  • the token dispensary redirects the client app to a login-and-consent experience
  • the user signs in, approves the scopes
  • the login-and-consent experience generates a code, sends it back to the client app
  • the client app sends the code to the token dispensary to redeem the code for a token

I think you are showing the final step in this process. In that step, the client app says "I have a code here, and I want to exchange it for a token." The client app, at that point, must not specify a set of scopes.

The client app can request a set of scopes (in the call to /authorize), but the actual set of scopes to be associated to the token must be explicitly approved by the user at the time of consent. Apigee associates the set of approved scopes to the code that it generates at that time.

Specifying the scope at the time of code-for-token redemption must not be permitted, because a malicious client application could specify any scopes it wants, though the user approved a different set. That would not be ok.

Does this explanation make sense?

Maybe you have the specific case in which the client is trying to *narrow* the set of scopes on the token, after the user already approved a different set of scopes. In other words, the scopeset the client app passes to Apigee when redeeming the code for a token is a subset of the scopeset that the user approved. That would also be the wrong time to try to set scopes. If the client app wants a small set of scopes, it should request a small set of scopes, and then the login-and-consent experience would prompt the user to approve those.

View solution in original post

9 REPLIES 9