jwe-decrypt
The jwe-decrypt plugin decrypts JWE authorization headers in requests sent to APISIX routes or services.
Examples
The examples below demonstrate how you can work with the jwe-decrypt plugin for different scenarios.
Decrypt Data with JWE
The following example demonstrates how to decrypt a JWE token. Generate JWE tokens outside APISIX, configure the matching decryption key on a consumer, and create a route with jwe-decrypt to decrypt the authorization header.
- Admin API
- ADC
- Ingress Controller
Create a consumer with jwe-decrypt and configure the decryption key:
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"username": "jack",
"plugins": {
"jwe-decrypt": {
"key": "jack-key",
"secret": "key-length-should-be-32-chars123"
}
}
}'
Create a route with jwe-decrypt to decrypt the authorization header:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "jwe-decrypt-route",
"uri": "/anything/jwe",
"plugins": {
"jwe-decrypt": {
"header": "Authorization",
"forward_header": "Authorization"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
consumers:
- username: jack
plugins:
jwe-decrypt:
key: jack-key
secret: key-length-should-be-32-chars123
services:
- name: jwe-decrypt-service
routes:
- name: jwe-decrypt-route
uris:
- /anything/jwe
plugins:
jwe-decrypt:
header: Authorization
forward_header: Authorization
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
namespace: aic
name: jack
spec:
gatewayRef:
name: apisix
plugins:
- name: jwe-decrypt
config:
key: jack-key
secret: key-length-should-be-32-chars123
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: jwe-decrypt-plugin-config
spec:
plugins:
- name: jwe-decrypt
config:
header: Authorization
forward_header: Authorization
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: jwe-decrypt-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything/jwe
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: jwe-decrypt-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
Apply the configuration to your cluster:
kubectl apply -f jwe-decrypt-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
namespace: aic
name: jack
spec:
ingressClassName: apisix
plugins:
- name: jwe-decrypt
config:
key: jack-key
secret: key-length-should-be-32-chars123
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: jwe-decrypt-route
spec:
ingressClassName: apisix
http:
- name: jwe-decrypt-route
match:
paths:
- /anything/jwe
upstreams:
- name: httpbin-external-domain
plugins:
- name: jwe-decrypt
config:
header: Authorization
forward_header: Authorization
Apply the configuration to your cluster:
kubectl apply -f jwe-decrypt-apisix-crd.yaml
Generate JWE tokens outside APISIX with the consumer secret as the encryption key. The token should use this structure:
base64url(header)..base64url(iv).base64url(ciphertext).base64url(tag)
where the header is {"alg":"dir","enc":"A256GCM","kid":"<consumer-key>"}. Use a unique, randomly generated IV for each token.
APISIX decrypts the ciphertext and tag directly with AES-256-GCM and does not pass the protected header as additional authenticated data (AAD). If you generate the token with a general-purpose JWE library, configure it so the authentication tag is calculated without AAD; otherwise APISIX rejects the token with failed to decrypt JWE token.
Send a request to the route with the JWE encrypted data in the Authorization header. For example, the following token encrypts the payload {"uid":10000,"uname":"test"} for the consumer key jack-key with the secret configured above:
curl "http://127.0.0.1:9080/anything/jwe" -H 'Authorization: eyJraWQiOiJqYWNrLWtleSIsImFsZyI6ImRpciIsImVuYyI6IkEyNTZHQ00ifQ..vi29KBCQKcVmPwTT.VToyPMFbq-ZY05MIpntP1N3AmYeq3zELQ0B6iQ.vuTPG2ODc-DjUTjNCzfA2A'
You should see a response similar to the following, where the Authorization header shows the plaintext of the payload:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Authorization": "{\"uid\":10000,\"uname\":\"test\"}",
"Host": "127.0.0.1",
"User-Agent": "curl/8.1.2",
"X-Amzn-Trace-Id": "Root=1-6510f2c3-1586ec011a22b5094dbe1896",
"X-Forwarded-Host": "127.0.0.1"
},
"json": null,
"method": "GET",
"origin": "127.0.0.1, 119.143.79.94",
"url": "http://127.0.0.1/anything/jwe"
}