Invalid Authorization Code error using OAuth 2.0 policy with external authorization

Not applicable

I'm having issue with configuring OAuth 2.0 with external authorization.

The scenario I want to implement is simple and straightforward. I want to integrate Apigee with existing backend authentication and authorization service that implements OAuth 2.0 flows while keeping client_id / client_secret validation on Apigee.

I took the policy configuration from Using third-party OAuth tokens as basis for a reverse-proxy setup.

The API proxy has two flows: /authorization and /token.

The /authorization proxy flow loads related app info and redirects user agent to auth server login page.

<Flow name="authorize">
    <Description/>
    <Request>
        <Step>
            <Name>Get-OAuth-v20-Info-1</Name>
        </Step>
        <Step>
            <Name>Access-To-Application-Entity</Name>
        </Step>
        <Step>
            <Name>Extract-App-Name-from-Entity</Name>
        </Step>
        <Step>
            <Name>Redirect-To-Login</Name>
        </Step>
    </Request>
    <Response/>
    <Condition>(proxy.pathsuffix MatchesPath "/authorize") and (request.verb = "GET")</Condition>
</Flow>

The /token target flow is implemented as pass-through flow to backend auth server token endpoint. There are policies in response flow to parse server response, extract access and refresh token and store both in Apigee.

<Flow name="token">
    <Description>token</Description>
    <Request/>
    <Response>
        <Step>
            <Name>Set-External-OAuth-Status</Name>
        </Step>
        <Step>
            <Name>Extract-Code</Name>
        </Step>
        <Step>
            <Name>Set-OAuth-Tokens</Name>
        </Step>
    </Response>
    <Condition>(proxy.pathsuffix MatchesPath "/token")</Condition>
</Flow>

Extract-Code policy definition:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ExtractVariables async="false" continueOnError="false" enabled="true" name="Extract-Code">
    <DisplayName>Extract Code</DisplayName>
    <Properties/>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <JSONPayload>
        <Variable name="access_token">
            <JSONPath>$.access_token</JSONPath>
        </Variable>
        <Variable name="refresh_token">
            <JSONPath>$.refresh_token</JSONPath>
        </Variable>
    </JSONPayload>
    <Source clearPayload="false">message</Source>
    <VariablePrefix>apigee</VariablePrefix>
</ExtractVariables>

Set-OAuth-Token policy definition:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 name="Set-OAuth-Tokens" enabled="true" continueOnError="false" async="false">
    <DisplayName>Set OAuth Tokens</DisplayName>
    <ExternalAuthorization>true</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <ReuseRefreshToken>false</ReuseRefreshToken>
    <SupportedGrantTypes>
        <GrantType>authorization_code</GrantType>
        <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true">
        <Format>FORM_PARAM</Format>
    </GenerateResponse>
    <ExternalAccessToken>apigee.access_token</ExternalAccessToken>
    <ExternalRefreshToken>apigee.refresh_token</ExternalRefreshToken>
    <StoreToken>true</StoreToken>
    <Tokens/>
</OAuthV2>

Pretty much the same as config from doc page.

Yet call to /token endpoint fails with 400 error code. OAuth 2.0 policy generates the error with body content:

{"ErrorCode" : "invalid_request", "Error" :"Invalid Authorization Code"}

The question is - what is the reason of the issue? How could I configure the proxy and / or policies to get it working?

Let me know if some info is missing.

Thanks in advance!

0 4 3,637
4 REPLIES 4

Not applicable

Looks like you are trying to implement a OAuth token Generation using Client and Auth types. The error pretty much says that it could be an issue with your request .Please double check your request that you are passing the grant type in your request and the consumer and secret key. For example a typical Client Credentials based grant type will look like the below:

OAuth Policy :

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuth-v20-1"> <DisplayName>OAuth v2.0 1</DisplayName> <FaultRules/> <Properties/> <Attributes/> <Operation>GenerateAccessToken</Operation> <ExpiresIn>100000000</ExpiresIn> <GenerateResponse/> <SupportedGrantTypes> <GrantType>client_credentials</GrantType> </SupportedGrantTypes> <GrantType>request.queryparam.grant_type</GrantType> <GenerateResponse/> </OAuthV2>

Request:

http://yourorg/youruri?grant_type=client_credentials

and in the Header you can pass the consumer key and secret key in Base64 Encoded Format

Header:

Authorization Basic MnFUS3hZQWJ4Z1hhZkwxVzJrNHZmUjZ3VWxveTc3YlY6R1F0OFkzZnBWMEhUbUhBeQ==

let me know if this helps.

Not applicable

Hi Andry,

Your steps looks good,

I think your "invalid_request" error is due to incorrect config in your oauth2 policy.

grant_type: :client_credentials

client_id: ***********

client_secret : *******

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <OAuthV2 name="GenerateAccessTokenClient"> <ExpiresIn>3600000</ExpiresIn> <SupportedGrantTypes> <GrantType>client_credentials</GrantType> </SupportedGrantTypes> <GrantType>request.header.grant_type</GrantType> <GenerateResponse/>

</OAuthV2>

You can also look int document for the detail.

http://docs.apigee.com/api-services/content/oauth-20-client-credentials-grant-type

Former Community Member
Not applicable

Hi Andrey, I have the exact same problem. Could you resolve this?

I had a similar problem with always receiving the "Invalid Authorization Code" error and I realized that I was using ExternalAuthorizationCode incorrectly.

In my /authorize endpoint, I used an ExtractVariables policy to place my external auth code from a target endpoint or service callout into an external_auth_code variable.

In the same flow I included an OAuth v2.0 policy:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-GenerateAuthCode">
    <ExternalAuthorizationCode>external_auth_code</ExternalAuthorizationCode>
    <Operation>GenerateAuthorizationCode</Operation>
    <GenerateResponse enabled="false"/>
</OAuthV2>

Then in my /token endpoint I can use GenerateAccessToken using that external code, just as normal. No need to specify the ExternalAuthorizationCode element here.

My original problem was that I was placing the ExternalAuthorizationCode element in my GenerateAccessToken policy, the same way I was using ExternalAccessToken and ExternalRefreshToken. Silly mistake, but hopefully this helps someone else who's stuck on the same thing!