Skip to content

psumaps/etis-auth-provider

Repository files navigation

ETIS Auth Provider

JWT authentication provider service for ETIS iCal token validation. Designed for deployment in Kubernetes clusters to provide authentication for web resources.

Features

  • Token Validation: Validates 16-character iCal tokens against upstream ETIS service (ical.psu.ru)
  • JWT Generation: Exchanges valid iCal tokens for JWT tokens with SHA256 token hash, issue time, and expiration
  • KrakenD Compatible: Full support for KrakenD CE JWT validation with JWK endpoint
  • Production Ready: Built-in rate limiting, caching, logging, and graceful shutdown
  • Kubernetes Native: Health probes, ConfigMaps, Secrets, and security best practices
  • JWK Endpoint: Provides JSON Web Key endpoint for symmetric key validation

Documentation

Quick Start

Local Development

# Build and run
make build
export JWT_SECRET=your-secret-key
./etis-auth-provider

# Or use Docker
docker build -t etis-auth-provider .
docker run -p 8080:8080 -e JWT_SECRET=your-secret-key etis-auth-provider

Docker Compose

docker-compose up

API Endpoints

POST /auth

Exchange iCal token for JWT token.

Request (JSON body):

{
  "token": "1234567890abcdef"
}

Or (Authorization header):

Authorization: Bearer 1234567890abcdef

Response:

{
  "jwt": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Error Response:

{
  "error": "Invalid token"
}

GET /jwk

JWK (JSON Web Key) endpoint for KrakenD integration.

Response:

{
  "keys": [
    {
      "kty": "oct",
      "alg": "HS256",
      "k": "base64url-encoded-secret",
      "kid": "auto-generated-key-id"
    }
  ]
}

GET /health

Health check endpoint (liveness probe).

Response:

{
  "status": "ok"
}

GET /ready

Readiness check endpoint.

Response:

{
  "status": "ok"
}

Configuration

All configuration is done via environment variables:

Variable Default Description
PORT 8080 Service port
UPSTREAM_URL https://ical.psu.ru/calendars/ iCal validation endpoint
JWT_SECRET change-me-in-production Secret key for JWT signing (required in production)
JWT_EXPIRATION 3600 JWT expiration time in seconds
CACHE_FRESHNESS 3600 Token cache TTL in seconds
TIMEOUT 10 Upstream request timeout in seconds
LOG_LEVEL info Logging level: error/info/debug
RATE_LIMIT_GLOBAL 100 Global requests per window
RATE_LIMIT_PER_IP 10 Per-IP requests per window
RATE_LIMIT_WINDOW 60 Rate limit window in seconds
CLEANUP_INTERVAL 300 Cleanup interval in seconds
TLS_SKIP_VERIFY false Skip TLS certificate verification (use only if upstream has self-signed cert)

Kubernetes Deployment

Prerequisites

  • Kubernetes cluster (1.19+)
  • kubectl configured
  • Docker image built and available to cluster

Deploy

  1. Create a custom JWT secret:
kubectl create secret generic etis-auth-provider-secret \
  --from-literal=JWT_SECRET=$(openssl rand -base64 32)
  1. Deploy the service:
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
  1. Optional: Deploy Ingress for external access:
# Edit k8s/ingress.yaml and change auth.example.com to your domain
kubectl apply -f k8s/ingress.yaml
  1. Optional: Apply NetworkPolicy for security:
kubectl apply -f k8s/networkpolicy.yaml

Verify Deployment

# Check pod status
kubectl get pods -l app=etis-auth-provider

# Check logs
kubectl logs -l app=etis-auth-provider

# Test health endpoint
kubectl port-forward svc/etis-auth-provider 8080:8080
curl http://localhost:8080/health

KrakenD Integration

This service is fully compatible with KrakenD CE JWT validation. The service provides a JWK (JSON Web Key) endpoint that KrakenD can use to validate JWT tokens.

Quick Setup

1. Configure KrakenD to use the JWK endpoint:

{
  "endpoint": "/protected",
  "extra_config": {
    "auth/validator": {
      "alg": "HS256",
      "jwk_url": "http://etis-auth-provider:8080/jwk",
      "cache": true,
      "cache_duration": 3600,
      "operation_debug": true,
      "disable_jwk_security": true
    }
  }
}

2. Authentication Flow:

1. Client → POST /auth (with iCal token) → Receive JWT token
2. Client → Request protected endpoint with JWT → KrakenD validates JWT → Backend service

Configuration Options

Basic Configuration (examples/krakend-config.json)

Minimal setup with authentication:

  • Login endpoint proxies to /auth
  • Protected endpoint validates JWT using JWK endpoint

Advanced Configuration (examples/krakend-advanced.json)

Production-ready setup with:

  • Rate limiting: IP-based rate limits on authentication
  • Claim propagation: Pass JWT claims as HTTP headers to backend
  • CORS support: Configurable cross-origin access
  • Health checks: Gateway health monitoring
  • Error handling: Detailed error responses

Key Features

JWK Endpoint (/jwk):

  • Returns symmetric key in JWK format
  • Automatically generates kid (key ID) from secret hash
  • Compatible with KrakenD's JWT validator
  • Cacheable (recommended TTL: 3600 seconds)

JWT Token Format:

{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "auto-generated-key-id"
}
{
  "sub": "token-hash",
  "iat": 1234567890,
  "exp": 1234571490
}

Claim Propagation: KrakenD can forward JWT claims as HTTP headers to your backend:

"propagate_claims": [
  ["sub", "X-User-Token-Hash"],
  ["iat", "X-Token-Issued-At"],
  ["exp", "X-Token-Expires-At"]
]

Kubernetes Deployment

For internal cluster communication:

http://etis-auth-provider:8080/auth  (authentication)
http://etis-auth-provider:8080/jwk   (JWK endpoint for validation)

Important Notes

  1. disable_jwk_security: true is required for symmetric keys (HS256)
  2. Same secret must be used in both services (use Kubernetes Secrets)
  3. Cache JWK endpoint in KrakenD to reduce load
  4. operation_debug: true helps troubleshoot JWT validation issues

Testing

# Get JWT token
TOKEN=$(curl -X POST http://localhost:8080/auth \
  -H "Content-Type: application/json" \
  -d '{"token":"your-ical-token"}' | jq -r '.jwt')

# Use token with KrakenD protected endpoint
curl http://localhost:8000/api/protected \
  -H "Authorization: Bearer $TOKEN"

# Check JWK endpoint
curl http://localhost:8080/jwk

See examples/ directory for complete KrakenD configuration examples.

TLS Certificate Issues

If you encounter certificate verification errors like:

x509: certificate signed by unknown authority

This happens when the upstream server's certificate chain is incomplete or uses a CA not in your system's trust store.

Solution:

Set TLS_SKIP_VERIFY=true environment variable:

docker run -e TLS_SKIP_VERIFY=true ...

Or in Kubernetes:

env:
  - name: TLS_SKIP_VERIFY
    value: "true"

⚠️ Security Note: Only use TLS_SKIP_VERIFY=true if you trust the upstream server (e.g., internal network). For production with external upstreams, consider adding the CA certificate to your system's trust store instead.

Architecture

  • Stateless: In-memory cache only, no persistent state (horizontally scalable)
  • 12-Factor App: Configuration via environment variables, logs to stdout
  • Security: Non-root container, read-only filesystem, minimal capabilities
  • Observability: Structured logging with configurable levels

Development

# Format code
make fmt

# Run linters
make vet

# Build
make build

# Clean
make clean

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors