How-to: Secure an API with Gravitee.io API Platform
In the previous post, we explained you how to bootstrap very quickly Gravitee.io Platform with both components API Management and Access Management.
Based on this stack, it’s now time to go further and look for an easy way to secure your API(s).
** For this post, we are assuming that docker-compose for Gravitee.io API Platform is up and running.
Prepare your API
To show you how to achieve API security, we will use the Echo API which can be accessible at https://api.gravitee.io/echo
First, check that the Echo API is ready to handle HTTP requests:
$ curl -X GET https://api.gravitee.io/echo{
"headers" : {
"Host" : "api.gravitee.io",
"User-Agent" : "curl/7.54.0",
"Accept" : "*/*",
"X-Forwarded-For" : "90.110.132.28",
"X-Forwarded-Host" : "api.gravitee.io",
"X-Forwarded-Port" : "443",
"X-Forwarded-Proto" : "https",
"X-Forwarded-Server" : "2190b6ef1a19",
"X-Real-Ip" : "90.110.132.28",
"Accept-Encoding" : "gzip"
},
"query_params" : { }
}
It’s now time to declare the API within Gravitee.io API Management.
From your browser, go to https://apim.gravitee.io/portal, log in as admin/admin, and go to Administration.
To go ahead, we have provided you with the Echo API definition you can download from GitHub. You can then import it into Gravitee.io:
The API is not started by default, so you have to click on the Start the API button to make available on the API Gateway.
For this API, two plans are provided by default:
- A free plan, without any security, which allows consumers for GET requests only.
- A secured plan, based on an OAuth2 authorization server, with no restriction
Let’s check defined restrictions for the free plan (you can see the X-Gravitee-Transaction-Id which indicates you that the request was handled by the API Gateway)
$ curl -k -X GET https://apim.gravitee.io/echo{
"headers" : {
"Host" : "api.gravitee.io",
"User-Agent" : "curl/7.54.0",
"Accept" : "*/*",
"Accept-Encoding" : "gzip",
"X-Forwarded-For" : "172.25.0.1, 90.110.132.28",
"X-Forwarded-Host" : "apim.gravitee.io",
"X-Forwarded-Port" : "443",
"X-Forwarded-Proto" : "https",
"X-Forwarded-Server" : "2190b6ef1a19",
"X-Gravitee-Transaction-Id" : "baed476c-1626-4834-ad47-6c16269834da",
"X-Real-Ip" : "172.25.0.1"
},
"query_params" : { }
}
What about POST requests?
$ curl -k -X POST https://apim.gravitee.io/echo{
"message" : "You're not allowed to access this resource",
"http_status_code" : 403
}
Ok, everything is working as expected for the pass-trough plan, but the API is still not secured and I want to make POST requests!
Create a Security Domain
For the OAuth2 plan, we need an authorization server, and you’re a lucky guy / gal, we have one for you: Gravitee.io Access Management.
You can access it from your browser at https://am.gravitee.io and log in as admin/adminadmin.
First of all, we have to create a security domain:
Then, create a client for the API Gateway (which acts as a resource server in the sense of OAuth specification):
Let’s try to generate an access token for this user:
$ curl k -X POST 'https://am.gravitee.io/auth/demo/oauth/token?grant_type=password&username=bobdylan@ilovemusic.com&password=ilovemusic' -H 'Authorization: Basic YXBpbS1nYXRld2F5OmYzOTMwOTlhLTA0NzgtNDI5ZC05MzA5LTlhMDQ3ODYyOWRkOA=='
The Authorization: Basic
header is corresponding to the base64 value of client_id and client_secret:
base64_encode(client_id:client_secret)
The expected response should be as follow:
{
“access_token” : “eyJraWQiOiJkZWZhdWx0LWdyYXZpdGVlLUFNLWtleSIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiJlMDA5NTNhOS1lOTRjLTQyZDktODk1My1hOWU5NGM1MmQ5YmMiLCJhdWQiOiJhcGltLWdhdGV3YXkiLCJkb21haW4iOiJkZW1vIiwiaXNzIjoiaHR0cDovL2dyYXZpdGVlLmFtIiwiZXhwIjoxNTQ5NDk2NDM2LCJpYXQiOjE1NDk0ODkyMzYsImp0aSI6IjE2YzMwN2I4LWVlMjktNDRiOS04MzA3LWI4ZWUyOTg0Yjk2YyJ9.CK2_vJuxyK9zxCqe7SDyprmnCMSaRk33Bt589zrprfE”,
“token_type” : “bearer”,
“expires_in” : 7199
}
Now that we have a token for our client, we can use it to make a call to the API Gateway:
$ curl -k -X POST https://apim.gravitee.io/echo -H 'Authorization: Bearer eyJraWQiOiJkZWZhdWx0LWdyYXZpdGVlLUFNLWtleSIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiJlMDA5NTNhOS1lOTRjLTQyZDktODk1My1hOWU5NGM1MmQ5YmMiLCJhdWQiOiJhcGltLWdhdGV3YXkiLCJkb21haW4iOiJkZW1vIiwiaXNzIjoiaHR0cDovL2dyYXZpdGVlLmFtIiwiZXhwIjoxNTQ5NDk2NDM2LCJpYXQiOjE1NDk0ODkyMzYsImp0aSI6IjE2YzMwN2I4LWVlMjktNDRiOS04MzA3LWI4ZWUyOTg0Yjk2YyJ9.CK2_vJuxyK9zxCqe7SDyprmnCMSaRk33Bt589zrprfE"{
"message" : "access_denied",
"http_status_code" : 401
}
Wait! I’m pretty sure about my access_token so what’s going wrong there?
Subscribe to the API
At this level, your access_token may be valid, but there is no subscription to the Echo API and its secured OAuth2 plan. The API consumer should ask for a subscription, that’s the reason why the access_token is not sufficient by itself.
From the API Gallery, choose the Echo API
and subscribe to the OAuth plan
:
$ curl -k -X POST https://apim.gravitee.io/echo -H 'Authorization: Bearer eyJraWQiOiJkZWZhdWx0LWdyYXZpdGVlLUFNLWtleSIsImFsZyI6IkhTMjU2In0.eyJzdWIiOiJlMDA5NTNhOS1lOTRjLTQyZDktODk1My1hOWU5NGM1MmQ5YmMiLCJhdWQiOiJhcGltLWdhdGV3YXkiLCJkb21haW4iOiJkZW1vIiwiaXNzIjoiaHR0cDovL2dyYXZpdGVlLmFtIiwiZXhwIjoxNTQ5NDk2NTUyLCJpYXQiOjE1NDk0ODkzNTIsImp0aSI6ImQ2YTBlYWRlLWQ4MjUtNDRjYi1hMGVhLWRlZDgyNWI0Y2JlYiJ9.d2R4KdC0UqkSI6WbCSvCLtPSKCk1JsV4t26pjFuEzUI' -d 'ping'> ping
Eureka! We are now able to send POST requests to the API gateway.
You can now have a quick look to the analytics for your API to check that there were some calls from an Unknown Application (because of the pass-trough plan), and some others from Default Application (thanks to the OAuth plan).
In this blog, there was a bit of magic and you may ask yourself how the API Gateway is able to validate an incoming HTTP request and its access_token.
This part was hidden by the initial import of the API definition to go faster. We would advice you to have a look to the OAuth plan configuration which is based on an OAuth2 resource (declare at the API level from the Design >Resources menu).
This post was a first step and was exposing you with a way to secure very quickly your API. You can do even more with Gravitee.io API Management by applying more restrictions based on OAuth scopes, quota and rate-limit by plan.
The best is still to play with Gravitee.io API Platform to enjoy all its features!