Verifying Amazon Alexa requests with SAP Cloud Platform – Cloud Foundry + API Management
In my previous blog posts on (1) Connecting an Echo Dot to SAP using SAP Cloud Platform + SAP ABAP 750 and (2) Visualizing Alexa’s response with SAPUI5, I’ve been able to utilize different platforms and tools that SAP has made available to connect my Amazon Echo Dot and make simple requests to an on-premise backend SAP ABAP server as well as updating a SAPUI5 application display together with returning the verbal response.
However, I explicitly didn’t mention anything about securing/protecting the API endpoints nor go over any details on verification/validation of the user identity. So, let’s talk about securing the API endpoints in this post.
Here’s the problem on the existing API…
I put my current API endpoint to the test by triggering a request from a third-party API tool with a valid JSON body (just like how Alexa would form it) and it actually reached my backend SAP server and it returned a valid response. THIS IS NOT A GOOD THING.
This means that anyone who knows the full URL to my API endpoint will be able to send or potentially flood requests freely from any API/REST tools to my backend SAP server.
I need to find a way to protect my API endpoint ASAP!
Although it’s really not that important since this entire demo is merely a PoC running on an developer trial ABAP server but I was looking for an excuse to try out the new released Cloud Foundry trial and also get more hands-on experience with SAP Cloud Platform, so I’m making this requirement up!
My solution to the problem above is to (1) Add a new policy to my API endpoint to validate an application key and (2) utilize a Cloud Foundry app to perform the verification that the request is indeed being sent from Alexa and trigger the API endpoint with the application key in the header of the request to identify itself
Here’s how the solution would look like.
Securing the API endpoint
The first part of the solution is to add some form of authentication to the API endpoint. I opted to add a policy to verify a static application key that will be sent in the header of the request in which only an authorized application would know and validated during the PreFlow to the ProxyEndpoint.
To do this, I have to perform these three simple steps in SAP Cloud Platform – API Management:
1. Create a Product on the API Portal and link it to the API endpoint
2. Consume the Product by creating an Application on the Developer Portal which then will generate an application key
3. Return to the API Portal and add a new Policy to the API Preflow – ProxyEndpoint called Verify API Key
Once these three steps above are completed and if I try to trigger the same API endpoint again using my third party API tool – I will now get an error like below.
But, if I were to set the ‘APIKey’ in the Header of the request and trigger the API endpoint again, it will now be successful.
Perfect! I have now added a simple api key verification to my API endpoint.
But wait, this change also completely broke my existing solution as Alexa can no longer make calls to this API since it is unable to pass the new HTTP header ‘APIKey’ during its call.
This brings us to the second part of the solution.
Are you Alexa?
Reading through the Amazon Alexa’s developer documentation on hosting a custom skills as a web service, there are a few security recommendations particularly around verifying that the request is indeed being sent by Alexa as a way to protect the API endpoint from potential attackers.Ref: https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service#verifying-that-the-request-was-sent-by-alexa
Since my personal objective of this hands-on is to try out the new Cloud Foundry, I looked to deploying a simple node.js application to Cloud Foundry that will act as a new API to (1) verify that the request is coming from Alexa and (2) identify itself to the API endpoint published in API Management with the header ‘APIKey’.
Before I even think about attempting to manually code those requirements from Amazon (which is impossible given my skillset), a quick search on “alexa verifier” on npmjs returned a few promising results. This is perfect! Someone out there has already thought about this and is kind enough to package this in an easy to use npm module.
This application would first call alexa-verifier-middleware to verify that the call is indeed coming from Alexa and then uses express-http-proxy to hardcode the header APIKey and forward the request to the API endpoint that’s published on API Management.
Here are the overview of steps that I took to get a node.js+express.js application pushed to SAP Cloud Foundry.
1. Activate the Cloud Foundry Trial on my SAP Cloud Platform trial account.
2. Install the CLI for Cloud Foundry on my computer
3. Set the Cloud Foundry API endpoint
4. Login to SAP Cloud Foundry
5. Push my application to Cloud Foundry
With the app running on Cloud Foundry, I can now run another test through my third-party API tool and sending a request directly to the Cloud Foundry application. This will be a negative test.
Awesome! The deployed application on Cloud Foundry now verifies that my request sent from the third-party API tool is not a valid request as I am missing parameters that would normally be on an actual Alexa request.
Let’s update this new API endpoint URL into the Amazon Skills Kit (ASK).
I now have an updated API endpoint for Alexa which is an application deployed on Cloud Foundry that verifies and identify itself with a basic API key verification on the API management.
I find that there is much to learn on SAP Cloud Platform especially on all the other features and tools that SAP is releasing which I’ve not even begun to explore. The addition of Cloud Foundry in the Cloud Platform is certainly interesting as we can now deploy small web applications very quickly to satisfy a requirement and not worry about all the other mundane tasks of managing a server, etc.
Part three: Verifying Amazon Alexa requests with SAP Cloud Platform – Cloud Foundry + API Management (This post)