How-to: Secure an API with Gravitee.io API Platform

David Brassely
graviteeio
Published in
5 min readFeb 6, 2019

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:

Import Echo API definition

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
Echo API: Available plans

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:

Create a Demo security domain

Then, create a client for the API Gateway (which acts as a resource server in the sense of OAuth specification):

Create a new oauth client
Configure the token to allow only the password grant flow
Associate the default identity provider to the client (users managed from the security domain)
Create a user for the default identity provider
When configuration is done, you can enable the domain to deploy it on the AM Gateway

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 APIand subscribe to the OAuth plan:

API Gallery
Subscribe to the oauth plan
You’re ready to call the Echo API using your access_token!
$ 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).

OAuth2 plan configuration
AM Resource configuration: be careful with the client secret which may be subject to changes according to your environment.

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!

--

--