API First: From Zero to Hero (Part 3)

3Bit Technologies
7 min readFeb 29, 2020

--

In this third part of the article API First: From Zero to Hero (Part 1), we will integrate the security layer of the API, covering all the steps for building complete APIs using the API First strategy.

Securing the API with OpenID Connect (Authentication)

We now have end-to-end integration testing of our API, however, we also need to protect our API from unauthenticated access.

For this, we will use the OIDC framework (OpenID Connect v1.0), integrating the API Gateway (Kong) with the IAM solution (Keycloak).

To integrate Kong with Keycloak, we will need to install a community plugin from the image we already use (kong:latest). For that, we will need to create a customized Dockerfile that will install thejwt-keycloak plugin.

Below is the Dockerfile with the necessary steps to install the plugin:

We will now need to change the Makefile to:

  • Build the custom Kong image from the Dockerfile we created
  • Use our generated image of Kong instead of the official image

The updated Makefile:

Provisioning IAM

We need to provision the Keycloak (IAM) locally so that we can request access tokens from our client (newman) and validate them at the gateway (Kong).

Keycloak uses the concept of realms to group security settings logically, similar to Kubernetes workspaces.

To facilitate the tutorial, a realm ( realm-export.json) called test has already been created, which has a client called newman configured to use OIDC and with the secret 5b7aad6a-9efc-4d14-9fd4-641ed48754c5

Our Makefile will provision the Keycloak with a memory database (H2) and will automatically import this pre-existing realm.

We also added a waiting time after the Keycloak is started (20 seconds), to wait for it to be properly provisioned.

Here is an updated Makefile:

We have the following drawing of the current solution:

We can run the Makefile to verify that everything is set up correctly:

make -k run-integration-tests

Enable the plugin in the API

We now have the IAM configured and provisioned along with our test suite, gateway and mock.

However, we still need to configure our API at the gateway to make it secure. In Kong, this is done through plugins.

The swagger-to-kong component is also capable of configuring plugins via Kong Routes, which is exactly what we need.

For that, we will create the file json kong-route-config.json with the plugins that we want to enable by Route.

The Route name is obtained by sanitizing the API + info.title. + the paths.PATH.METHOD.operationId of the operation. Sanitization is the process of removing special characters, exchanging spaces for - and exchanging accented characters for their respective non-accented characters, all in lowercase.

The openapi section below would become the Route named swagger-petstore.listPets:

Using the regex features available in swagger-to-kong, we will have the following content for the file kong-route-config.json (which contains the plugins that will be enabled/configured by Route):

This configuration file tells the component swagger-to-kong to:

  1. Enable the Prometheus metrics plugin for all Routes (this setting is the default for swagger-to-kong and is defined via the kong-route-config-default.json file
  2. For Route swagger-petstore.showPetById, swagger-petstore.listPets and swagger-petstore.createPets (via the .* Regex) configure the security plugin (jwt-keycloak) already pointing to the IAM (keycloak) and also stating that the Access Token can be extracted from the HTTP Cookie oauthtoken (to facilitate integration with oidc-proxy)
  3. For Route swagger-petstore.listPets configure the additional CORS plugin.

This file must be kept under version control and so can have one config for each environment (according to the IAM and the settings of the other plugins) or it can be transformed through some templating process (e.g. mustache).

CORS plugin

The configuration of the CORS plugin demonstrated in the previous item, was extracted directly from the Konga interface.

With that, we can manually configure the plugins via UI and then export only the JSON that represents each plugin, to facilitate the use of the tool.

Necessary steps:

  1. In Konga, select the desired Service or Route and browse Plugins
  2. Click the Raw view icon (eye icon)
  3. Copy the generated JSON
  4. Remove unnecessary attributes and use JSON in the kong-route-config.json file

Export example:

JSON (raw) example:

JSON example (no attributes with null value, ids, parent Service/Route item and timestamps):

Configuring swagger-to-kong in the Makefile

We now need to change the Makefile to reflect the necessary changes, passing to swagger-to-kong the plugin’s configuration file:

If we run Makefile now, we will have to see the tests fail due to the fact that our API is protected with OIDC and the client (newman) is not configured to pass on valid credentials:

make -k run-integration-tests

Configuring authentication on the client

For our integration test to work again, we need to configure our collection in Postman so it:

  • Have the credentials (client_id and client_secret) as a Variable in the environment localhost
  • Invoke a Pre-request Script for all operations, which will talk to the IAM (Keycloak) to negotiate the credentials for an Access Token
  • Propagate the Access Token for all operations as Header Authorization: Bearer $TOKEN
  • Use an oauthtoken cookie for one of the operations instead of the Header to propagate the Access Token

In the postman, we will add the variables to the localhost environment by following the steps below:

  1. Click on Manage Environments
  2. In the Popup, select the environment localhost
  3. Add the variable client_id with the value newman
  4. Add the variable client_secret with the value 5b7aad6a-9efc-4d14–9fd4–641ed48754c5
  5. Add the tenant variable with the value http://keycloak:8083/auth/realms/test/protocol/openid-connect/token
  6. Click Update to make the changes effective
  7. Export the environment as done in the step Creating an environment and exporting

Creating the Pre-script in the collection

Now we will create a pre-script directly in the Collection Swagger Petstore, which will cause it to be executed before each execution.

Steps to create the Pre-script:

  1. In the Postman side navigation menu, right click on the collection Swagger Petstore and then click Edit
  2. In the popup, select the Pre-request Scripts tab
  3. Add the script below:

4. Click on update to make the changes effective

Configuring authentication on the collection

Now we will set up Bearer authentication directly in the Collection Swagger Petstore, which will make it used together with each run.

Steps to configure authentication:

  1. In the Postman side navigation menu, right click on the collection Swagger Petstore and then click Edit
  2. In the popup, select the Authorization tab
  3. In the Type combo, select Bearer Token
  4. In the Token field, enter the value {{token}}
  5. Click Update to make the changes effective

Configuring authentication on requests (Bearer)

As our openapi spec is not secure, by default Postman does not define the authentication configuration, leaving it as In Auth, we have to change this configuration in all requests:

  1. In the collection Swagger Petstore, in the folder pets select the requests (List all pets and Create a pet) and one by one navigate to the tab Authorization
  2. In the TYPE combo select the type Inherit auth from parent
  3. Click Save to make the changes

Configuring authentication on requests (cookie)

We will configure one of the requests so that it uses Cookie oauthtoken to authenticate instead of Header Authorization, for this:

  1. In the collection Swagger Petstore, in the folder pets select the request Info for a specific pet and navigate to the tab Authorization
  2. In the TYPE combo select the type No Auth
  3. Navigate to the Headers tab
  4. Add a Header with KEY oauthtoken and VALUE {{token}}
  5. Click Save to make the changes effective

Exporting the collection

Now we can export the collection again, according to the steps described in Exporting the collection

Finishing

Now if everything went correctly, when executing our Makefile we will have the desired result with the API authenticated in Keycloak and validated by Kong.

Success

We saw in this tutorial how:

  • Use Postman to import and execute definitions from an openapi spec
  • How to create automated tests (collection) from Postman and export them for execution via the command line
  • How to create API mocks with Prism
  • How to use the swagger-to-kong tool to import openapi definitions into Kong (automatically creating Service and Route)
  • How to use the swagger-to-kong tool to configure plugins in the generated routes
  • How to use newman to run the collection created in Postman
  • How to protect the API (authentication) with Keycloak, Kong + plugin jwt-keycloak and swagger-to-kong (plugins)
  • How to run integration tests with Kong + Postgres, Keycloak, Prism, swagger-to-kong and newman

Next steps

For the next steps, we will address the API authorization theme based on the Keycloak openapi x Realm roles spec, completing the API first cycle without a backend code implemented!

Want to know more? Don’t forget to visit us at https://www.3bit.com.br/3bit

--

--

3Bit Technologies
3Bit Technologies

Written by 3Bit Technologies

Cloud Specialists providing professional services with DevOps, BigData, Cloud Native Applications and Security. https://www.3bit.com.br/3bit

No responses yet