DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How To Build Web Service Using Spring Boot 2.x
  • Building REST API Backend Easily With Ballerina Language
  • 7 Microservices Best Practices for Developers
  • The Principles of Planning and Implementing Microservices

Trending

  • Memory Leak Due to Time-Taking finalize() Method
  • The Ultimate Guide to Code Formatting: Prettier vs ESLint vs Biome
  • Navigating Double and Triple Extortion Tactics
  • Simplifying Multi-LLM Integration With KubeMQ
  1. DZone
  2. Data Engineering
  3. Databases
  4. Multi-tenancy authentication through Kong API Gateway

Multi-tenancy authentication through Kong API Gateway

By 
Cezar Romaniuc user avatar
Cezar Romaniuc
·
Jan. 13, 20 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
15.6K Views

Join the DZone community and get the full member experience.

Join For Free

The API Gateway pattern implements a service that’s the entry point into the microservices based application, from external API clients or consumers.
It is responsible for request routing, API composition, and other edge functions such as authentication.

When working with a microservices architecture, either on a greenfield project or during migration from monolith, a best practice is to start addressing cross-cutting concerns. Authentication is such a concern and in this article we’ll cover the Authentication of a multi-tenancy application.

There are numerous technologies we can use to implement an API Gateway pattern, including off-the-shelf API Gateway products like Kong.


When it receives a request, Kong searches within a routing map that specifies which upstream service to route the request to. This function is identical to the reverse proxy feature provided by web servers such as NGINX. Kong is based on the NGINX HTTP server, and let us configure flexible routing rules that use the HTTP method, headers and path to select the backend/upstream service and it also provides a bundle of plugins that implement edge functions such as authentication: acl and key auth.


Let’t consider the following prerequisites and steps to implement api key based authentication:

  • myService - a microservice that should be private and exposes an endpoint http://myServicePrivateHost:80/api/v1/myServicePath
  • two tenants tenant1.mydomain.com and tenant2.mydomain.com for which we want to authenticate the requests
  • Kong running on http://localhost:8000 for proxying and http://localhost:8001 for Admin API


1. Create a service object, a representation of the upstream microservice

Request:

Shell




x


 
1
curl -X POST \
2
  http://localhost:8001/services \
3
  -H 'Content-Type: application/json' \
4
  -d '{
5
    "host": "myServicePrivateHost",
6
    "name": "myService"
7
}'


 Response:

Shell




x


 
1
{
2
    "host": "myServicePrivateHost",
3
    "created_at": 1577460734,
4
    "connect_timeout": 60000,
5
    "id": "110a66e0-ab86-495d-9fc7-1ade0eea6f41",
6
    "protocol": "http",
7
    "name": "myService",
8
    "read_timeout": 60000,
9
    "port": 80,
10
    "path": null,
11
    "updated_at": 1577460734,
12
    "retries": 5,
13
    "write_timeout": 60000,
14
    "tags": null,
15
    "client_certificate": null
16
}



2. Create a route object for each tenant

  • service id - is extracted from step 1 response
  • hosts - field containing the actual domain, tenant specific
  • route name - must be unique and in this case it is prefixed with the tenant name

Request:

Shell




x


 
1
curl -X POST \
2
  http://localhost:8001/routes \
3
  -H 'Content-Type: application/json' \
4
  -d '{
5
    "protocols": [
6
        "http",
7
        "https"
8
    ],
9
    "service": {
10
        "id": "110a66e0-ab86-495d-9fc7-1ade0eea6f41"
11
    },
12
    "name": "tenant1.routeForMyService",
13
    "preserve_host": false,
14
    "regex_priority": 0,
15
    "strip_path": false,
16
    "paths": [
17
        "/api/v1/myServicePath"
18
    ],
19
    "hosts": [
20
        "tenant1.mydomain.com"
21
    ],
22
    "methods": [
23
        "GET"
24
    ]
25
}'


Note: Perform the same request from the current step and replace tenant1 with tenant2 for the purpose of creating the route for the other tenant.


When a request comes in, Kong will make use of the host header, path and HTTP method in order to select the route. If no route will be found the response will be:

Shell




xxxxxxxxxx
1


 
1
{
2
    "message": "no Route matched with those values"
3
}


At this point we have two unauthenticated routes and we'll create a consumer for each of them. Those consumers can be client applications or users and they can have multiple api keys.


3. Create consumer object for each tenant

Request:

Shell




xxxxxxxxxx
1


 
1
curl --request POST \
2
  --url http://localhost:8001/consumers \
3
  --header 'Content-Type: application/json' \
4
  --data '{"username":"someConsumerForTenant1"}'


Note: Perform the same request from the current step and replace tenant1 with tenant2 for the purpose of creating the consumer for the other tenant.


Now we should group the consumers for a specific tenant (there are also cases where we want to group by a tenant's application as well) and the specified group name will be whitelisted for consuming the api.


4. Create a group for each consumer 

Request:

Shell




xxxxxxxxxx
1


 
1
curl --request POST \
2
  --url http://localhost:8001/consumers/someConsumerForTenant1/acls \
3
  --header 'Content-Type: application/json' \
4
  --data '{"group":"tenant1Group"}'


Note: Perform the same request from the current step and replace tenant1 with tenant2 for the purpose of creating the group for the other tenant.


5. Applying key-auth plugin for the tenant specific route

Request:

Shell




xxxxxxxxxx
1


 
1
curl --request POST \
2
  --url http://localhost:8001/routes/tenant1.routeForMyService/plugins \
3
  --header 'Content-Type: application/json' \
4
  --data '{"name":"key-auth"}'


Note: Perform the same request from the current step and replace tenant1 with tenant2 for the purpose of applying the plugin for the other tenant route.


6. Applying acl plugin for the tenant specific route

Request:

Shell




x


 
1
curl --request POST \
2
  --url http://localhost:8001/routes/tenant1.routeForMyService/plugins \
3
  --header 'Content-Type: application/json' \
4
  --data '{"name":"acl", "config":{"whitelist":["tenant1Group"]}}'


Note: Perform the same request from the current step and replace tenant1 with tenant2 for the purpose of applying the plugin for the other tenant route. 


7. Generate an api key for tenant1:

Request:

Shell




x


 
1
curl --request POST \
2
  --url http://localhost:8001/consumers/someConsumerForTenant1/key-auth \
3
  --header 'Content-Type: application/json' \
4
  --data '{}'


Response:

Shell




xxxxxxxxxx
1


 
1
{
2
    "key": "6DlgBFKA2a0uD9CHVgqQvsZfWsePC0zu",
3
    "created_at": 1577462044,
4
    "consumer": {
5
        "id": "47dd2c7b-8094-4a9f-96f0-15120ddb8a79"
6
    },
7
    "id": "40c69ad1-37f8-4551-ab66-eb3609e78f26"
8
}



8. Access /api/v1/myServicePath for tenant1 without an apikey header:

Request:

Shell




x


 
1
curl --request GET \
2
  --url http://localhost:8000/api/v1/myServicePath \
3
  --header 'host: tenant1.mydomain.com'


Response:

Shell




xxxxxxxxxx
1


 
1
{
2
    "message": "No API key found in request"
3
}



9. Access /api/v1/myServicePath for tenant1 with the corresponding api key generated in step 7:

Request:

Shell




x


 
1
curl --request GET \
2
  --url http://localhost:8000/api/v1/myServicePath \
3
  --header 'apikey: 6DlgBFKA2a0uD9CHVgqQvsZfWsePC0zu' \
4
  --header 'host: tenant1.mydomain.com'


Response:

Shell




xxxxxxxxxx
1


 
1
{
2
    "message": "name resolution failed"
3
}


Note: The response depends on the actual microservice deployed locally. If it's up and running it will return the proper response. In our case the service doesn't exist so it will return 503 service temporary unavailable and the above response.


10. Access /api/v1/myServicePath for tenant2 with the tenant1's api key:

 Response:

Shell




xxxxxxxxxx
1


 
1
{
2
    "message": "You cannot consume this service"
3
}



These steps can be further automated by creating a wrapper over Kong Admin API. It will be in fact a microservice other services (e.g an IAM  - Identity and access management - microservice responsible with authentication and authorization) will communicate with, as a means to generate consumers and api keys for those consumers.

In this way we can leverage Kong API Gateway for centralizing the authentication to our multi-tenancy application.

API authentication Requests shell microservice consumer Web Service application Database Best practice

Published at DZone with permission of Cezar Romaniuc. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Build Web Service Using Spring Boot 2.x
  • Building REST API Backend Easily With Ballerina Language
  • 7 Microservices Best Practices for Developers
  • The Principles of Planning and Implementing Microservices

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!