ExternalRefreshToken - Not storing token

Not applicable

We have an an OAuth2 requirement that means all our User Authentication is managed in an external IDp and where we need the IDp to be the token issuer for all grant types including Refresh Token.

In our implementation we are proxying the calls back to our ID Server and then setting the Tokens back into APIGEE.

In the most part this is working as expected. What is not so clear cut and posing the biggest issue is dealing with refresh tokens on an Authorization_Code flow.

Using the following as source for some of our implementation,

https://github.com/swilliams11/apigee-auth0-external-authorization

We have manged to get authorization_code flow to work fairly successfully. The major difference we have is we are not using callouts. However it works.

The problem time comes when requesting an access token, we receive the access token successfully and we do have the refresh token. When we try to set the refresh token using <ExternalRefreshToken> in a OAuth2 -> GenerateAccessToken we have found using (as suggested by article above) a grant type of "client_credentials" instead of "authorization_code" the actual refresh token is not stored.

If we do use the grant type = "authorization_code", even though we have the authorization code, we keep getting an error of "Invalid Authorization Code"

We are assuming right now that the reason that the Refresh Token is not being set when we set "Client_Credentials" is because of the flow type.

What we would love to know is why, even though the we have code when we update the grant type to "authorization_code" do we get the error.

Solved Solved
0 2 324
1 ACCEPTED SOLUTION

robert
Participant V

Hi @ScottRoberts,

you are correct that the refresh token won't work when the grant type is set to client_credentials. That is because client credentials doesn't support refresh. So that approach is out for this use case. What you could do to remedy is, on the policy to generate the token, set the grant_type to password. You could then add the external refresh and access tokens. That would work and you are done as edge now knows about the external tokens and doesn't really care about the auth code.

However, you have another question about why isn't it working with the auth code grant. In order for that to work, you will need to supply both parts. The first policy would store the external auth code (for the authorize call). The second policy (part of the token call) would use the auth code from the previous call and also allow you to store the external access and refresh tokens. Make sense? Perhaps not so here are the policies to make it all work.

Register the Auth Code. - GET /authorize

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-StoreExternalAuthorizationCode">
    <DisplayName>OA-StoreExternalAuthorizationCode</DisplayName>
    <Operation>GenerateAuthorizationCode</Operation>
    <ClientId>request.queryparam.client_id</ClientId>
    <ResponseType>request.queryparam.response_type</ResponseType>
    <GenerateResponse enabled="false"/>
    <ExternalAuthorization>true</ExternalAuthorization>
    <ExternalAuthorizationCode>external_auth_code</ExternalAuthorizationCode>
    <StoreToken>true</StoreToken>
    <Tokens/>
</OAuthV2>

Register the Token. - POST /token

Don't forget to set oauth_external_authorization_status to true prior to this policy running.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-StoreToken">
    <DisplayName>OA-StoreToken</DisplayName>
    <Properties/>
    <Attributes/>
    <ExternalAuthorization>true</ExternalAuthorization>
    <ExternalAccessToken>external_access_token</ExternalAccessToken>
    <ExternalRefreshToken>external_refresh_token</ExternalRefreshToken>
    <Operation>GenerateAccessToken</Operation>
    <StoreToken>true</StoreToken>
    <SupportedGrantTypes>
        <GrantType>authorization_code</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true"/>
</OAuthV2>

If this post answered your question, please click accept.

View solution in original post

2 REPLIES 2

robert
Participant V

Hi @ScottRoberts,

you are correct that the refresh token won't work when the grant type is set to client_credentials. That is because client credentials doesn't support refresh. So that approach is out for this use case. What you could do to remedy is, on the policy to generate the token, set the grant_type to password. You could then add the external refresh and access tokens. That would work and you are done as edge now knows about the external tokens and doesn't really care about the auth code.

However, you have another question about why isn't it working with the auth code grant. In order for that to work, you will need to supply both parts. The first policy would store the external auth code (for the authorize call). The second policy (part of the token call) would use the auth code from the previous call and also allow you to store the external access and refresh tokens. Make sense? Perhaps not so here are the policies to make it all work.

Register the Auth Code. - GET /authorize

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-StoreExternalAuthorizationCode">
    <DisplayName>OA-StoreExternalAuthorizationCode</DisplayName>
    <Operation>GenerateAuthorizationCode</Operation>
    <ClientId>request.queryparam.client_id</ClientId>
    <ResponseType>request.queryparam.response_type</ResponseType>
    <GenerateResponse enabled="false"/>
    <ExternalAuthorization>true</ExternalAuthorization>
    <ExternalAuthorizationCode>external_auth_code</ExternalAuthorizationCode>
    <StoreToken>true</StoreToken>
    <Tokens/>
</OAuthV2>

Register the Token. - POST /token

Don't forget to set oauth_external_authorization_status to true prior to this policy running.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OA-StoreToken">
    <DisplayName>OA-StoreToken</DisplayName>
    <Properties/>
    <Attributes/>
    <ExternalAuthorization>true</ExternalAuthorization>
    <ExternalAccessToken>external_access_token</ExternalAccessToken>
    <ExternalRefreshToken>external_refresh_token</ExternalRefreshToken>
    <Operation>GenerateAccessToken</Operation>
    <StoreToken>true</StoreToken>
    <SupportedGrantTypes>
        <GrantType>authorization_code</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true"/>
</OAuthV2>

If this post answered your question, please click accept.

Robert, thanks for your input, kind of went a slightly different route. It works, feels like a hack but we basically do the following

Verify that the code coming is is valid then pass that off to our IDServer for full validation and access and refresh code generation and then on the response, for the purpose of the flow generate a new AuthorizationCode just to satisfy the Policy. As we are only really interested in storing the external refresh token and access tokens this seems like a reasonable compromise.