OAuth with external IdP - "Client identifier is required" when trying to refresh a token

Not applicable

I have an OAuth setup with an external identity provider/manager as discussed in the thread "OAuth with external IdP, with Apigee in the role of client application" (https://community.apigee.com/questions/28209/oauth-with-external-idp-with-apigee-in-the-role-of.html), namely:

  1. A client authenticates to the identity manager through Edge. The upstream identity manager generates an auth code.
  2. Edge intercepts the identity manager's auth code and generates its own auth code, associating the upstream auth code with it as an attribute. Edge sends its own auth code to the client, with a 302 redirect.
  3. The client POSTs to the /token endpoint hosted on Edge, sending the code, the client_id + client_secret, and grant_type=authorization_code.
  4. Edge receives the code, retrieves the associated upstream auth code, and fetches access and refresh tokens from the identity manager. Edge then generates its own access and refresh tokens, and associates the upstream tokens with the newly-generated access token as attributes. The Edge-generated access and refresh tokens are returned to the client.
  5. Subsequent requests to APIs protected by Edge are granted access based on the client submitting the access token as a bearer token in the Authorization header.

So far, so good. This all works.

Now the client wants to refresh the token. Here is the flow:

  1. The client submits the refresh token to a /refresh endpoint along with grant_type=refresh_token. The bearer token is submitted in the Authorization header to authenticate the request. The client_id is also submitted.
  2. Edge verifies the access token and authorizes access to the /refresh endpoint.
  3. Edge retrieves the upstream refresh token that was associated with the access token, and calls the identity manager to do a refresh, generating new upstream access and refresh tokens.
  4. Edge then refreshes its own token, using the RefreshAccessToken operation of the OAuthV2 policy. As part of this policy, the new upstream tokens are associated with the new access token as attributes.

Most of this is working, except for step 4. No matter what I try, the OAuthV2 RefreshAccessToken policy issues the response {"ErrorCode" : "invalid_client", "Error" :"Client identifier is required"}

This happens whether or not I submit the client_id as a form parameter or query parameter, whether or not I use the <ClientId> element in the policy, and whether or not I set the various ExternalAuthorization and external_authorization_status parameters.

I know that the client ID is valid because there is a VerifyAPIKey policy in the flow before the OAuthV2 policy. (I've tried taking that policy out, which also has no effect.)

If I do a trace, I can see the client_id form parameter with the proper value as part of the request body, right next to the grant_type and refresh_token parameters. But Edge just refuses to see it.

What am I doing wrong?

Solved Solved
1 8 1,403
1 ACCEPTED SOLUTION

Not applicable

The RefreshAccessToken takes client_id and client_secret as basic auth header.

http://docs.apigee.com/api-services/content/access-tokens#refreshinganaccesstoken

If you want your request to work over a form param, you can have have this basic auth policy to add the Auth header before OAuth policy is executed: http://docs.apigee.com/api-services/reference/basic-authentication-policy

View solution in original post

8 REPLIES 8

Not applicable

The RefreshAccessToken takes client_id and client_secret as basic auth header.

http://docs.apigee.com/api-services/content/access-tokens#refreshinganaccesstoken

If you want your request to work over a form param, you can have have this basic auth policy to add the Auth header before OAuth policy is executed: http://docs.apigee.com/api-services/reference/basic-authentication-policy

Thanks, that works. It wasn't clear that the policy is so selective, given the flexibility of the other operations.

Should we update the docs to make it clearer? @Floyd Jones maybe you have a perspective?

Hey @Dino and @pblair - I went ahead and made the docs more obvious by adding a bulleted list in bold for client_id and client_secret in the Authentication section of refreshing an access token. Given that other grant types (implicit) and operations (requesting an auth code) require only client_id, I could see guessing that client_id is all that's needed for refresh as well. Just one of those nuances one needs to learn. Hope the bullets help make it more visual.

@Floyd Jones I'm afraid that as matters stand your revision to the documentation is incorrect. If you try adding client_id and client_secret as form parameters they are not accepted and you get {"ErrorCode" : "invalid_client", "Error" :"Client identifier is required"}. Currently the only format accepted is a basic auth header. Is this a bug?

Follow-on question: I'm getting the token back now, but it includes all the attributes I set in the policy, even though I have display="false" on those attributes.

Is there any way I can keep those attributes from being returned in the token response?

I had a similar issue (with Access Token response). I was seeing the user attributes even if display was false. I did not go into further debugging. I ended up with a javascript policy on the response path to strip those parameters off (the ones I do not want).

Seems like a bug!