I'm really new to Apigee Edge, and I don't even fully grasp what people use it for. What I can say is that I am using it to set up URLs that are protected by various forms of authentication and can receive arbitrary requests from my app for testing purposes.
I have succeeded in setting up a simple No-Target api proxy, selecting the oauth2 option in the setup wizard for securing it, and following this tutorial carefully: https://docs.apigee.com/api-platform/tutorials/secure-calls-your-api-through-oauth-20-client-credent...
I also see that the setup wizard gives an option to secure an api proxy by requiring an api key, or to simply have no authentication. What I'm still lacking is being able to secure an api proxy with basic auth. It would be nice if there were an option for that right in the setup wizard and if there were a tutorial analogous to that of the oauth2 tutorial. Lacking that, I need to at least figure out a work-around.
Here is what I have been able to figure out so far. When I select an authentication option in the setup wizard for an api proxy, it results in what are called policies being applied to the proxy. These policies are a small set of functions Apigee Edge provides to us which then have configuration options. When I select to use a policy for my proxy, I see xml code which describes the configuration for that policy. Every policy has documentation which then tells me all the ways I can configure it.
I'm not sure how the oauth2 configured proxy makes sure the access token is actually valid, but I was able to figure out how the companion proxy for issuing tokens is able to make sure the client_id and client_secret are valid. I had to create a product, app, and developer that were linked together, and that developer on that app then had its own api key and secret. The proxy then looks up a developer by matching the provided client_id with the dev's stored api key, and then confirms that the provided client_secret matches the dev's stored secret.
I'm guessing my best option for setting up a username/password basic auth system will end up somehow using a dev's api key and secret as if they were a username and password.
Similar to the oauth2 policy's verification operation, I noticed that the Verify API Key policy makes sure the provided api key matches one of the devs on that app and proxy. I also saw that I can configure the policy to look for the api key in whatever part of the request I want. But this policy does not appear to have an option for verifying some provided secret matches the dev's secret. But I saw that I can at least look at the dev's secret from within this policy. Is there a way for this policy to check it against something in the request? Alternatively, is there a way I can add another policy to the chain that can verify these values match?
It looks like I also need to use the Basic Authentication policy, but not for actually authenticating. It looks like it's just for converting the Authorization header into a couple of values for later policies to easily read from. Correct?
Finally, I apologize that this is yet another question in the Community on this topic, but none of the ones I browsed fully answered the question for me. They were either not exactly what I was trying to do or they were written in a way that a newbie like me doesn't understand what's going on.
Solved! Go to Solution.
Hi @David Ripplinger, Basic authentication policy is simply a policy that can base64 encode or decode a string into its constituent variables. It actually doesn't verify anything like client_id or client_secret or anything like that.
We can make use of Basic Auth, Verify API Key & Raise Fault policy to validate incoming client_id & client_secret.
Steps 1 -
The client would pass the client_id and client_secret as a Base64 encoded in a header. In Basic Auth Policy we can sue a Decode Operation & get client_id in the "decoded.clientId" variable and client_secret in the "decoded.clientSecret" variable.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <BasicAuthentication async="false" continueOnError="false" enabled="true" name="Decoding-Authentication"> <DisplayName>Decoding-Authentication</DisplayName> <Operation>Decode</Operation> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> <User ref="decoded.clientId"/> <Password ref="decoded.clientSecret"/> <AssignTo createNew="false">request.header.Authorization</AssignTo> <Source>request.header.Authorization</Source> </BasicAuthentication>
Step 2 -
Now with Verify API Key policy, we can validate it with a client_id(which refers to the decoded.clientId from Basic Auth policy).
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <VerifyAPIKey async="false" continueOnError="false" enabled="true" name="Verify-Client-Key"> <DisplayName>Verify-Client-Key</DisplayName> <Properties/> <APIKey ref="decoded.clientId"/> </VerifyAPIKey>
If you start the Trace Session, then you will see that Verify API Key also populates the corresponding client_secret as a variable.
Step 3 -
Now after Verify API Key policy we can use a Raise Fault Policy with a Condition to check the client_secret from Trace Variables with decoded.clientSecret & raise a fault if it doesn't match.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <RaiseFault async="false" continueOnError="false" enabled="true" name="Invalid-Client-Secret"> <DisplayName>Invalid-Client-Secret</DisplayName> <Properties/> <FaultResponse> <Set> <Headers/> <Payload contentType="application/json"> \{"error": {"message":"Invalid Client Secret", "detail":"Provided Client Secret is not valid"}} </Payload> <StatusCode>401</StatusCode> <ReasonPhrase>Invalid Client Secret</ReasonPhrase> </Set> </FaultResponse> <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables> </RaiseFault>
In this way, we can validate both client_id & client_secret.
<Step> <Name>Decoding-Authentication</Name> </Step> <Step> <Name>Verify-Client-Key</Name> </Step> <Step> <Condition>verifyapikey.Verify-Client-Key.client_secret != decoded.clientSecret</Condition> <Name>Invalid-Client-Secret</Name> </Step>