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

OAuth with external IdP, with Apigee in the role of client application

Not applicable

I'm having trouble fitting our authentication/authorization use case into the OAuth flows as envisaged by the Apigee documentation.

I believe this is because as we envision our use case, Apigee would need to be playing the OAuth role of the client app, with our back-end APIs in the role of resource servers. In addition, we are using an external OAuth identity provider, and it's not entirely clear from the Apigee documentation concerning external OAuth tokens how we'd configure what we want to do (or if we need to create our own custom policies).

Here is the auth code flow we would like to implement:

1. Browser makes a request for an endpoint protected by Apigee. I.e., the resource owner's user agent makes a request to the client application (Apigee) for Apigee to access on behalf of the resource owner a protected resource (the back-end API) and send back the resource to the browser.

2. Apigee sees that this browser session is not authenticated and redirects the browser to the external identity provider (auth server).

3. The resource owner authenticates with the identity provider and authorizes Apigee to access the APIs on behalf of the resource owner.

4. The auth server redirects the browser back to Apigee with an auth code.

5. Apigee uses the auth code to make a back-channel request to the identity provider to obtain an access token. (This is signed JWT containing claims, but Apigee doesn't look at this information.)

6. Apigee makes an upstream request to the resource server, to exchange the IdP's token for a resource server token. [I understand that this is not part of the standard auth code flow.]

7. Apigee stores the token received from the resource server.

8. Apigee redirects the browser back to the originally requested endpoint.

9. Thereafter (for the duration of the browser session) when accessing upstream resources in response to requests from the browser, Apigee adds the resource server's token to the appropriate header.

What's important to us here is that, because the identity provider and resource server tokens contain claims and other information we don't want exposed (even if encrypted), we don't want them to be sent back to the browser or visible to external user agents.

I've looked at the Apigee OAuth documentation, particularly with regard to using third-party OAuth tokens, and have also studied the musicapi-oauth-delegated-authentication tutorial (https://github.com/dzuluaga/apigee-tutorials/tree/master/apiproxies/musicapi-oauth-delegated-authentication). However, the exact meaning of the configurations for the OAuthV2 policy are not specified clearly enough for me to understand how to manage the configuration in this particular case, nor to understand what I might need to implement in a custom policy. Might someone help me with this?

EDIT

I think I'm beginning to piece this together. Using the example of the musicapi-oauth-delegated-authentication tutorial, I think this is how the story would go:

1. All the back-end endpoints protected by Apigee would be protected by an OAuthV2 VerifyAccessToken policy, which would result in a redirect to the identity provider if the token is invalid or absent.

2. After login, the identity provider would redirect back to Apigee's /generatetokens endpoint with the auth code

3. The part that is missing in the example on GitHub is that service callouts that need to be performed before the OAuthV2 Store External Token policy is called. In the example on GitHub, before this policy is called there is an AssignMessage policy that sets the oauth_external_authorization_status flow variable to true. In real life, what has to happen instead is to have a service callout which POSTs the Identity Provider's auth code to its token endpoint in order to receive back an auth token. Only if this succeeds should oauth_external_authorization_status be set to true, otherwise it should be false (which means that the access token won't be generated and saved, which it shouldn't be).

4. For the flow I described in my original question, I will also need a second service callout to the upstream resource server's token endpoint to receive the upstream token. In that case, oauth_external_authorization_status shouldn't be set to true unless this service callout also successfully returns a token.

5. Once this token is returned, I need to save it so that it can be added to the headers when subsequent requests come in from the user. This part I'm not clear about.

6. Now the OAuthV2 Store External Token policy is invoked to generate an Apigee access token and store it.

7. This token is supplied to the user agent and is used in subsequent requests.

8. Requests with a valid Apigee access token are passed through to the back-end API with an added header containing the upstream token.

Does that sound right?

If so, the only things I'm vague about now are:

1. Saving the upstream token

2. Handling token refresh -- the Identity Provider's access token expires after a certain amount of time; the Identity Provider supplies a refresh token along with the access token. It's still not entirely clear to me how this fits into the flow. It's looking to me like I'm going to have to manually code refreshing the token from the identity provider; is that right? I imagine that the token issued by Apigee also expires, so I'm not sure how best to handle the interaction between these expirations.

EDIT #2

OK, so I am experiencing one additional difficulty. As a result of the success or failure of the service callouts I need to set oauth_external_authorization_status. I'm not sure how to do that with an Extract Variables policy, since servicecallout.RequestAuthToken.failed is boolean so it won't match a text pattern, and I don't know how to create a boolean value in an Extract Variables policy either. How do I accomplish this?

2 19 5,276
19 REPLIES 19