Configure authentication and authorization with SecurityPolicy — JWT, OIDC, API Key, ExtAuth, Basic Auth
How this skill is triggered — by the user, by Claude, or both
Slash command
/envoy-gateway-adopters:eg-authThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Configure authentication and authorization for Envoy Gateway using the SecurityPolicy CRD.
Configure authentication and authorization for Envoy Gateway using the SecurityPolicy CRD. SecurityPolicy attaches to a Gateway (applies to all routes) or a specific HTTPRoute/GRPCRoute. When a SecurityPolicy targets both a Gateway and a Route, the Route-level policy takes precedence.
Determine whether authentication applies at the Gateway level (all routes) or to a specific HTTPRoute.
For Gateway-level targeting (default):
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: <policy-name> # TODO: Replace with a descriptive name
namespace: <namespace> # Must match the target resource namespace
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: <gateway-name> # TODO: Replace with your Gateway name
For HTTPRoute-level targeting:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: <policy-name>
namespace: <namespace>
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace with your HTTPRoute name
You can also use targetSelectors to match resources by label instead of name:
spec:
targetSelectors:
- kind: HTTPRoute
group: gateway.networking.k8s.io
matchLabels:
app: my-protected-app
Select one of the following authentication methods based on the Method argument.
Validates JSON Web Tokens using remote or local JWKS. Best for service-to-service and API authentication.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-auth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
jwt:
providers:
- name: my-provider # TODO: Name this provider (referenced in authorization rules)
issuer: "https://issuer.example.com" # TODO: Replace with your token issuer URL
remoteJWKS:
uri: "https://issuer.example.com/.well-known/jwks.json" # TODO: Replace with your JWKS endpoint
Using local JWKS (stored in a ConfigMap instead of fetched remotely):
jwt:
providers:
- name: my-provider
localJWKS:
type: ValueRef
valueRef:
group: ""
kind: ConfigMap
name: jwt-local-jwks # TODO: Create this ConfigMap with a "jwks" key
Extract claims to headers (forward JWT claims to the backend):
jwt:
providers:
- name: my-provider
issuer: "https://issuer.example.com"
remoteJWKS:
uri: "https://issuer.example.com/.well-known/jwks.json"
extractFrom:
headers:
- name: Authorization
valuePrefix: "Bearer "
# Also extract from cookies if needed:
# cookies:
# - access-token
Claims-based authorization (require specific claim values):
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: jwt-claim-auth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
jwt:
providers:
- name: my-provider
issuer: "https://issuer.example.com" # TODO: Replace
remoteJWKS:
uri: "https://issuer.example.com/.well-known/jwks.json" # TODO: Replace
authorization:
defaultAction: Deny
rules:
- name: allow-admins
action: Allow
principal:
jwt:
provider: my-provider # Must match the provider name above
scopes: ["read", "write"] # TODO: Replace with required scopes
claims:
- name: user.roles # TODO: Replace with the claim path to check
valueType: StringArray
values: ["admin"] # TODO: Replace with required claim values
Redirects unauthenticated users to an OpenID Connect provider for interactive login. Best for web applications with browser-based users. Requires HTTPS on the Gateway listener.
First, create a Secret containing your OIDC client secret:
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: oidc-client-secret # TODO: Choose a name
namespace: <namespace>
stringData:
client-secret: "<your-client-secret>" # TODO: Replace with your OIDC client secret
Then create the SecurityPolicy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: oidc-auth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
oidc:
provider:
issuer: "https://accounts.google.com" # TODO: Replace with your OIDC provider issuer
clientID: "<your-client-id>" # TODO: Replace with your OIDC client ID
clientSecret:
name: oidc-client-secret # Must match the Secret name above
# redirectURL and logoutPath MUST match the target HTTPRoute's host and path prefix
redirectURL: "https://www.example.com/myapp/oauth2/callback" # TODO: Replace
logoutPath: "/myapp/logout" # TODO: Replace
scopes:
- openid
- profile
- email # TODO: Adjust scopes as needed
# Forward the access token to the backend via Authorization header:
# forwardAccessToken: true
# Share cookies across subdomains:
# cookieDomain: "example.com"
Important: The redirectURL must be prefixed with the target HTTPRoute's host and path. The logoutPath must be prefixed with the HTTPRoute's path prefix. Register this redirect URL with your OIDC provider.
Validates requests against API keys stored in Kubernetes Secrets. Good for machine-to-machine API access.
First, create an Opaque Secret containing valid API keys (key = client ID, value = API key):
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: apikey-secret # TODO: Choose a name
namespace: <namespace>
stringData:
client1: "supersecret-key-1" # TODO: Replace with actual API keys
client2: "supersecret-key-2"
# NOTE: Do NOT include "Bearer " prefix in the values even if clients send
# "Authorization: Bearer <key>". Envoy strips the prefix automatically.
Then create the SecurityPolicy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: apikey-auth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
apiKeyAuth:
credentialRefs:
- group: ""
kind: Secret
name: apikey-secret # Must match the Secret name above
extractFrom:
# Extract API key from a custom header:
- headers:
- x-api-key # TODO: Change the header name if needed
# Or extract from a query parameter:
# - params:
# - api_key
# Or extract from the Authorization header (Bearer scheme):
# - headers:
# - Authorization
Delegates auth decisions to an external HTTP or gRPC service. Use ExtAuth when your authorization logic requires database lookups, custom business rules, or integration with systems not natively supported by Envoy Gateway.
HTTP ExtAuth:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: ext-auth-http
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
extAuth:
http:
backendRefs:
- name: http-ext-auth # TODO: Replace with your auth service name
port: 9002 # TODO: Replace with your auth service port
headersToBackend:
- x-current-user # Headers from auth response to forward to the backend
# Optional: send specific headers to the auth service
# By default HTTP ExtAuth only receives: Host, Method, Path, Content-Length, Authorization
headersToExtAuth:
- x-custom-header # TODO: Add headers your auth service needs
# failOpen: false # Set to true to allow traffic if the auth service is unavailable
# timeout: 10s # Timeout for auth service requests (default: 10s)
gRPC ExtAuth:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: ext-auth-grpc
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
extAuth:
grpc:
backendRefs:
- name: grpc-ext-auth # TODO: Replace with your gRPC auth service name
port: 9002 # TODO: Replace with your gRPC auth service port
# gRPC services receive ALL request headers by default (unlike HTTP)
# failOpen: false
# timeout: 10s
When to use ExtAuth vs. built-in methods:
WARNING (EGTM-023): Basic authentication uses SHA1 hashing and does not enforce password complexity. It is recommended to use JWT or OIDC instead. If you must use Basic Auth, always pair it with TLS to prevent credentials from being transmitted in plain text.
First, generate an htpasswd file and create a Secret:
# Generate .htpasswd file (SHA algorithm)
htpasswd -cbs .htpasswd user1 password1
htpasswd -bs .htpasswd user2 password2
# Create the Kubernetes Secret
kubectl create secret generic basic-auth --from-file=.htpasswd -n <namespace>
Then create the SecurityPolicy:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: basic-auth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
basicAuth:
users:
name: basic-auth # Must match the Secret name above
# forwardUsernameHeader: x-username # Optional: forward authenticated username to backend
Authorization rules work independently or alongside any authentication method. They control which authenticated requests are allowed or denied.
IP-based allow/deny lists:
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: ip-allow-list
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
authorization:
defaultAction: Deny
rules:
- name: allow-internal
action: Allow
principal:
clientCIDRs:
- 10.0.0.0/8 # TODO: Replace with your allowed CIDR ranges
- 192.168.0.0/16
JWT claim-based authorization (combine with JWT authentication):
authorization:
defaultAction: Deny
rules:
- name: allow-by-claim
action: Allow
principal:
jwt:
provider: my-provider # Must match a JWT provider name
claims:
- name: groups
valueType: StringArray
values: ["engineering", "platform"]
CORS can be configured in the same SecurityPolicy alongside authentication.
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
name: cors-and-auth
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: <route-name> # TODO: Replace
cors:
allowOrigins:
- "https://app.example.com" # TODO: Replace with your allowed origins
- "https://*.example.com" # Wildcard subdomain support
allowMethods:
- GET
- POST
- PUT
- DELETE
allowHeaders:
- Authorization
- Content-Type
exposeHeaders:
- X-Request-Id
maxAge: 86400s # Cache preflight for 24 hours
# allowCredentials: true # Enable if cookies/auth headers needed cross-origin
jwt:
providers:
- name: my-provider
issuer: "https://issuer.example.com"
remoteJWKS:
uri: "https://issuer.example.com/.well-known/jwks.json"
kubectl apply -f security-policy.yaml
# Verify the SecurityPolicy status
kubectl get securitypolicy/<policy-name> -o yaml
# Check that conditions show Accepted: True
kubectl get securitypolicy/<policy-name> -o jsonpath='{.status.conditions}'
npx claudepluginhub missberg/envoy-skills --plugin envoy-gateway-adoptersConfigures API gateways (Kong, AWS, Azure, Apigee) as centralized security enforcement points for authentication, rate limiting, request validation, and threat protection.
Configures API gateways (Kong, AWS, Azure, Apigee) as centralized security enforcement points for authentication, rate limiting, request validation, and threat protection.
Guides API authentication, authorization, and security patterns including OAuth 2.0 flows with PKCE, OIDC, JWT, API keys, rate limiting, and common vulnerabilities.