ApiKey from OAuth for use in Separate Proxy with Simple Verify API Key policy

We have the following scenario:

Proxy A: Using OAuth 2.0 policy for token generation, validation, refresh, etc.

Proxy A, before generating an OAuth 2.0 token, does a simple username/pw validation to another proxy, Proxy B.

Proxy B: has a Verify API Key policy.

We have set up our dev app so that the products for Proxy A and Proxy B are tied to it, hence they can use the same API Key. However...the key and secret come into Proxy A for use in OAuth 2.0 policy as a basic auth header:

Authorization: Basic <key>:<secret>

But Proxy B expects just the key in an http header, for use in VerifyApiKey policy:

ApiKey: <key>

We'd prefer not to write a JS policy to manually grab and parse the key portion out of the basic auth header. There's gotta be an easier way to do this since Apigee edge has numerous policies to deal with api keys.

One option was to try and use the Get OAuth v2 Info policy with the <ClientId> element, which sets client id and secret as variables, but I wasn't sure if that can only be used after an OAuth v2.0 token has been produced by OAuthV2 policy. We need to get our hands on the api key portion of the basic auth header for use in the Proxy B call before GetToken will have been executed.

Another option that looked promising is the ExtractVariables Policy, maybe with something like this:

<ExtractVariablesname='ExtractVariable-OauthToken'>
	<Source>request</Source>
	<Header name="Authorization">
		<PatternignoreCase="false">Basic {key}:{secret}</Pattern>
	</Header>
        <VariablePrefix>clientrequest</VariablePrefix>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</ExtractVariables>

Then, for our service callout from Proxy A --> Proxy B, we could set a header based on {clientreqeust.key}, if I'm understanding this correctly.

Thoughts? Better/Simpler ideas?

Thanks in advance!

0 4 405
4 REPLIES 4

aswinsegu
Participant IV

Hi @Patrick McMichael,

Try making use of Basic Authentication Policy's Decode operation and extract API Key as a variable which can be passed on to Proxy B for Verify API Key policy

<BasicAuthenticationname="DecodeBaseAuthHeaders">
	<DisplayName>Decode Basic Authentication Header</DisplayName>
	<Operation>Decode</Operation>
	<IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
	<User ref="request.header.username"/>
	<Password ref="request.header.password"/>
	<Source>request.header.Authorization</Source>
</BasicAuthentication>

So here the API Key gets assigned to variable "request.header.username", which could be used further for your purpose

Great idea...will try that - thx!

@Aswin Segu

Ok...so the good news is that I can set the variable with the decode operation, BUT by the time I go to use the variable in my

AssignMessage

policy that creates the request, the variable I used has gone out of scope.

Here's what I have:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BasicAuthentication async="false" continueOnError="false" enabled="true" name="Basic-Authentication-Decode-ApiKey">
    <DisplayName>Basic Authentication Decode ApiKey</DisplayName>
    <Operation>Decode</Operation>
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <User ref="request.basicauth.apikey"/>
    <Password ref="request.basicauth.secret"/>
    <Source>request.header.Authorization</Source>
</BasicAuthentication>

Then in my create request I do this:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="CreateRequest">
    <DisplayName>CreateRequest</DisplayName>
    <Properties/>
    <Set>
        <Headers>
            <Header name="Content-Type">application/x-www-form-urlencoded</Header>
            <Header name="ApiKey">{request.basicauth.apikey}</Header>
        </Headers>
        <QueryParams/>
        <Payload>username={request.formparam.username}&password={request.formparam.password}</Payload>
        <Path>/authenticate</Path>
    </Set>
    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="true" transport="http" type="request">auth_request</AssignTo>
</AssignMessage>

BUT while I see request.basicauth.apikey set from the BasicAuth decode op, by the time it's used to set the header, it has gone out of scope.

Hi @Patrick McMichael

Assuming all these flow variables are populated

Please pass the payload as FormParams instead of Payload

<FormParams>     
        <FormParam name="username">{request.formparam.username}</FormParam>	<FormParam name="password">{request.formparam.password}</FormParam>
</FormParams>