OAuth with SAP API Management (HCP) – Part 1
When considering the implementation of an API Management project, there are many ways to do Authorization. In a digital world, OAuth (especially in version 2.0) has widely used mechanism for cross-domain authorization. If you are serious in implementing an API-driven infrastructure to deliver Apps to customers, there will be no way around OAuth.
Let’s take a step back.
What is OAuth? A specification.
What does it do? It specifies how to “enable a third-party
application to obtain limited access to an HTTP service, either on
behalf of a resource owner by orchestrating an approval interaction
between the resource owner and the HTTP service, or by allowing the
third-party application to obtain access on its own behalf.” (taken from the specs).
The IETF Document is quite readable, and is worth bookmarking to understand all of the spec’s details.
For an overview about OAuth, there are plenty of websites out there. An good overview is available on DigitalOcean, where the concepts and the flows are well explained.
In this blog entry, we’ll cover a basic scenario of OAuth: the “Client Credential” flow (or “two-legged” flow because only 2 parties are involved). This flow is used when the application is also the resource owner, so there is no user involved in this grant type flow.
First of all, I will assume you are acquainted with SAP API Management from our public cloud (HCP), and generally acquainted with web technologies. Also, we’ll use POSTMAN to do all the testing.
If not, please consider going through a good tutorial first of all.
The main idea behind this tutorial is to implement a “client credential” flow using the SAP API Management components.
The diagram below depicts the various steps to get there.
1- we will create an API Proxy that will be our “token endpoint” (using the OAuth policy). This API will generate the access token for instance, but could also revoke or refresh tokens.
2- we’ll create a dummy API proxy, to be the protected resource (using the OAuth policy).
3-we’ll add the dummy API proxy to an API Product
4- we’ll create an application and add the API Product created in step 3. This application has an application key and an application secret, corresponding to the client_id and client_secret required by OAuth to generate the token.
5- we’ll now use our token endpoint to get an access token, using the credentials of the application
6- finally, we’ll use the access token to get access to the protected resource, the dummy API proxy.
Remember that SAP API Management is a framework with a lot of predefined stuff, so we can implement virtually any behavior, or flow.
1- Create the Token Endpoint
First of all let’s create the token endpoint in order to generate the access token.
Create a new proxy, and call it “OAuthService“.
Because the endpoint of this proxy will be the OAuth policy, simply set the target endpoint to be any URL (http://none.com for instance).
Add a “Resource” that we’ll call “GenerateToken” for instance. This is the path we’ll call when we want to generate a token. Note that is has to be a “POST” because we will be sending the credentials as x-www-form-urlencoded body to the endpoint.
Now open the policy editor and add an “OAuthV2” policy in the “GenerateToken” flow.
The OAuthV2 policy is a multi-purpose policy: depending on how you configure it, it can generate, invalidate, verify, refresh, etc. OAuth tokens. For more information, have a look at the help.
In our case, we will configure it, so that it will return an “access_token”, ie. generate a token when requested.
The configuration of the OAuthV2 policy is available below:
<OAuthV2 async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt"> <Operation>GenerateAccessToken</Operation> <GenerateResponse/> <SupportedGrantTypes> <GrantType>client_credentials</GrantType> </SupportedGrantTypes> </OAuthV2>
Your token endpoint proxy should look like this:
Note that the execution of the proxy above will be stopped after the OAuth policy is triggered, not reaching the dummy host we have defined in the first place (normal behavior of the “GenerateResponse” configuration tag in the OAuthV2 policy).
Also note that the order of the configuration XML elements is important. The OAuthV2 policy XML configuration should have the elements configured in the following order:
2- Create a dummy API proxy
Our next step is to create the resource that will be protected by an OAuthv2 policy, ie. the requester will need to provide an access token.
For this exercise, we will not proxy an actual API, but stop the execution in the API Management layer. To do so, we’ll define a specific “route rule” that will not point to a target. The response will be generated from with the API proxy with an “assignMessage” policy.
First of all, create an new API proxy. name it “OAuthTestProxy” for instance.
Once the proxy is created, switch to Edit mode and generate 2 resources: Test1 (only “GET”) and Test2 (only “POST”). We will use these resources later.
Also in Edit mode, delete the default route, and create your own one, which target endpoint shall be “NONE”.
Eventually, your proxy should look like this:
Now we will add a response for the resources we have created. This is done by using an “AssignMessage” policy, which can assign values to request or response elements such as headers, parameters, body, ….
Go to the Policy Editor, and add an “AssignMessage” policy in the Outgoing flow of your “Test1” resource.
To do so:
– click on the “Edit” button in your policy editor
– click on the “Test1” resource on the left side og your screen
– click on the “+” button next to the “AssignMessage” policy on the right.
Name the policy “SetResponse” and select “Outgoing Response” as stream.
Click on “Add”.
Now configure the policy to return a message to the caller:
<AssignMessage async="false" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'> <!-- Sets the converted json to the response --> <Set> <Payload contentType="application/json">Test1 - GET Response</Payload> </Set> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> <AssignTo createNew="false" type="response">response</AssignTo> </AssignMessage>
Do the same for the “Test2” resource, and use another response:
<AssignMessage async="false" continueOnError="false" enabled="true" xmlns='http://www.sap.com/apimgmt'> <!-- Sets the converted json to the response --> <Set> <Payload contentType="application/json">Test2 - POST Response</Payload> </Set> <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables> <AssignTo createNew="false" type="response">response</AssignTo> </AssignMessage>
Test your policy by using postman.
Your URL should be composed as follows:
HCP API Management URL, followed by the URL of your proxy, followed by your resource name:
“http://myHCPTrial” + “/v1/OauthTest” + “/Test1”
Remember to use “GET” or “POST” methods for your 2 resources.
Add OAuth token verification policy
We will now add the OAuth access token verification policy to our API Proxy.
This policy is not tied to any resource, and shall always be executed at the very beginning of the request. hence we’ll place it in the “pre-flow” section.
To do so:
– click on the “Edit” button in your policy editor
– click on the “PreFlow” resource on the left side of your screen
– click on the “+” button next to the “OAuthV2” policy on the right
– name the policy “VerifyAccessToken” and set it toe the “Incoming Request” stream
– click on add.
Now configure your policy to check the OAuth token:
<OAuthV2 async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt"> <!-- this flag has to be set when you want to work with third-party access tokens --> <ExternalAuthorization>false</ExternalAuthorization> <!-- valid values are GenerateAccessToken, GenerateAccessTokenImplicitGrant, GenerateAuthorizationCode , RefreshAccessToken , VerifyAccessToken , InvalidateToken , ValidateToken --> <Operation>VerifyAccessToken</Operation> <GenerateResponse enabled="true"/><SupportedGrantTypes/> <Tokens/> </OAuthV2>
As you can see, we are using the same policy as for the OAuthService (OAuthV2 policy), but with an “Operation” of type “VerifyAccessToken”.
Click on “Update” and on “Save” to save and deploy your proxy.
We now have all proxies in place. In Part 2, we will add the dummy proxy (resource) to an API Product and an API Application, and get an access token with the Applications ID and secret.