Getting Started With Application Authentication Via Kong API Gateway
Kong is an open-source, customizable, Nginx-based and scalable API middleware (API Gateway).Kong can be configured in front of any RESTful API and let the developers concentrate more on implementing business logic without caring about functionalities like authentication mechanism, rate limiting, logging, internal communications between APIs, carrying out communication with public entities and other organizations. It’s like a security layer which sits in front of your application and enhances it’s performance.Kong provides full control over architecture and it’s currently used by many organizations including small and large ones.We can add many functionalities to Kong via plugins and it is easily customizable.
Once you integrate Kong within your architecture, you will have full control over Kong’s data.It’s built on Nginx and uses the robust database like Apache Cassandra and PostgreSQL.It also provides Admin interface to manage your APIs.You can make Kong scale as per your requirements in which stateless Kong servers talks to the single Cassandra or PostgreSQL database and act in the same manner.The client applications talks to Kong and then Kong acts as a reverse proxy and routes the requests to the applications on the basis of managed plugins in Kong.
Below is an illustration of integrating a RESTful API with Kong:
Requirements:
OS: ubuntu 14.04
kong version: 0.8.3
Single Node Cassandra Database version: 2.2.7
Note: Kong, by default, listens to API Requests on port 8000 and it’s RESTful admin interface runs on port 8001.
Step 1: Adding an API to Kong:
[js]curl -i -X POST \
–url http://localhost:8001/apis/ \
–data ‘name=app’ \
–data ‘upstream_url=http://xxxxxxxxxx.com/’ \
–data ‘request_host=xxxxxxxxxx.com’
[/js]
HTTP/1.1 201 Created
Date: Thu, 28 Jul 2016 03:33:39 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.8.3
{“upstream_url”:”http:\/\/xxxxxxxxxx.com\/”,”strip_request_path”:false,”id”:”f4cf8a4e-88fd-49f1-85d2-1dbaae256547″,”created_at”:1469676819000,”preserve_host”:false,”name”:”app”,”request_host”:”xxxxxxxxxx.com”}
Step 2: Accessing API via Kong:
[js]curl -i -X GET –url http://localhost:8000/heartbeat –header ‘Host: xxxxxxxxxx.com’ [/js]
HTTP/1.1 200 OK
Date: Thu, 28 Jul 2016 03:36:21 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx/1.4.6 (Ubuntu)
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Content-Type, x-requested-with, Content-Country , Content-Region, X-Auth-Token, Region, content-country, content-region, x-auth-token, region
X-Kong-Upstream-Latency: 9
X-Kong-Proxy-Latency: 0
Via: kong/0.8.3
{“CommitMessage”:”hooks dependency removed”,”CommitId”:”c003fe573436d3cee33c5753fd8ca7b12e08f1b8″,”mysql_status”:200,”status”:200,”home_hazelcast_status”:200,”CommitAuthor”:”yyyy “,”Version”:”qa-12.3.4″,”CommitMerge”:””,”CommitDate”:”Fri Jul 15 14:43:04 2016 +0530″}
Step 3: Enabling authentication plugin in Kong:
[js]curl -i -X POST \
–url http://localhost:8001/apis/app/plugins/ \
–data ‘name=key-auth’
[/js]
HTTP/1.1 201 Created
Date: Thu, 28 Jul 2016 03:37:58 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.8.3
{“api_id”:”f4cf8a4e-88fd-49f1-85d2-1dbaae256547″,”id”:”4e951c2e-3c24-4b23-95bb-13c96769ef6f”,”created_at”:1469677078000,”enabled”:true,”name”:”key-auth”,”config”:{“key_names”:[“apikey”],”hide_credentials”:false}}
Step 4: Accessing API via Kong after enabling key-auth plugin:
[js]curl -i -X GET \
–url http://localhost:8000/ \
–header ‘Host: xxxxxxxxxx.com’
[/js]
HTTP/1.1 401 Unauthorized
Date: Thu, 28 Jul 2016 03:39:11 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
WWW-Authenticate: Key realm=”kong”
Server: kong/0.8.3
{“message”:”No API Key found in headers, body or querystring”}
As a result, Kong is blocking all requests without the authentication. Now, we have to add an authorized consumer to Kong to access the application.
Step 5: Creating an authorized Consumer to access the API via Kong:
[js]
curl -i -X POST \
–url http://localhost:8001/consumers/ \
–data "username=myuser"
[/js]
HTTP/1.1 201 Created
Date: Thu, 28 Jul 2016 03:41:40 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.8.3
{“username”:”myuser”,”created_at”:1469677300000,”id”:”364ae246-2965-43f5-b424-68d6b1dfe681″}
Step 6: Creating an api-key for authorized Consumer:
[js]curl -i -X POST \
–url http://localhost:8001/consumers/myuser/key-auth/ \
–data ‘key=mykey’
[/js]
HTTP/1.1 201 Created
Date: Thu, 28 Jul 2016 03:42:52 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Access-Control-Allow-Origin: *
Server: kong/0.8.3
{“key”:”mykey”,”consumer_id”:”364ae246-2965-43f5-b424-68d6b1dfe681″,”created_at”:1469677372000,”id”:”5c682d7c-8a62-473b-92a4-1127eb3a2d09″}
Step 7: Validating the above set credentials for authorized Consumer:
[js]curl -i -X GET \
–url http://localhost:8000/heartbeat \
–header "Host: xxxxxxxxxx.com" \
–header "apikey: mykey"
[/js]
HTTP/1.1 200 OK
Date: Thu, 28 Jul 2016 03:45:07 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx/1.4.6 (Ubuntu)
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Content-Type, x-requested-with, Content-Country , Content-Region, X-Auth-Token, Region, content-country, content-region, x-auth-token, region
X-Kong-Upstream-Latency: 9
X-Kong-Proxy-Latency: 0
Via: kong/0.8.3
{“CommitMessage”:”hooks dependency removed”,”CommitId”:”c003fe573436d3cee33c5753fd8ca7b12e08f1b8″,”mysql_status”:200,”status”:200,”home_hazelcast_status”:200,”CommitAuthor”:”yyyy “,”Version”:”qa-12.3.4″,”CommitMerge”:””,”CommitDate”:”Fri Jul 15 14:43:04 2016 +0530″}
Step 8: Kong blocking requests for unauthorized Consumer:
[js]curl -i -X GET –url http://localhost:8000/heartbeat –header "Host: xxxxxxxxxx.com" –header "apikey: mykeynew"[/js]
HTTP/1.1 403 Forbidden
Date: Thu, 28 Jul 2016 03:51:14 GMT
Content-Type: application/json; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: kong/0.8.3
{“message”:”Invalid authentication credentials”}
In this way, we can do the API authentication via Kong keeping the backend application lightweight and focusing only on the product and Kong handling all the other services around the application.
In my next blog, I’ll be demonstrating some advanced use-cases with Kong API Gateway.
How would you restrict a specific named consumer, with an apikey, to call an API and that API only? so you can lock down the consumer-apikey-api and that key cannot be used to call other APIs within the Kong API gateway open source version.
Kong supports API Key authentication. You can create customer-specific API keys and configure KONG to validate those keys whenever your customer is hitting those APIs. The person who has the valid API key can only hit the API. Reference link :- https://docs.konghq.com/plugins/key-authentication/
Hi Tarun,
Thanks for this intro on Kong authentication. I am trying to find a solution to a problem that am currently facing. There is currently an API gateway that am designing and the client needs to access different Microservices on the other side of the gateway. But the problem is each Microservice comes with its own authentication(like Oauth2). But I want the client to be authorized only once by the gateway. Can Kong help me solve this? If so, is it possible for me to integrate Kong with my existing Nginx without much changes ?
Not sure if this is the answer to your query but the flow is that the moment you enable oauth2 on one of the APIs of kong, kong accepts the necessary parameters from the client and hits the API. If the response of that APIs is 200 OK, The token generated by Kong is stored in the Kong’s database and now KONG manages the lifetime of that token. Every request coming from the client is now validated against the KONG’s token and if that is valid, then only the request is allowed. But you still need to write custom APIs to pass that token in every request so that KONG can validate it.
Its well integrated with exisiting NGinx. You can move all your Nginx logic to Kong.
Hello,
Great blog article, thank you.
What is not clear to me is what level Kong goes to, to validate the identity of the downstream server.
For example, if my upstream is example.com.
What authentication checks are made on the server identity when the TLS session is established. Is it checking the full cert chain up to a root? Is it validating the server identity is indeed example.com.
Thanks for any insight you can offer.
Colin
It validates both, the server identity and certificates associated with it. The certs should match the identity.
Nice tutorial, right now i’m learning api gateway especially kong api my question is how to create registration form and use that data to accessing that api instead of we create user manually like you did? Many thanks..
API gateway is just an entrance for your all backend applications. It’s not capable of serving the response directly to the user instead it will fetch the response from the backend server and deliver the response. You can think of just a Nginx server with multiple capabilities which is actually proxying pass your request to the upstream server. You can’t write custom business logic in KONG. You can use Kong just as an entrance point where external users won’t be able to know what are the URLs of your backend applications. It is also providing you various security measures (oauth2, API-key authentication) and other services like CORS etc. In my blog, the user which I’ve created is not an external user. I’ve just enabled an auth-key authentication on my gateway that only entertain those request from the outer world if the external user has the allotted key which is respected by KONG. It won’t be confused with the login/password authentication of a web application.
Nice post, but i have a question, maybe is really simple to answer but i can’t figure it out.
If i remove authentication from my api, how can i block or do something in order to make sure that only kong server can consume my api?
Thanks. In that case, you can do multiple things:-
1) You can restrict your upstream server to only receive traffic through Kong’s IP. As your application API URLs will be pointing to Kong only, no one can figure out what is your upstream URLs and thus won’t be able to hit directly the upstream servers.
2) You should also make your upstream applications running in private subnet, so that no one can reach to them from outside world.
3) Moreover, you can handle the things on application’s web server(nginx/apache) level by checking the headers which KONG adds while forwarding the request to the upstream server. If the request header matches the Kong’s header, then only entertain the request otherwise its an unauthorized request.