Skip to main content

Overview

These endpoints demonstrate KrakenD’s JWT validation and authorization capabilities using two different token providers: Keycloak and a custom JWT signer. Endpoints:
  • GET /private/moderate - Requires Keycloak JWT with moderator role
  • GET /private/custom - Requires custom JWT with specific roles

What It Demonstrates

  • JWT Validation: Verifies token signatures using JWK
  • Role-Based Access Control (RBAC): Enforces role requirements
  • Multiple Auth Providers: Supports different JWT issuers
  • Nested Claims: Handles complex JWT claim structures

GET /private/moderate

Description

A protected endpoint that requires a valid JWT token from Keycloak with the moderator role. HTTP Method: GET
Endpoint: /private/moderate
Cache TTL: 1 second

Authentication

Required: JWT token in Authorization header Format:
Authorization: Bearer <jwt_token>
Required Role: moderator (in realm_access.roles)

Request Example

curl -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..." \
  http://localhost:8080/private/moderate

Expected Response (Success)

Status: 200 OK
{
  "id": 1,
  "name": "John Doe",
  "email": "[email protected]",
  "role": "moderator",
  "status": "active"
}

Error Responses

Missing Token:
{
  "error": "missing authorization header"
}
Status: 401 Unauthorized Invalid Token:
{
  "error": "invalid token"
}
Status: 401 Unauthorized Insufficient Permissions:
{
  "error": "insufficient permissions"
}
Status: 403 Forbidden

Backend Service

  • Host: http://fake_api (inherited from global config)
  • URL Pattern: /user/1.json
  • Purpose: Returns user data after successful authentication

KrakenD Configuration

{
  "@comment": "Feature: Authorization based on JWT (using Keycloak)",
  "endpoint": "/private/moderate",
  "cache_ttl": "1s",
  "backend": [
    {
      "url_pattern": "/user/1.json"
    }
  ],
  "extra_config": {
    "auth/validator": {
      "alg": "RS256",
      "audience": ["playground"],
      "roles_key_is_nested": true,
      "roles_key": "realm_access.roles",
      "roles": ["moderator"],
      "jwk_url": "http://keycloak:8080/realms/krakend/protocol/openid-connect/certs",
      "disable_jwk_security": true
    }
  }
}

Key Configuration Options

Algorithm:
"alg": "RS256"
RSA signature with SHA-256. Keycloak uses RSA for signing JWTs. Audience Validation:
"audience": ["playground"]
Token must include "playground" in the aud claim. Nested Roles:
"roles_key_is_nested": true,
"roles_key": "realm_access.roles"
Keycloak stores roles in a nested structure:
{
  "realm_access": {
    "roles": ["moderator", "user"]
  }
}
Required Roles:
"roles": ["moderator"]
User must have the moderator role to access this endpoint. JWK URL:
"jwk_url": "http://keycloak:8080/realms/krakend/protocol/openid-connect/certs"
Fetches public keys from Keycloak to verify token signatures.

GET /private/custom

Description

A protected endpoint that requires a custom JWT token signed with HMAC-SHA256, containing specific roles. HTTP Method: GET
Endpoint: /private/custom

Authentication

Required: JWT token in Authorization header Format:
Authorization: Bearer <jwt_token>
Required Roles: role_a AND role_c (user must have both)

Request Example

curl -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  http://localhost:8080/private/custom

Expected Response (Success)

Status: 200 OK
{
  "id": 1,
  "name": "Jane Smith",
  "email": "[email protected]",
  "department": "Engineering"
}

Error Responses

Same as /private/moderate.

Backend Service

  • Host: http://fake_api (inherited from global config)
  • URL Pattern: /user/1.json
  • Purpose: Returns user data after successful authentication

KrakenD Configuration

{
  "@comment": "Feature: Authorization based on JWT (using KrakenD JOSE signer)",
  "endpoint": "/private/custom",
  "backend": [
    {
      "url_pattern": "/user/1.json"
    }
  ],
  "extra_config": {
    "auth/validator": {
      "alg": "HS256",
      "audience": ["http://api.example.com"],
      "roles_key": "roles",
      "issuer": "https://krakend.io",
      "roles": ["role_a", "role_c"],
      "jwk_url": "http://fake_api/jwk/symmetric.json",
      "disable_jwk_security": true
    }
  }
}

Key Configuration Options

Algorithm:
"alg": "HS256"
HMAC with SHA-256. Uses a symmetric key (same key for signing and verification). Issuer Validation:
"issuer": "https://krakend.io"
Token must be issued by https://krakend.io (checked via the iss claim). Audience Validation:
"audience": ["http://api.example.com"]
Token must be intended for http://api.example.com. Flat Roles Structure:
"roles_key": "roles"
Roles are stored at the top level of the JWT:
{
  "sub": "user123",
  "roles": ["role_a", "role_b", "role_c"]
}
Required Roles:
"roles": ["role_a", "role_c"]
User must have both role_a AND role_c to access this endpoint.

JWT Token Structure

Keycloak Token Example

{
  "exp": 1709485200,
  "iat": 1709481600,
  "iss": "http://keycloak:8080/realms/krakend",
  "aud": ["playground"],
  "sub": "user123",
  "realm_access": {
    "roles": ["moderator", "user"]
  },
  "email": "[email protected]"
}

Custom Token Example

{
  "exp": 1709485200,
  "iat": 1709481600,
  "iss": "https://krakend.io",
  "aud": ["http://api.example.com"],
  "sub": "user456",
  "roles": ["role_a", "role_b", "role_c"],
  "email": "[email protected]"
}

Obtaining Tokens

Get Keycloak Token

curl -X POST http://localhost:8080/realms/krakend/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=playground" \
  -d "username=moderator_user" \
  -d "password=password123"

Get Custom Token

Use the /token endpoint (see token.mdx):
curl -X POST http://localhost:8080/token

Comparison

Feature/private/moderate/private/custom
AlgorithmRS256 (Asymmetric)HS256 (Symmetric)
ProviderKeycloakKrakenD JOSE
Roles Keyrealm_access.rolesroles
IssuerKeycloak realmhttps://krakend.io
Audienceplaygroundhttp://api.example.com
Required Rolesmoderatorrole_a AND role_c

Use Cases

/private/moderate

  • Enterprise SSO with Keycloak
  • Multi-application authentication
  • OIDC-compliant systems
  • Complex role hierarchies

/private/custom

  • Internal microservices
  • Custom authentication systems
  • Lightweight JWT validation
  • API-to-API communication

Security Considerations

JWK Security

"disable_jwk_security": true
⚠️ Warning: Only use in development. In production:
  • Remove disable_jwk_security or set to false
  • Use HTTPS for JWK URLs
  • Implement JWK caching
  • Use proper certificate validation

Algorithm Selection

  • RS256 (Keycloak): More secure, public/private key pair, rotate keys easily
  • HS256 (Custom): Faster, but shared secret must be protected

Role Enforcement

Roles are validated with AND logic:
"roles": ["role_a", "role_c"]
User must have all listed roles.

Build docs developers (and LLMs) love