Authenticate Consumer using multiple JWTs from different sourcesv3.14+
Authenticate a Consumer by verifying a JWT from one of two possible sources, each backed by a different JWKS.
The plugin checks for a primary Authorization header first.
If it doesn’t find the header, it falls back to a secondary Authorization2 header.
The verified JWT’s sub claim is used to look up and authenticate the matching Kong Gateway Consumer.
This example contains the following nodes:
- The node
HAS_AUTH1checks whether a primary Authorization header is present. - The node
BRANCH_AUTH1checks for an Authorization header. If the header exists, it extracts and verifies the JWT against JWKS1 and sets the Consumer; otherwise it checks for the secondary header. - The nodes
EXTRACT_AUTH1,VERIFY_AUTH1,BUILD_CONSUMER1, andSET_CONSUMER1handle the primary JWT path. - The node
HAS_AUTH2checks whether a secondary Authorization2 header is present. - The node
BRANCH_AUTH2routes execution for the secondary JWT path. - The nodes
EXTRACT_AUTH2,VERIFY_AUTH2,BUILD_CONSUMER2, andSET_CONSUMER2handle the secondary JWT path.
Note: Datakit has a priority of 810, which means it runs after rate limiting plugins (priority 900 and above). If you use Consumer-based rate limits, Datakit must run first so the Consumer is set before rate limiting executes. You can adjust this with dynamic plugin ordering.
Prerequisites
-
You have configured a Consumer.
-
You have configured Vault secrets for both JWKS JSON values.
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: datakit
config:
resources:
vault:
jwks1: "{vault://env/JWKS1_JSON}"
jwks2: "{vault://env/JWKS2_JSON}"
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: "(.Authorization // .authorization) != null\n"
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: ".Authorization // .authorization\n"
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: "(.Authorization2 // .authorization2) != null\n"
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: ".Authorization2 // .authorization2\n"
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
Make the following request:
curl -i -X POST http://localhost:8001/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongClusterPlugin
metadata:
name: datakit
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
labels:
global: 'true'
config:
resources:
vault:
jwks1: '{vault://env/JWKS1_JSON}'
jwks2: '{vault://env/JWKS2_JSON}'
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: '(.Authorization // .authorization) != null\n'
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: '.Authorization // .authorization\n'
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: '(.Authorization2 // .authorization2) != null\n'
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: '.Authorization2 // .authorization2\n'
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
plugin: datakit
" | kubectl apply -f -
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_datakit" "my_datakit" {
enabled = true
config = {
resources = {
vault = {
jwks1 = "{vault://env/JWKS1_JSON}"
jwks2 = "{vault://env/JWKS2_JSON}"
}
}
nodes = [
{
name = "HAS_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization // .authorization) != null
EOF
},
{
name = "BRANCH_AUTH1"
type = "branch"
input = "HAS_AUTH1"
then = ["EXTRACT_AUTH1", "VERIFY_AUTH1", "BUILD_CONSUMER1", "SET_CONSUMER1"]
else = ["HAS_AUTH2", "BRANCH_AUTH2"]
},
{
name = "EXTRACT_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization // .authorization
EOF
},
{
name = "VERIFY_AUTH1"
type = "jwt_verify"
issuers = ["expected-issuer-1"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH1"
key = "vault.jwks1"
}
},
{
name = "BUILD_CONSUMER1"
type = "jq"
input = "VERIFY_AUTH1.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER1"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER1"
},
{
name = "HAS_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization2 // .authorization2) != null
EOF
},
{
name = "BRANCH_AUTH2"
type = "branch"
input = "HAS_AUTH2"
then = ["EXTRACT_AUTH2", "VERIFY_AUTH2", "BUILD_CONSUMER2", "SET_CONSUMER2"]
},
{
name = "EXTRACT_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization2 // .authorization2
EOF
},
{
name = "VERIFY_AUTH2"
type = "jwt_verify"
issuers = ["expected-issuer-2"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH2"
key = "vault.jwks2"
}
},
{
name = "BUILD_CONSUMER2"
type = "jq"
input = "VERIFY_AUTH2.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER2"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER2"
} ]
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: datakit
service: serviceName|Id
config:
resources:
vault:
jwks1: "{vault://env/JWKS1_JSON}"
jwks2: "{vault://env/JWKS2_JSON}"
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: "(.Authorization // .authorization) != null\n"
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: ".Authorization // .authorization\n"
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: "(.Authorization2 // .authorization2) != null\n"
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: ".Authorization2 // .authorization2\n"
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
Make sure to replace the following placeholders with your own values:
-
serviceName|Id: Theidornameof the service the plugin configuration will target.
Make the following request:
curl -i -X POST http://localhost:8001/services/{serviceName|Id}/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
serviceName|Id: Theidornameof the service the plugin configuration will target.
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/services/{serviceId}/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane. -
serviceId: Theidof the service the plugin configuration will target.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: datakit
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
resources:
vault:
jwks1: '{vault://env/JWKS1_JSON}'
jwks2: '{vault://env/JWKS2_JSON}'
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: '(.Authorization // .authorization) != null\n'
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: '.Authorization // .authorization\n'
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: '(.Authorization2 // .authorization2) != null\n'
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: '.Authorization2 // .authorization2\n'
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
plugin: datakit
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the service resource:
kubectl annotate -n kong service SERVICE_NAME konghq.com/plugins=datakit
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_datakit" "my_datakit" {
enabled = true
config = {
resources = {
vault = {
jwks1 = "{vault://env/JWKS1_JSON}"
jwks2 = "{vault://env/JWKS2_JSON}"
}
}
nodes = [
{
name = "HAS_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization // .authorization) != null
EOF
},
{
name = "BRANCH_AUTH1"
type = "branch"
input = "HAS_AUTH1"
then = ["EXTRACT_AUTH1", "VERIFY_AUTH1", "BUILD_CONSUMER1", "SET_CONSUMER1"]
else = ["HAS_AUTH2", "BRANCH_AUTH2"]
},
{
name = "EXTRACT_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization // .authorization
EOF
},
{
name = "VERIFY_AUTH1"
type = "jwt_verify"
issuers = ["expected-issuer-1"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH1"
key = "vault.jwks1"
}
},
{
name = "BUILD_CONSUMER1"
type = "jq"
input = "VERIFY_AUTH1.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER1"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER1"
},
{
name = "HAS_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization2 // .authorization2) != null
EOF
},
{
name = "BRANCH_AUTH2"
type = "branch"
input = "HAS_AUTH2"
then = ["EXTRACT_AUTH2", "VERIFY_AUTH2", "BUILD_CONSUMER2", "SET_CONSUMER2"]
},
{
name = "EXTRACT_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization2 // .authorization2
EOF
},
{
name = "VERIFY_AUTH2"
type = "jwt_verify"
issuers = ["expected-issuer-2"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH2"
key = "vault.jwks2"
}
},
{
name = "BUILD_CONSUMER2"
type = "jq"
input = "VERIFY_AUTH2.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER2"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER2"
} ]
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
service = {
id = konnect_gateway_service.my_service.id
}
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: datakit
route: routeName|Id
config:
resources:
vault:
jwks1: "{vault://env/JWKS1_JSON}"
jwks2: "{vault://env/JWKS2_JSON}"
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: "(.Authorization // .authorization) != null\n"
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: ".Authorization // .authorization\n"
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: "(.Authorization2 // .authorization2) != null\n"
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: ".Authorization2 // .authorization2\n"
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
Make sure to replace the following placeholders with your own values:
-
routeName|Id: Theidornameof the route the plugin configuration will target.
Make the following request:
curl -i -X POST http://localhost:8001/routes/{routeName|Id}/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
routeName|Id: Theidornameof the route the plugin configuration will target.
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/routes/{routeId}/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane. -
routeId: Theidof the route the plugin configuration will target.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: datakit
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
resources:
vault:
jwks1: '{vault://env/JWKS1_JSON}'
jwks2: '{vault://env/JWKS2_JSON}'
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: '(.Authorization // .authorization) != null\n'
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: '.Authorization // .authorization\n'
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: '(.Authorization2 // .authorization2) != null\n'
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: '.Authorization2 // .authorization2\n'
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
plugin: datakit
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the httproute or ingress resource:
kubectl annotate -n kong httproute konghq.com/plugins=datakit
kubectl annotate -n kong ingress konghq.com/plugins=datakit
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_datakit" "my_datakit" {
enabled = true
config = {
resources = {
vault = {
jwks1 = "{vault://env/JWKS1_JSON}"
jwks2 = "{vault://env/JWKS2_JSON}"
}
}
nodes = [
{
name = "HAS_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization // .authorization) != null
EOF
},
{
name = "BRANCH_AUTH1"
type = "branch"
input = "HAS_AUTH1"
then = ["EXTRACT_AUTH1", "VERIFY_AUTH1", "BUILD_CONSUMER1", "SET_CONSUMER1"]
else = ["HAS_AUTH2", "BRANCH_AUTH2"]
},
{
name = "EXTRACT_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization // .authorization
EOF
},
{
name = "VERIFY_AUTH1"
type = "jwt_verify"
issuers = ["expected-issuer-1"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH1"
key = "vault.jwks1"
}
},
{
name = "BUILD_CONSUMER1"
type = "jq"
input = "VERIFY_AUTH1.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER1"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER1"
},
{
name = "HAS_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization2 // .authorization2) != null
EOF
},
{
name = "BRANCH_AUTH2"
type = "branch"
input = "HAS_AUTH2"
then = ["EXTRACT_AUTH2", "VERIFY_AUTH2", "BUILD_CONSUMER2", "SET_CONSUMER2"]
},
{
name = "EXTRACT_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization2 // .authorization2
EOF
},
{
name = "VERIFY_AUTH2"
type = "jwt_verify"
issuers = ["expected-issuer-2"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH2"
key = "vault.jwks2"
}
},
{
name = "BUILD_CONSUMER2"
type = "jq"
input = "VERIFY_AUTH2.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER2"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER2"
} ]
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
route = {
id = konnect_gateway_route.my_route.id
}
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: datakit
consumer: consumerName|Id
config:
resources:
vault:
jwks1: "{vault://env/JWKS1_JSON}"
jwks2: "{vault://env/JWKS2_JSON}"
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: "(.Authorization // .authorization) != null\n"
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: ".Authorization // .authorization\n"
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: "(.Authorization2 // .authorization2) != null\n"
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: ".Authorization2 // .authorization2\n"
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
Make sure to replace the following placeholders with your own values:
-
consumerName|Id: Theidornameof the consumer the plugin configuration will target.
Make the following request:
curl -i -X POST http://localhost:8001/consumers/{consumerName|Id}/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
consumerName|Id: Theidornameof the consumer the plugin configuration will target.
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/consumers/{consumerId}/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane. -
consumerId: Theidof the consumer the plugin configuration will target.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: datakit
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
resources:
vault:
jwks1: '{vault://env/JWKS1_JSON}'
jwks2: '{vault://env/JWKS2_JSON}'
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: '(.Authorization // .authorization) != null\n'
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: '.Authorization // .authorization\n'
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: '(.Authorization2 // .authorization2) != null\n'
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: '.Authorization2 // .authorization2\n'
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
plugin: datakit
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the KongConsumer resource:
kubectl annotate -n kong kongconsumer CONSUMER_NAME konghq.com/plugins=datakit
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_datakit" "my_datakit" {
enabled = true
config = {
resources = {
vault = {
jwks1 = "{vault://env/JWKS1_JSON}"
jwks2 = "{vault://env/JWKS2_JSON}"
}
}
nodes = [
{
name = "HAS_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization // .authorization) != null
EOF
},
{
name = "BRANCH_AUTH1"
type = "branch"
input = "HAS_AUTH1"
then = ["EXTRACT_AUTH1", "VERIFY_AUTH1", "BUILD_CONSUMER1", "SET_CONSUMER1"]
else = ["HAS_AUTH2", "BRANCH_AUTH2"]
},
{
name = "EXTRACT_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization // .authorization
EOF
},
{
name = "VERIFY_AUTH1"
type = "jwt_verify"
issuers = ["expected-issuer-1"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH1"
key = "vault.jwks1"
}
},
{
name = "BUILD_CONSUMER1"
type = "jq"
input = "VERIFY_AUTH1.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER1"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER1"
},
{
name = "HAS_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization2 // .authorization2) != null
EOF
},
{
name = "BRANCH_AUTH2"
type = "branch"
input = "HAS_AUTH2"
then = ["EXTRACT_AUTH2", "VERIFY_AUTH2", "BUILD_CONSUMER2", "SET_CONSUMER2"]
},
{
name = "EXTRACT_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization2 // .authorization2
EOF
},
{
name = "VERIFY_AUTH2"
type = "jwt_verify"
issuers = ["expected-issuer-2"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH2"
key = "vault.jwks2"
}
},
{
name = "BUILD_CONSUMER2"
type = "jq"
input = "VERIFY_AUTH2.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER2"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER2"
} ]
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
consumer = {
id = konnect_gateway_consumer.my_consumer.id
}
}
Add this section to your kong.yaml configuration file:
_format_version: "3.0"
plugins:
- name: datakit
consumer_group: consumerGroupName|Id
config:
resources:
vault:
jwks1: "{vault://env/JWKS1_JSON}"
jwks2: "{vault://env/JWKS2_JSON}"
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: "(.Authorization // .authorization) != null\n"
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: ".Authorization // .authorization\n"
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: "(.Authorization2 // .authorization2) != null\n"
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: ".Authorization2 // .authorization2\n"
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ "username": .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
Make sure to replace the following placeholders with your own values:
-
consumerGroupName|Id: Theidornameof the consumer group the plugin configuration will target.
Make the following request:
curl -i -X POST http://localhost:8001/consumer_groups/{consumerGroupName|Id}/plugins/ \
--header "Accept: application/json" \
--header "Content-Type: application/json" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
consumerGroupName|Id: Theidornameof the consumer group the plugin configuration will target.
Make the following request:
curl -X POST https://{region}.api.konghq.com/v2/control-planes/{controlPlaneId}/core-entities/consumer_groups/{consumerGroupId}/plugins/ \
--header "accept: application/json" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $KONNECT_TOKEN" \
--data '
{
"name": "datakit",
"config": {
"resources": {
"vault": {
"jwks1": "{vault://env/JWKS1_JSON}",
"jwks2": "{vault://env/JWKS2_JSON}"
}
},
"nodes": [
{
"name": "HAS_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization // .authorization) != null\n"
},
{
"name": "BRANCH_AUTH1",
"type": "branch",
"input": "HAS_AUTH1",
"then": [
"EXTRACT_AUTH1",
"VERIFY_AUTH1",
"BUILD_CONSUMER1",
"SET_CONSUMER1"
],
"else": [
"HAS_AUTH2",
"BRANCH_AUTH2"
]
},
{
"name": "EXTRACT_AUTH1",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization // .authorization\n"
},
{
"name": "VERIFY_AUTH1",
"type": "jwt_verify",
"issuers": [
"expected-issuer-1"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH1",
"key": "vault.jwks1"
}
},
{
"name": "BUILD_CONSUMER1",
"type": "jq",
"input": "VERIFY_AUTH1.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER1",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER1"
},
{
"name": "HAS_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": "(.Authorization2 // .authorization2) != null\n"
},
{
"name": "BRANCH_AUTH2",
"type": "branch",
"input": "HAS_AUTH2",
"then": [
"EXTRACT_AUTH2",
"VERIFY_AUTH2",
"BUILD_CONSUMER2",
"SET_CONSUMER2"
]
},
{
"name": "EXTRACT_AUTH2",
"type": "jq",
"input": "request.headers",
"jq": ".Authorization2 // .authorization2\n"
},
{
"name": "VERIFY_AUTH2",
"type": "jwt_verify",
"issuers": [
"expected-issuer-2"
],
"required_claims": [
"sub",
"iss",
"exp"
],
"inputs": {
"token": "EXTRACT_AUTH2",
"key": "vault.jwks2"
}
},
{
"name": "BUILD_CONSUMER2",
"type": "jq",
"input": "VERIFY_AUTH2.claims",
"jq": "{ \"username\": .sub }\n"
},
{
"name": "SET_CONSUMER2",
"type": "property",
"property": "kong.client.consumer",
"input": "BUILD_CONSUMER2"
}
]
},
"tags": []
}
'
Make sure to replace the following placeholders with your own values:
-
region: Geographic region where your Kong Konnect is hosted and operates. -
KONNECT_TOKEN: Your Personal Access Token (PAT) associated with your Konnect account. -
controlPlaneId: Theidof the control plane. -
consumerGroupId: Theidof the consumer group the plugin configuration will target.
See the Konnect API reference to learn about region-specific URLs and personal access tokens.
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: datakit
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
konghq.com/tags: ''
config:
resources:
vault:
jwks1: '{vault://env/JWKS1_JSON}'
jwks2: '{vault://env/JWKS2_JSON}'
nodes:
- name: HAS_AUTH1
type: jq
input: request.headers
jq: '(.Authorization // .authorization) != null\n'
- name: BRANCH_AUTH1
type: branch
input: HAS_AUTH1
then:
- EXTRACT_AUTH1
- VERIFY_AUTH1
- BUILD_CONSUMER1
- SET_CONSUMER1
else:
- HAS_AUTH2
- BRANCH_AUTH2
- name: EXTRACT_AUTH1
type: jq
input: request.headers
jq: '.Authorization // .authorization\n'
- name: VERIFY_AUTH1
type: jwt_verify
issuers:
- expected-issuer-1
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH1
key: vault.jwks1
- name: BUILD_CONSUMER1
type: jq
input: VERIFY_AUTH1.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER1
type: property
property: kong.client.consumer
input: BUILD_CONSUMER1
- name: HAS_AUTH2
type: jq
input: request.headers
jq: '(.Authorization2 // .authorization2) != null\n'
- name: BRANCH_AUTH2
type: branch
input: HAS_AUTH2
then:
- EXTRACT_AUTH2
- VERIFY_AUTH2
- BUILD_CONSUMER2
- SET_CONSUMER2
- name: EXTRACT_AUTH2
type: jq
input: request.headers
jq: '.Authorization2 // .authorization2\n'
- name: VERIFY_AUTH2
type: jwt_verify
issuers:
- expected-issuer-2
required_claims:
- sub
- iss
- exp
inputs:
token: EXTRACT_AUTH2
key: vault.jwks2
- name: BUILD_CONSUMER2
type: jq
input: VERIFY_AUTH2.claims
jq: '{ 'username': .sub }
'
- name: SET_CONSUMER2
type: property
property: kong.client.consumer
input: BUILD_CONSUMER2
plugin: datakit
" | kubectl apply -f -
Next, apply the KongPlugin resource by annotating the KongConsumerGroup resource:
kubectl annotate -n kong kongconsumergroup CONSUMERGROUP_NAME konghq.com/plugins=datakit
Prerequisite: Configure your Personal Access Token
terraform {
required_providers {
konnect = {
source = "kong/konnect"
}
}
}
provider "konnect" {
personal_access_token = "$KONNECT_TOKEN"
server_url = "https://us.api.konghq.com/"
}
Add the following to your Terraform configuration to create a Konnect Gateway Plugin:
resource "konnect_gateway_plugin_datakit" "my_datakit" {
enabled = true
config = {
resources = {
vault = {
jwks1 = "{vault://env/JWKS1_JSON}"
jwks2 = "{vault://env/JWKS2_JSON}"
}
}
nodes = [
{
name = "HAS_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization // .authorization) != null
EOF
},
{
name = "BRANCH_AUTH1"
type = "branch"
input = "HAS_AUTH1"
then = ["EXTRACT_AUTH1", "VERIFY_AUTH1", "BUILD_CONSUMER1", "SET_CONSUMER1"]
else = ["HAS_AUTH2", "BRANCH_AUTH2"]
},
{
name = "EXTRACT_AUTH1"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization // .authorization
EOF
},
{
name = "VERIFY_AUTH1"
type = "jwt_verify"
issuers = ["expected-issuer-1"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH1"
key = "vault.jwks1"
}
},
{
name = "BUILD_CONSUMER1"
type = "jq"
input = "VERIFY_AUTH1.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER1"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER1"
},
{
name = "HAS_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
(.Authorization2 // .authorization2) != null
EOF
},
{
name = "BRANCH_AUTH2"
type = "branch"
input = "HAS_AUTH2"
then = ["EXTRACT_AUTH2", "VERIFY_AUTH2", "BUILD_CONSUMER2", "SET_CONSUMER2"]
},
{
name = "EXTRACT_AUTH2"
type = "jq"
input = "request.headers"
jq = <<EOF
.Authorization2 // .authorization2
EOF
},
{
name = "VERIFY_AUTH2"
type = "jwt_verify"
issuers = ["expected-issuer-2"]
required_claims = ["sub", "iss", "exp"]
inputs = {
token = "EXTRACT_AUTH2"
key = "vault.jwks2"
}
},
{
name = "BUILD_CONSUMER2"
type = "jq"
input = "VERIFY_AUTH2.claims"
jq = <<EOF
{ "username": .sub }
EOF
},
{
name = "SET_CONSUMER2"
type = "property"
property = "kong.client.consumer"
input = "BUILD_CONSUMER2"
} ]
}
tags = []
control_plane_id = konnect_gateway_control_plane.my_konnect_cp.id
consumer_group = {
id = konnect_gateway_consumer_group.my_consumer_group.id
}
}