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! Go to Solution.
As informed to you over email, you need to do the following.
This should help you to resolve the problem.
Regards,
Amar
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.
@Dino-at-Google any updates?
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.
As informed to you over email, you need to do the following.
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.
replace "{apigee.username}" with the clientId comming in the request.