Client Identifier with OAuth External Authorization

Not applicable

I have the following OAuthv2.0 Generate Token Policy (which is attached to the response of the proxy endpoint flow because I get a JWT back from the target endpoint, I then validate&verify the JWT and i'm trying to now store it in an apigee token):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuthGenerateToken">
    <DisplayName>OAuth.GenerateToken</DisplayName>
    <Attributes/>
    <ClientId>response.header.client_id</ClientId>
    <ExternalAccessToken>oauth.access_token</ExternalAccessToken>
    <ExternalAuthorization>true</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <SupportedGrantTypes>
        <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
    <GenerateResponse enabled="true">
        <Format>FORM_PARAM</Format>
    </GenerateResponse>
    <ReuseRefreshToken>false</ReuseRefreshToken>
    <StoreToken>true</StoreToken>
    <Tokens/>
</OAuthV2>

What I can't figure out is why this policy still generates this error:

{"ErrorCode":"invalid_client","Error":"Client identifier is required"}

In this case

response.header.client_id

is populated to a valid value (it shows up as being read in the trace), but it seems that policy isn't using the ClientId element to make the check that is associated with the error (I've tried with various other flow variables as well, none seem to work).

The only way I can get rid of the above error is to use this on the request flow and have the request be a x-www-form-urlencoded with a formparam named "client_id" (which has the same value that I have in "response.header.client_id now"). My understanding is that I can use the ClientId directive to override this default location, but so far I have been unsuccessful.

Any help is appreciated, Thanks!

Solved Solved
1 9 2,064
1 ACCEPTED SOLUTION

@GuyH,

As informed to you over email, you need to do the following.

  • Have the AssignMessage policy "SetFormParamClientID" in the request flow (and not in response flow) because you have the set the request.formparam.client_id
  • You need to set the Consumer key associated with the DeveloperApp (corresponding to the Product associated with your API Proxy) and not the username (email id) as the grant_type is set as "client_credentials" in OAuthv2.0 policy "StoreToken"
  • In addition, you also need to set the grant_type in the AssignMessage policy "SetFormParamClientID".

This should help you to resolve the problem.

Regards,

Amar

View solution in original post

9 REPLIES 9

It appears that you are right @rj.walsh. I am able to reproduce the behaviour. Apigee seems to be _only_ looking at request.formparam.client_id variable and nothing else.

As you probably already thought there is a terrible hack around this: use AssignMessage policy to set request.formparam.client_id to the value of response.header.client_id just before the OAuth policy in the response flow. This should enable you to use external authorization until this is fixed.

@AMAR DEVEGOWDA or @ozanseymen has this been fixed or do we still have to use the hack. The downside is doing that clears out the entire request body and sets it to the client_id

I don't think anything has changed!

You do not need to set the request body.

The assignmessage looks like this:

<AssignMessage name='AM-FixupClientId'>
  <AssignVariable>
  <Name>request.formparam.client_id</Name>
  <Ref>response.header.client_id</Name>
  </AssignVariable>
</AssignMessage>

You're just setting one context variable.

It looks like setting that context variable wipes out the request body. I've attached a picture from the trace.

7755-screen-shot-2018-11-28-at-82542-pm.png

@Dino-at-Google any updates?

guy_hagemans
Participant III

Thanks for sharing, I was/am also stuck on this for an hour or two.

How did you get this to work?

As described, I added a AssignMessage policy as follows:

	<AssignMessage async="false" continueOnError="false" enabled="true" name="SetFormParamClientID">
    <DisplayName>SetFormParamClientID</DisplayName>
    <Properties/>
    <Set>
        <FormParams>
            <FormParam name="client_id">{apigee.username}</FormParam>
        </FormParams>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="false" transport="http" type="request"/>
</AssignMessage>

But I still get the same error. I tried to both set the policies on the request and response flows, but that didn't matter.

@GuyH,

As informed to you over email, you need to do the following.

  • Have the AssignMessage policy "SetFormParamClientID" in the request flow (and not in response flow) because you have the set the request.formparam.client_id
  • You need to set the Consumer key associated with the DeveloperApp (corresponding to the Product associated with your API Proxy) and not the username (email id) as the grant_type is set as "client_credentials" in OAuthv2.0 policy "StoreToken"
  • In addition, you also need to set the grant_type in the AssignMessage policy "SetFormParamClientID".

This should help you to resolve the problem.

Regards,

Amar

@GuyH confirmed through email that it is working fine for him with the above suggestion.

Not applicable

@GuyH

replace "{apigee.username}" with the clientId comming in the request.