Examples
Copy-paste starters for every endpoint, in curl, Node, Python, and CI.
Every snippet below honours the JWTSHIELD_URL environment variable. Set it to your account’s API endpoint before running.
Decode a token — /v1/inspect/token
inspect_token.sh
BASE_URL="${JWTSHIELD_URL:-https://api.jwtshield.com}"
TOKEN="$1"
curl --silent --show-error --fail \
--request POST \
--header "Authorization: Bearer $JWTSHIELD_KEY" \
--header "Content-Type: application/json" \
--data "$(printf '{"token": "%s"}' "$TOKEN")" \
"$BASE_URL/v1/inspect/token"inspect_token.js
const BASE_URL = process.env.JWTSHIELD_URL || "https://api.jwtshield.com";
const KEY = process.env.JWTSHIELD_KEY;
async function inspectToken(token) {
const response = await fetch(`${BASE_URL}/v1/inspect/token`, {
method: "POST",
headers: {
"Authorization": `Bearer ${KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ token }),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
return await response.json();
}
const body = await inspectToken(process.argv[2]);
console.log(`validated: ${body.validated}`);
console.log(`header: ${JSON.stringify(body.decoded.header)}`);
console.log(`payload: ${JSON.stringify(body.decoded.payload)}`);inspect_token.py
import os, sys, httpx
BASE_URL = os.environ.get("JWTSHIELD_URL", "https://api.jwtshield.com")
KEY = os.environ["JWTSHIELD_KEY"]
response = httpx.post(
f"{BASE_URL}/v1/inspect/token",
headers={"Authorization": f"Bearer {KEY}"},
json={"token": sys.argv[1]},
timeout=10.0,
)
response.raise_for_status()
body = response.json()
print(f"validated: {body['validated']}")
print(f"header: {body['decoded']['header']}")
print(f"payload: {body['decoded']['payload']}")Validate with an inline policy — /v1/validate/jwt
validate_jwt.sh
BASE_URL="${JWTSHIELD_URL:-https://api.jwtshield.com}"
SECRET="your-256-bit-secret"
ISSUER="https://issuer.example.com"
AUDIENCE="api://backend"
TOKEN="$1"
curl --silent --show-error --fail \
--request POST \
--header "Authorization: Bearer $JWTSHIELD_KEY" \
--header "Content-Type: application/json" \
--data "$(cat <<JSON
{
"token": "${TOKEN}",
"policy": {
"secret": "${SECRET}",
"issuer": "${ISSUER}",
"audiences": ["${AUDIENCE}"],
"allowed_algs": ["HS256"]
}
}
JSON
)" \
"$BASE_URL/v1/validate/jwt"validate_jwt.js
const BASE_URL = process.env.JWTSHIELD_URL || "https://api.jwtshield.com";
const KEY = process.env.JWTSHIELD_KEY;
async function validateJwt(token) {
const policy = {
secret: "your-256-bit-secret",
issuer: "https://issuer.example.com",
audiences: ["api://backend"],
allowed_algs: ["HS256"],
};
const response = await fetch(`${BASE_URL}/v1/validate/jwt`, {
method: "POST",
headers: {
"Authorization": `Bearer ${KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ token, policy }),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
}
const body = await validateJwt(process.argv[2]);
console.log("valid:", body.valid);
for (const finding of body.findings) {
console.log(` - ${finding.code} (${finding.severity}): ${finding.message}`);
}validate_jwt.py
import os, sys, httpx
BASE_URL = os.environ.get("JWTSHIELD_URL", "https://api.jwtshield.com")
KEY = os.environ["JWTSHIELD_KEY"]
policy = {
"secret": "your-256-bit-secret",
"issuer": "https://issuer.example.com",
"audiences": ["api://backend"],
"allowed_algs": ["HS256"],
}
response = httpx.post(
f"{BASE_URL}/v1/validate/jwt",
headers={"Authorization": f"Bearer {KEY}"},
json={"token": sys.argv[1], "policy": policy},
timeout=10.0,
)
response.raise_for_status()
body = response.json()
print(f"valid: {body['valid']}")
for f in body["findings"]:
print(f" - {f['code']} ({f['severity']}): {f['message']}")
print(f"summary: {body['summary']}")Validate against a registered issuer profile
When operators register profiles via the ISSUER_PROFILES_JSON environment variable, clients can reference them by ID instead of inlining the policy.
validate_with_profile.sh
curl -sSf -X POST "$JWTSHIELD_URL/v1/validate/jwt" \
-H "Authorization: Bearer $JWTSHIELD_KEY" \
-H "Content-Type: application/json" \
-d '{"token":"<jwt>","issuer_profile_id":"acme-auth0"}'validate_with_profile.py
KEY = os.environ["JWTSHIELD_KEY"]
httpx.post(
f"{BASE_URL}/v1/validate/jwt",
headers={"Authorization": f"Bearer {KEY}"},
json={
"token": token,
"issuer_profile_id": "acme-auth0",
},
timeout=10.0,
).raise_for_status()Run a regression suite — /v1/test/auth-regression
auth_regression.sh
curl -sSf -X POST "$JWTSHIELD_URL/v1/test/auth-regression" \
-H "Authorization: Bearer $JWTSHIELD_KEY" \
-H "Content-Type: application/json" \
-d '{
"checks": [
{
"token": "<good-token>",
"issuer_profile_id": "acme-auth0"
},
{
"token": "<expired-token>",
"issuer_profile_id": "acme-auth0",
"expected_failure_codes": ["TOKEN_EXPIRED"]
}
],
"fail_on_severity": "error"
}'Validate a CI OIDC token — /v1/validate/ci-oidc
GitHub Actions:
# .github/workflows/jwtshield-validate.yml
permissions:
contents: read
id-token: write
jobs:
validate-oidc:
runs-on: ubuntu-latest
steps:
- name: Retrieve runner OIDC token
id: token
run: |
JWT=$(curl -sSf \
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://jwtshield" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["value"])')
echo "::add-mask::$JWT"
echo "jwt=$JWT" >> "$GITHUB_OUTPUT"
- name: Validate via JWTShield
run: |
curl -sSf -H "Authorization: Bearer ${{ secrets.JWTSHIELD_KEY }}" \
-H "Content-Type: application/json" \
-d '{
"token": "${{ steps.token.outputs.jwt }}",
"provider": "github_actions",
"expected_repository": "${{ github.repository }}",
"expected_ref": "${{ github.ref }}"
}' \
"$JWTSHIELD_URL/v1/validate/ci-oidc"
GitLab CI:
# .gitlab-ci.yml
validate-oidc:
stage: validate
image: python:3.12-slim
id_tokens:
JWTSHIELD_OIDC_TOKEN:
aud: "api://jwtshield"
script:
- |
curl -sSf -H "Authorization: Bearer $JWTSHIELD_KEY" \
-H "Content-Type: application/json" \
-d "{\"token\":\"$JWTSHIELD_OIDC_TOKEN\",\"provider\":\"gitlab\",\"expected_project_path\":\"$CI_PROJECT_PATH\"}" \
"$JWTSHIELD_URL/v1/validate/ci-oidc"
See CI · OIDC guide for the full workflow with failure handling.
Lint an OIDC config — /v1/lint/oidc-config
curl -sSf -X POST "$JWTSHIELD_URL/v1/lint/oidc-config" \
-H "Authorization: Bearer $JWTSHIELD_KEY" \
-H "Content-Type: application/json" \
-d '{
"issuer": "https://acme.auth0.com/",
"client_id": "abc123",
"audiences": ["api://acme-backend"],
"jwks_uri": "https://acme.auth0.com/.well-known/jwks.json",
"redirect_uris": ["https://app.acme.com/cb"],
"alg_policy": { "allowed_algs": ["RS256"] },
"https_required": true
}'