Kong Authentication System
Introduction
Authentication is a critical aspect of API security. It verifies the identity of clients attempting to access your services and ensures that only authorized users can interact with your APIs. Kong Gateway, a popular open-source API gateway, provides robust authentication mechanisms to protect your services.
In this tutorial, you'll learn how Kong's authentication system works and how to implement various authentication methods to secure your APIs. By the end of this guide, you'll be able to configure authentication for your microservices architecture using Kong.
What is Kong?
Kong is an open-source API gateway that sits in front of your APIs and microservices, handling cross-cutting concerns like:
- Traffic control
- Monitoring
- Authentication
- Rate limiting
- Transformations
As an API gateway, Kong acts as a reverse proxy, routing client requests to appropriate backend services while applying policies like authentication.
Understanding Kong's Authentication Architecture
Kong's authentication system is plugin-based, giving you flexibility to choose the authentication method that best suits your needs.
Here's how Kong's authentication flow works:
When a request reaches Kong:
- Kong identifies which service/route the request is targeting
- It applies any configured authentication plugins
- If authentication passes, the request proceeds to the backend service
- If authentication fails, Kong returns a 401 Unauthorized response
Kong Authentication Plugins
Kong offers several authentication plugins. Let's explore the most commonly used ones:
1. Basic Authentication
Basic Authentication is the simplest form, using username and password credentials sent in the Authorization header.
Configuration
To enable Basic Authentication:
# Create a service
$ curl -i -X POST http://localhost:8001/services/ \
--data "name=example-service" \
--data "url=http://mockbin.org"
# Create a route
$ curl -i -X POST http://localhost:8001/services/example-service/routes \
--data "paths[]=/api"
# Enable basic-auth plugin
$ curl -i -X POST http://localhost:8001/services/example-service/plugins/ \
--data "name=basic-auth" \
--data "config.hide_credentials=true"
Creating Consumers and Credentials
# Create a consumer
$ curl -i -X POST http://localhost:8001/consumers/ \
--data "username=john"
# Create credentials for the consumer
$ curl -i -X POST http://localhost:8001/consumers/john/basic-auth \
--data "username=john" \
--data "password=secret"
Making Authenticated Requests
# This will fail with 401
$ curl -i http://localhost:8000/api
# This will succeed
$ curl -i http://localhost:8000/api \
-H "Authorization: Basic $(echo -n 'john:secret' | base64)"
2. Key Authentication
Key Authentication (also called API key authentication) uses a key that is unique to each consumer.
Configuration
# Enable key-auth plugin
$ curl -i -X POST http://localhost:8001/services/example-service/plugins/ \
--data "name=key-auth" \
--data "config.key_names=apikey"
Creating Consumers and Keys
# Create a consumer
$ curl -i -X POST http://localhost:8001/consumers/ \
--data "username=app1"
# Create an API key for the consumer
$ curl -i -X POST http://localhost:8001/consumers/app1/key-auth \
--data "key=your-secret-api-key"
Making Authenticated Requests
# Using query parameter
$ curl -i http://localhost:8000/api?apikey=your-secret-api-key
# Using header
$ curl -i http://localhost:8000/api \
-H "apikey: your-secret-api-key"
3. JWT Authentication
JSON Web Tokens (JWT) provide a more secure authentication method, especially for single-page applications and microservices.
Configuration
# Enable jwt plugin
$ curl -i -X POST http://localhost:8001/services/example-service/plugins/ \
--data "name=jwt"
Creating Consumers and Credentials
# Create a consumer
$ curl -i -X POST http://localhost:8001/consumers/ \
--data "username=mobile-app"
# Create JWT credentials
$ curl -i -X POST http://localhost:8001/consumers/mobile-app/jwt \
--data "algorithm=HS256" \
--data "key=mobile-app-key"
The response will include a secret
that you'll use to sign your JWTs.
Making Authenticated Requests
First, generate a JWT using the key and secret. Many libraries are available for this. Here's a simplified example:
// Node.js example using jsonwebtoken library
const jwt = require('jsonwebtoken');
const payload = {
iss: 'mobile-app-key' // The "key" field from your JWT credentials
};
const token = jwt.sign(payload, 'your-jwt-secret', { algorithm: 'HS256' });
console.log(token); // Use this token in your API request
Then use the token in your request:
$ curl -i http://localhost:8000/api \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
4. OAuth 2.0 Authentication
For more complex scenarios, Kong supports OAuth 2.0 authentication flow.
Configuration
# Enable oauth2 plugin
$ curl -i -X POST http://localhost:8001/services/example-service/plugins/ \
--data "name=oauth2" \
--data "config.enable_authorization_code=true" \
--data "config.scopes=email,profile" \
--data "config.mandatory_scope=true"
Setting up OAuth 2.0 is more complex and involves multiple steps:
- Creating a consumer
- Creating an application
- Implementing the authorization flow
- Managing access tokens
Due to its complexity, we'll explore OAuth 2.0 in a separate, dedicated tutorial.
Combining Authentication Methods
Kong allows you to combine multiple authentication plugins. For instance, you might want to:
- Use JWT for your mobile app
- Use API keys for your partner integrations
- Use Basic Auth for admin tools
To implement this, you can configure multiple authentication plugins on different routes:
# JWT for mobile app route
$ curl -i -X POST http://localhost:8001/services/example-service/routes \
--data "paths[]=/api/mobile" \
--data "name=mobile-route"
$ curl -i -X POST http://localhost:8001/routes/mobile-route/plugins/ \
--data "name=jwt"
# Key Auth for partner API routes
$ curl -i -X POST http://localhost:8001/services/example-service/routes \
--data "paths[]=/api/partners" \
--data "name=partner-route"
$ curl -i -X POST http://localhost:8001/routes/partner-route/plugins/ \
--data "name=key-auth"
Real-World Example: Securing a Microservices Architecture
Let's look at a practical example of securing multiple services in a microservices architecture:
Implementation Steps
- Set up your services in Kong:
# User service
$ curl -i -X POST http://localhost:8001/services/ \
--data "name=user-service" \
--data "url=http://user-service:3000"
$ curl -i -X POST http://localhost:8001/services/user-service/routes \
--data "paths[]=/api/users"
# Product service
$ curl -i -X POST http://localhost:8001/services/ \
--data "name=product-service" \
--data "url=http://product-service:3001"
$ curl -i -X POST http://localhost:8001/services/product-service/routes \
--data "paths[]=/api/products"
# Admin service
$ curl -i -X POST http://localhost:8001/services/ \
--data "name=admin-service" \
--data "url=http://admin-service:3002"
$ curl -i -X POST http://localhost:8001/services/admin-service/routes \
--data "paths[]=/api/admin"
- Apply authentication plugins to each service:
# JWT for user service
$ curl -i -X POST http://localhost:8001/services/user-service/plugins/ \
--data "name=jwt"
# Key Auth for product service
$ curl -i -X POST http://localhost:8001/services/product-service/plugins/ \
--data "name=key-auth"
# Basic Auth for admin service
$ curl -i -X POST http://localhost:8001/services/admin-service/plugins/ \
--data "name=basic-auth"
- Create consumers and credentials for each service
This follows the patterns we've already discussed for each authentication type.
Best Practices for Kong Authentication
- Use HTTPS - Always use HTTPS in production to protect credentials in transit
- Rotate credentials regularly - Implement a process to rotate API keys and secrets
- Apply rate limiting - Combine authentication with rate limiting to prevent brute force attacks
- Monitor failed authentication attempts - Set up logging and alerts for repeated authentication failures
- Use the principle of least privilege - Grant only the permissions necessary for each consumer
- Consider ACL plugins - After authentication, use Access Control Lists to further control access
- Implement JWT token expiration - For JWT authentication, set reasonable expiration times
- Don't expose consumer IDs - Use the
hide_credentials
option when available
Troubleshooting Authentication Issues
Common Issues and Solutions
-
401 Unauthorized errors:
- Verify the credentials are correct
- Check if the consumer exists
- Ensure the plugin is configured correctly
-
Credentials not being recognized:
- Verify the format of the Authorization header
- For JWT, check that the token is properly signed
- For API keys, ensure the key name matches the configuration
-
Plugin configuration issues:
- Use
curl -i -X GET http://localhost:8001/services/your-service/plugins
to check plugin status - Review Kong logs for detailed error information
- Use
Debugging Tips
Enable verbose logging in Kong by updating your Kong configuration:
# In kong.conf
log_level = debug
Then check the logs:
$ tail -f /usr/local/kong/logs/error.log
Summary
In this tutorial, you've learned:
- How Kong's authentication system works at a high level
- How to configure different authentication plugins (Basic Auth, Key Auth, JWT)
- How to create consumers and credentials
- How to make authenticated requests to your APIs
- How to implement authentication in a microservices architecture
- Best practices for API authentication with Kong
Kong's flexible authentication system allows you to implement the right security model for your specific needs, whether you're building a simple API or a complex microservices architecture.
Additional Resources
Exercises
- Set up Kong locally and configure Basic Authentication for a simple API
- Create a consumer and test authentication with curl
- Implement JWT authentication for a different route
- Try combining multiple authentication methods for a single service
- Implement a simple frontend that authenticates with your Kong-protected API
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)