From ad7721ba2c5136722bc700f7c38e0aa4334d8b33 Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Tue, 14 Oct 2025 17:54:16 +0530 Subject: [PATCH 01/17] Created a New Page for JWK Validation --- .../authentication/jwt-claim-validation.md | 671 +++++++++++++ .../json-web-tokens.md | 893 ------------------ tyk-docs/data/menu.yaml | 16 +- 3 files changed, 685 insertions(+), 895 deletions(-) create mode 100644 tyk-docs/content/api-management/authentication/jwt-claim-validation.md diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md new file mode 100644 index 0000000000..3a97cbb680 --- /dev/null +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -0,0 +1,671 @@ +--- +title: JWT Claim Validation +description: How to validate JWT claims in Tyk API Gateway. +tags: ["Authentication", "JWT", "JSON Web Tokens", "Claims", "Validation"] +keywords: ["Authentication", "JWT", "JSON Web Tokens", "Claims", "Validation"] +date: 2025-01-10 +--- + +## Introduction + +JSON Web Tokens contain claims - key-value pairs that provide information about the token and its subject. Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. + +Tyk supports validation of both: + +- **Registered claims**: standardized claims defined in the JWT specification (such as `iss`, `aud`, `exp`) +- **Custom claims**: application-specific claims that contain business logic or additional metadata + +By validating JWT claims, you can enforce fine-grained access control policies, ensure tokens originate from trusted sources, and verify that users have the appropriate permissions for your APIs. + +{{< note success >}} +**Note** + +JWT claim validation - with the exception of [temporal claims]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#temporal-claims-exp-iat-nbf" >}}) - is available exclusively for Tyk OAS APIs and from Tyk 5.10.0 onwards. +{{< /note >}} + +## JWT Claims Fundamentals + +### What are JWT Claims? +A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The payload contains the claims - a set of key-value pairs that carry information about the token and its subject. + +```json +{ + "iss": "https://auth.company.com", + "aud": "api.company.com", + "sub": "user123", + "exp": 1735689600, + "iat": 1735603200, + "department": "engineering", + "role": "admin" +} +``` + +Claims serve different purposes: + +- **Identity information**: who the token represents (`sub`, `iss`) +- **Access control**: what the token can access (`aud`, custom permissions) +- **Validity period**: when the token is valid (`exp`, `iat`, `nbf`) +- **Business logic**: application-specific data (`department`, `role`) + +### Registered vs Custom Claims + +Registered Claims are standardized by the JWT specification ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1)) and have predefined meanings: + +| Claim | Name | Purpose | +|-------|------------|---------| +| `iss` | Issuer | Identifies who issued the token | +| `aud` | Audience | Identifies who the token is intended for | +| `sub` | Subject | Identifies the subject of the token | +| `exp` | Expiration Time | When the token expires | +| `iat` | Issued At | When the token was issued | +| `nbf` | Not Before | When the token becomes valid | +| `jti` | JWT ID | Unique identifier for the token | + +Custom Claims are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. + +### How Tyk Processes JWT Claims + +After [verifying]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) that the token hasn't been tampered with, Tyk processes claims in this order: + +- [Registered Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#registered-claims-validation" >}}): Checks standard claims against your configuration +- [Custom Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#custom-claims-validation" >}}): Applies your business rules to custom claims +- [Authorization]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#managing-authorization" >}}): Uses validated claims to determine API access and apply policies + +If any validation step fails, Tyk rejects the request with a specific error message indicating which claim validation failed and why. + +## Registered Claims Validation + +Tyk can validate the seven registered JWT claims defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1). These claims are grouped into **temporal claims** (time-based validation) and **identity claims** (content-based validation). + +### Temporal Claims (exp, iat, nbf) + +Temporal claims define when a JWT is valid. Tyk automatically validates these claims when present in the token. + +- **Expiration Time (exp)**: the `exp` claim specifies when the token expires (as a Unix timestamp). Tyk rejects tokens where the current time is after the expiration time. +- **Issued At (iat)**: the `iat` claim specifies when the token was issued. Tyk rejects tokens that claim to be issued in the future. +- **Not Before (nbf)**: the `nbf` claim specifies the earliest time the token can be used. Tyk rejects tokens before this time. + +#### Clock Skew Configuration + +Due to the nature of distributed systems, you may encounter clock skew between your Identity Provider and Tyk servers. You can configure tolerance for timing differences: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + issuedAtValidationSkew: 5 # Allow tokens issued up to 5 seconds in the future + notBeforeValidationSkew: 2 # Allow tokens to be valid 2 seconds early + expiresAtValidationSkew: 2 # Allow tokens to be valid 2 seconds past expiration +``` + +- `expiresAtValidationSkew` allows recently expired tokens to be considered valid +- `issuedAtValidationSkew` allows tokens claiming future issuance to be valid +- `notBeforeValidationSkew` allows tokens to be valid before their `nbf` time + +{{< note success >}} +**Note** + +Temporal claim validation and the associated clock skew controls were supported by Tyk prior to 5.10.0 and also for [Tyk Classic APIs]({{< ref "api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis" >}}) +{{< /note >}} + +### Identity Claims (iss, aud, sub, jti) + +Identity claims provide information about the token's origin and intended use. Unlike temporal claims, these require explicit configuration to enable validation. + +#### Issuer Validation (iss) + +Validates that the token was issued by a trusted Identity Provider: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + allowedIssuers: + - "https://auth.company.com" + - "https://auth.partner.com" +``` + +Tyk accepts tokens if the `iss` claim matches any configured issuer. If `allowedIssuers` is empty, no issuer validation is performed. + +#### Audience Validation (aud) + +Validates that the token is intended for your API: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + allowedAudiences: + - "api.company.com" + - "mobile-app" +``` + +The `aud` claim can be a string or array. Tyk accepts tokens if any audience value matches any configured audience. If `allowedAudiences` is empty, no audience validation is performed. + +#### Subject Validation (sub) + +Validates the token subject against allowed values: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + allowedSubjects: + - "user" + - "service-account" + - "admin" +``` + +Useful for restricting API access to specific types of subjects or known entities. If `allowedSubjects` is empty, no audience validation is performed. + +#### JWT ID Validation (jti) + +Validates that the token contains a unique identifier: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + jtiValidation: + enabled: true +``` + +When enabled, Tyk requires the `jti` claim to be present. This is useful for token tracking and revocation scenarios. Note that Tyk does not perform any validation on the content of the claim, only that it is present. + +### Configuration Examples + +Basic registered claims validation: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + allowedIssuers: ["https://auth.company.com"] + allowedAudiences: ["api.company.com"] + jtiValidation: + enabled: true + expiresAtValidationSkew: 5 +``` + +Multi-IdP configuration: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + allowedIssuers: + - "https://auth0.company.com" + - "https://keycloak.company.com" + allowedAudiences: + - "api.company.com" + - "mobile.company.com" + subjectClaims: ["sub", "username"] +``` + +In this example we expect one Identity Provider to present the subject in the `sub` claim, and the other to present it in the `username` claim. + +## Custom Claims Validation + +Custom claims validation allows you to enforce business-specific rules on JWT tokens beyond the standard registered claims. + +**Use Cases**: + +- **Role-based access control**: Validate that users have required roles (for example `admin`, `editor` ,`viewer`) +- **Department restrictions**: Ensure users belong to authorized departments +- **Feature flags**: Check if users have access to specific features or API endpoints +- **Geographic restrictions**: Validate user location or region-based access +- **Subscription tiers**: Enforce access based on user subscription levels + +### Validation Types + +Three distinct validation types are supported by the custom claims validation. These validation types can be applied to any custom claim in your JWT tokens, providing flexible control over your authorization logic. + +#### Required + +Required type validation ensures that a specific claim exists in the JWT token, regardless of its value. + +**Use Cases:** + +- Ensuring user metadata is present (even if empty) +- Validating that required organizational fields exist +- Confirming compliance with token structure requirements + +**Behavior:** + +- ✅ **Passes** if the claim exists with any non-null value (including empty strings, arrays, or objects) +- ❌ **Fails** if the claim is missing or explicitly set to `null` + +**Example Configuration:** + +```yaml +customClaimValidation: + department: + type: required + user_metadata: + type: required +``` + +#### Exact Match + +Exact match type validation verifies that a claim's value exactly matches one of the specified allowed values. + +**Use Cases:** + +- Role validation (e.g. `admin`, `editor`, `viewer`) +- Environment-specific access (e.g. `production`, `staging`, `development`) +- Subscription tier validation (e.g. `premium`, `standard`, `basic`) +- Boolean flag validation (`true`, `false`) + +**Behavior:** + +- ✅ Passes if the claim value exactly matches any value in the allowedValues array +- ❌ Fails if the claim value doesn't match any allowed value or if the claim is missing +- Case-sensitive for string comparisons +- Type-sensitive (string "true" ≠ boolean true) + +**Example Configuration:** + +```yaml +customClaimValidation: + role: + type: exact_match + allowedValues: + - admin + - editor + - viewer + subscription_tier: + type: exact_match + allowedValues: + - premium + - standard +``` + +#### Contains + +The Contains type validation checks whether a claim's value contains or includes one of the specified values. This validation type works differently depending on the data type of the claim and is particularly useful for array-based permissions and substring matching. + +**Use Cases:** + +- Permission arrays (`["read:users", "write:posts", "admin:system"]`) +- Tag-based access control +- Partial string matching for departments or locations +- Multi-value scope validation + +**Behavior by Data Type:** + +Arrays: +- ✅ Passes if the array contains any of the specified values +- ❌ Fails if none of the specified values are found in the array + +Strings: +- ✅ Passes if the string contains any of the specified substrings +- ❌ Fails if none of the specified substrings are found + +Other Types: +- Converts to string and performs substring matching + +Example Configuration: + +```yaml +customClaimValidation: + permissions: + type: contains + allowedValues: + - admin:system + - write:api + department_code: + type: contains + allowedValues: + - ENG + - SALES +``` + +With this configuration, a token might contain these claims: + +```json +{ + "permissions": ["read:users", "write:posts", "admin:system"], + "department_code": "ENG-BACKEND", +} +``` + +In this example: +- `permissions` validation passes because the array contains `"admin:system"` +- `department_code` validation passes because the string contains `"ENG"` + +### Data Type Support + +The framework is designed to handle the diverse data types commonly found in JWT tokens. The validation behavior adapts intelligently based on the actual data type of each claim, ensuring robust and predictable validation across different token structures. + +#### Supported Data Types + +##### String Values + +String claims are the most common type in JWT tokens and support all three validation types with intuitive behavior. + +**Validation behavior** + +- **Required**: Passes if the string exists (including empty strings `""`) +- **Exact Match**: Performs case-sensitive string comparison +- **Contains**: Checks if the string contains any of the specified substrings + +**Example** + +Claims: + +```json +{ + "department": "Engineering", + "user_id": "user123", + "email": "john.doe@company.com" +} +``` + +Validation configuration: + +```yaml +customClaimValidation: + department: + type: exact_match + allowedValues: + - Engineering + - Sales + - Marketing + email: + type: contains + allowedValues: + - "@company.com" + - "@partner.com" +``` + +##### Numeric Values + +Numeric claims (integers and floating-point numbers) are validated with type-aware comparison logic. + +**Validation behavior** + +- **Required**: Passes if the number exists (including `0`) +- **Exact Match**: Performs numeric equality comparison (`42` matches `42.0`) +- **Contains**: Converts to string and performs substring matching + +**Example** + +Claims: + +```json +{ + "user_level": 5, + "account_balance": 1250.75, + "login_count": 0 +} +``` + +Validation configuration: + +```yaml +customClaimValidation: + user_level: + type: exact_match + allowedValues: + - 1 + - 2 + - 3 + - 4 + - 5 + account_balance: + type: required +``` + +##### Boolean Values + +Boolean claims are commonly used for feature flags and permission toggles. + +**Validation Behavior** + +- **Required**: Passes if the boolean exists (`true` or `false`) +- **Exact Match**: Performs strict boolean comparison +- **Contains**: Converts to string (`"true"` or `"false"`) and performs substring matching + +**Example** + +Claims: + +```json +{ + "is_admin": true, + "email_verified": false, + "beta_features": true +} +``` + +Validation configuration: + +```yaml +customClaimValidation: + is_admin: + type: exact_match + allowedValues: + - true + email_verified: + type: required +``` + +##### Array Values + +Arrays are particularly powerful for permission systems and multi-value attributes. + +**Validation behavior** + +- **Required**: Passes if the array exists (including empty arrays `[]`) +- **Exact Match**: Checks if the entire array exactly matches one of the allowed arrays +- **Contains**: Checks if the array contains any of the specified values (most common use case) + +**Example** + +Claims: + +```json +{ + "roles": ["user", "editor"], + "permissions": ["read:posts", "write:posts", "delete:own"], + "departments": ["engineering", "product"], + "tags": [] +} +``` + +Validation configuration: + +```yaml +customClaimValidation: + permissions: + type: contains + allowedValues: + - write:posts + - admin:system + roles: + type: contains + allowedValues: + - admin + - editor + - moderator + tags: + type: required +``` + +##### Object Values + +Complex object claims can be validated, though typically you'll want to validate specific nested properties using [dot notation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#nested-claims-dot-notation" >}}). + +**Validation Behavior** + +- **Required**: Passes if the object exists (including empty objects `{}`) +- **Exact Match**: Performs deep object comparison (rarely used) +- **Contains**: Converts to JSON string and performs substring matching + +**Example** + +Claims: + +```json +{ + "user_metadata": { + "department": "Engineering", + "level": 5, + "location": "US" + }, + "preferences": {} +} +``` + +Configuration: + +```yaml +customClaimValidation: + user_metadata: + type: required + preferences: + type: required +``` + +##### Type Coercion and Edge Cases + +**Null and Undefined Values** + +- null values: Always fail validation (treated as missing) +- undefined/missing claims: Fail all validation types except when validation is not configured + +**Mixed-Type Arrays** + +Arrays containing different data types are supported. The `contains` validation will attempt to match values using appropriate type comparison, + +```json +{ + "mixed_permissions": ["read", 42, true, "admin"] +} +``` + +**Type Mismatches** + +When the expected value type doesn't match the claim type, Tyk performs intelligent conversion: + +- Numbers to strings: `42` become `"42"` +- Booleans to strings: `true` becomes "`true"` +- Objects/arrays to strings: Converted to JSON representation + +##### Best Practices + +- Be Explicit About Types: When configuring `allowedValues`, use the same data type as expected in the token +- Use Arrays for Multi-Value Validation: Prefer array-based claims for permissions and roles +- Consider Empty Values: Remember that empty strings, arrays, and objects pass `required` validation +- Test Type Coercion: Verify behavior when token types don't match expected types + +### Nested Claims (Dot Notation) + +JSON Web Tokens often contain complex, hierarchical data structures with nested objects and arrays. Tyk's custom claims validation framework supports dot notation syntax, allowing you to validate specific values deep within nested claim structures without having to validate entire objects. + +**Basic Syntax:** + +- `user.name` - Access the `name` property within the `user` object +- `metadata.department.code` - Access the `code` property within `department` within `metadata` +- `permissions.api.read` - Access the `read` property within `api` within `permissions` + +#### Nested Object Validation + +The most common use case for dot notation is validating properties within nested objects, such as user metadata, organizational information, or configuration settings. + +[OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693#name-act-actor-claim) relies upon nesting for the `act` (actor) claim. + +**Example Token** + +```json +{ + "user": { + "name": "John Doe", + "email": "john.doe@company.com", + "profile": { + "department": "Engineering", + "level": "senior", + "location": { + "country": "US", + "region": "West" + } + } + } +} +``` + +You could set the following configuration to validate the requester's department and level: + +```yaml +{ + "customClaimValidation": { + "user.profile.department": { + "type": "exact_match", + "allowedValues": ["Engineering", "Sales", "Marketing"] + }, + "user.profile.level": { + "type": "contains", + "allowedValues": ["senior", "lead", "principal"] + } + } +} +``` + +### Non-blocking Validation + +The non-blocking validation feature specifically enables a gradual rollout approach to validation rules by allowing you to monitor validation failures without rejecting requests. + +#### How Non-blocking Validation Works + +When configured, a validation rule can be set to "non-blocking" mode, which means: + +1. If validation passes, the request proceeds normally +2. If validation fails, instead of rejecting the request: + - a warning is logged in the gateway [system logs]({{< ref "api-management/logs-metrics#system-logs" >}}) + - the request is allowed to proceed to the upstream API + +This allows you to: + +- Monitor how new validation rules would affect traffic without disrupting users +- Gradually roll out stricter validation requirements +- Debug validation issues in production environments + +#### Configuring Non-Blocking Mode + +Non-blocking mode can be configured for any custom claim validation rule with the addition of the boolean `nonBlocking` flag, for example: + +```yaml +{ + "customClaimValidation": { + "user.profile.department": { + "type": "exact_match", + "allowedValues": ["Engineering", "Sales", "Marketing"] + }, + "user.profile.level": { + "type": "contains", + "allowedValues": ["senior", "lead", "principal"] + }, + "user.preferences.notifications": { + "type": "required", + "nonBlocking": true + } + } +} +``` + +The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. + diff --git a/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md b/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md index fca875342b..696894d728 100644 --- a/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md +++ b/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md @@ -326,899 +326,6 @@ x-tyk-api-gateway: If both `.source` and `.jwksURIs` are configured, the latter will take precedence. {{< /note >}} -## Claim Validation - -JSON Web Tokens contain claims - key-value pairs that provide information about the token and its subject. Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. - -Tyk supports validation of both: - -- **Registered claims**: standardized claims defined in the JWT specification (such as `iss`, `aud`, `exp`) -- **Custom claims**: application-specific claims that contain business logic or additional metadata -By validating JWT claims, you can enforce fine-grained access control policies, ensure tokens originate from trusted sources, and verify that users have the appropriate permissions for your APIs. - -{{< note success >}} -**Note** - -JWT claim validation - with the exception of [temporal claims]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#temporal-claims-exp-iat-nbf" >}}) - is available exclusively for Tyk OAS APIs and from Tyk 5.10.0 onwards. -{{< /note >}} - -### JWT Claims Fundamentals - -#### What are JWT Claims? -A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The payload contains the claims - a set of key-value pairs that carry information about the token and its subject. - -```json -{ - "iss": "https://auth.company.com", - "aud": "api.company.com", - "sub": "user123", - "exp": 1735689600, - "iat": 1735603200, - "department": "engineering", - "role": "admin" -} -``` - -Claims serve different purposes: - -- **Identity information**: who the token represents (`sub`, `iss`) -- **Access control**: what the token can access (`aud`, custom permissions) -- **Validity period**: when the token is valid (`exp`, `iat`, `nbf`) -- **Business logic**: application-specific data (`department`, `role`) - -#### Registered vs Custom Claims - -Registered Claims are standardized by the JWT specification ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1)) and have predefined meanings: - -| Claim | Name | Purpose | -|-------|------------|---------| -| `iss` | Issuer | Identifies who issued the token | -| `aud` | Audience | Identifies who the token is intended for | -| `sub` | Subject | Identifies the subject of the token | -| `exp` | Expiration Time | When the token expires | -| `iat` | Issued At | When the token was issued | -| `nbf` | Not Before | When the token becomes valid | -| `jti` | JWT ID | Unique identifier for the token | - -Custom Claims are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. - -#### How Tyk Processes JWT Claims - -After [verifying]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) that the token hasn't been tampered with, Tyk processes claims in this order: - -- [Registered Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#registered-claims-validation" >}}): Checks standard claims against your configuration -- [Custom Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#custom-claims-validation" >}}): Applies your business rules to custom claims -- [Authorization]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#managing-authorization" >}}): Uses validated claims to determine API access and apply policies - -If any validation step fails, Tyk rejects the request with a specific error message indicating which claim validation failed and why. - -### Registered Claims Validation - -Tyk can validate the seven registered JWT claims defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1). These claims are grouped into **temporal claims** (time-based validation) and **identity claims** (content-based validation). - -#### Temporal Claims (exp, iat, nbf) - -Temporal claims define when a JWT is valid. Tyk automatically validates these claims when present in the token. - -- **Expiration Time (exp)**: the `exp` claim specifies when the token expires (as a Unix timestamp). Tyk rejects tokens where the current time is after the expiration time. -- **Issued At (iat)**: the `iat` claim specifies when the token was issued. Tyk rejects tokens that claim to be issued in the future. -- **Not Before (nbf)**: the `nbf` claim specifies the earliest time the token can be used. Tyk rejects tokens before this time. - -##### Clock Skew Configuration - -Due to the nature of distributed systems, you may encounter clock skew between your Identity Provider and Tyk servers. You can configure tolerance for timing differences: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - issuedAtValidationSkew: 5 # Allow tokens issued up to 5 seconds in the future - notBeforeValidationSkew: 2 # Allow tokens to be valid 2 seconds early - expiresAtValidationSkew: 2 # Allow tokens to be valid 2 seconds past expiration -``` - -- `expiresAtValidationSkew` allows recently expired tokens to be considered valid -- `issuedAtValidationSkew` allows tokens claiming future issuance to be valid -- `notBeforeValidationSkew` allows tokens to be valid before their `nbf` time - -{{< note success >}} -**Note** - -Temporal claim validation and the associated clock skew controls were supported by Tyk prior to 5.10.0 and also for [Tyk Classic APIs]({{< ref "api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis" >}}) -{{< /note >}} - -#### Identity Claims (iss, aud, sub, jti) - -Identity claims provide information about the token's origin and intended use. Unlike temporal claims, these require explicit configuration to enable validation. - -##### Issuer Validation (iss) - -Validates that the token was issued by a trusted Identity Provider: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - allowedIssuers: - - "https://auth.company.com" - - "https://auth.partner.com" -``` - -Tyk accepts tokens if the `iss` claim matches any configured issuer. If `allowedIssuers` is empty, no issuer validation is performed. - -##### Audience Validation (aud) - -Validates that the token is intended for your API: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - allowedAudiences: - - "api.company.com" - - "mobile-app" -``` - -The `aud` claim can be a string or array. Tyk accepts tokens if any audience value matches any configured audience. If `allowedAudiences` is empty, no audience validation is performed. - -##### Subject Validation (sub) - -Validates the token subject against allowed values: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - allowedSubjects: - - "user" - - "service-account" - - "admin" -``` - -Useful for restricting API access to specific types of subjects or known entities. If `allowedSubjects` is empty, no audience validation is performed. - -##### JWT ID Validation (jti) - -Validates that the token contains a unique identifier: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - jtiValidation: - enabled: true -``` - -When enabled, Tyk requires the `jti` claim to be present. This is useful for token tracking and revocation scenarios. Note that Tyk does not perform any validation on the content of the claim, only that it is present. - -#### Configuration Examples - -Basic registered claims validation: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - allowedIssuers: ["https://auth.company.com"] - allowedAudiences: ["api.company.com"] - jtiValidation: - enabled: true - expiresAtValidationSkew: 5 -``` - -Multi-IdP configuration: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - allowedIssuers: - - "https://auth0.company.com" - - "https://keycloak.company.com" - allowedAudiences: - - "api.company.com" - - "mobile.company.com" - subjectClaims: ["sub", "username"] -``` - -In this example we expect one Identity Provider to present the subject in the `sub` claim, and the other to present it in the `username` claim. - -### Custom Claims Validation - -Custom claims validation allows you to enforce business-specific rules on JWT tokens beyond the standard registered claims. You can validate application-specific data such as user roles, departments, permissions, or any other business logic embedded in your JWTs. - -Custom claims are commonly used for such purposes as: - -- **Role-based access control**: Validate that users have required roles (for example `admin`, `editor` ,`viewer`) -- **Department restrictions**: Ensure users belong to authorized departments -- **Feature flags**: Check if users have access to specific features or API endpoints -- **Geographic restrictions**: Validate user location or region-based access -- **Subscription tiers**: Enforce access based on user subscription levels - -Key Benefits of Tyk's comprehensive custom claim validation framework include: - -- **Enhanced Security**: Add additional layers of validation beyond standard JWT verification -- **Business Logic Enforcement**: Implement complex authorization rules at the gateway level -- **Flexible Validation**: Support for multiple validation types and data structures -- **Non-blocking Options**: Configure warnings instead of blocking requests for certain validations -- **Nested Data Support**: Validate complex, nested JSON structures within claims - -#### Validation Types - -Three distinct validation types are supported by the custom claims validation framework, each designed for different use cases and levels of validation strictness. These validation types can be applied to any custom claim in your JWT tokens, providing flexible control over your authorization logic. - -##### Required - -Required type validation ensures that a specific claim exists in the JWT token, regardless of its value. This is the most basic form of validation and is useful when you need to guarantee that certain information is present in tokens. - -**Use Cases:** - -- Ensuring user metadata is present (even if empty) -- Validating that required organizational fields exist -- Confirming compliance with token structure requirements - -**Behavior:** - -- ✅ **Passes** if the claim exists with any non-null value (including empty strings, arrays, or objects) -- ❌ **Fails** if the claim is missing or explicitly set to `null` - -**Example Configuration:** - -```yaml -customClaimValidation: - department: - type: required - user_metadata: - type: required -``` - -##### Exact Match - -Exact match type validation verifies that a claim's value exactly matches one of the specified allowed values. This provides precise control over acceptable claim values and is ideal for role-based access control and categorical validations. - -**Use Cases:** - -- Role validation (e.g. `admin`, `editor`, `viewer`) -- Environment-specific access (e.g. `production`, `staging`, `development`) -- Subscription tier validation (e.g. `premium`, `standard`, `basic`) -- Boolean flag validation (`true`, `false`) - -**Behavior:** - -- ✅ Passes if the claim value exactly matches any value in the allowedValues array -- ❌ Fails if the claim value doesn't match any allowed value or if the claim is missing -- Case-sensitive for string comparisons -- Type-sensitive (string "true" ≠ boolean true) - -**Example Configuration:** - -```yaml -customClaimValidation: - role: - type: exact_match - allowedValues: - - admin - - editor - - viewer - subscription_tier: - type: exact_match - allowedValues: - - premium - - standard -``` - -##### Contains - -The Contains type validation checks whether a claim's value contains or includes one of the specified values. This validation type works differently depending on the data type of the claim and is particularly useful for array-based permissions and substring matching. - -**Use Cases:** - -- Permission arrays (`["read:users", "write:posts", "admin:system"]`) -- Tag-based access control -- Partial string matching for departments or locations -- Multi-value scope validation - -**Behavior by Data Type:** - -Arrays: -- ✅ Passes if the array contains any of the specified values -- ❌ Fails if none of the specified values are found in the array - -Strings: -- ✅ Passes if the string contains any of the specified substrings -- ❌ Fails if none of the specified substrings are found - -Other Types: -- Converts to string and performs substring matching - -Example Configuration: - -```yaml -customClaimValidation: - permissions: - type: contains - allowedValues: - - admin:system - - write:api - department_code: - type: contains - allowedValues: - - ENG - - SALES -``` - -With this configuration, a token might contain these claims: - -```json -{ - "permissions": ["read:users", "write:posts", "admin:system"], - "department_code": "ENG-BACKEND", -} -``` - -In this example: -- `permissions` validation passes because the array contains `"admin:system"` -- `department_code` validation passes because the string contains `"ENG"` - -#### Data Type Support - -The framework is designed to handle the diverse data types commonly found in JWT tokens. The validation behavior adapts intelligently based on the actual data type of each claim, ensuring robust and predictable validation across different token structures. - -##### Supported Data Types - -###### String Values - -String claims are the most common type in JWT tokens and support all three validation types with intuitive behavior. - -**Validation behavior** - -- **Required**: Passes if the string exists (including empty strings `""`) -- **Exact Match**: Performs case-sensitive string comparison -- **Contains**: Checks if the string contains any of the specified substrings - -**Example** - -Claims: - -```json -{ - "department": "Engineering", - "user_id": "user123", - "email": "john.doe@company.com" -} -``` - -Validation configuration: - -```yaml -customClaimValidation: - department: - type: exact_match - allowedValues: - - Engineering - - Sales - - Marketing - email: - type: contains - allowedValues: - - "@company.com" - - "@partner.com" -``` - -###### Numeric Values - -Numeric claims (integers and floating-point numbers) are validated with type-aware comparison logic. - -**Validation behavior** - -- **Required**: Passes if the number exists (including `0`) -- **Exact Match**: Performs numeric equality comparison (`42` matches `42.0`) -- **Contains**: Converts to string and performs substring matching - -**Example** - -Claims: - -```json -{ - "user_level": 5, - "account_balance": 1250.75, - "login_count": 0 -} -``` - -Validation configuration: - -```yaml -customClaimValidation: - user_level: - type: exact_match - allowedValues: - - 1 - - 2 - - 3 - - 4 - - 5 - account_balance: - type: required -``` - -###### Boolean Values - -Boolean claims are commonly used for feature flags and permission toggles. - -**Validation Behavior** - -- **Required**: Passes if the boolean exists (`true` or `false`) -- **Exact Match**: Performs strict boolean comparison -- **Contains**: Converts to string (`"true"` or `"false"`) and performs substring matching - -**Example** - -Claims: - -```json -{ - "is_admin": true, - "email_verified": false, - "beta_features": true -} -``` - -Validation configuration: - -```yaml -customClaimValidation: - is_admin: - type: exact_match - allowedValues: - - true - email_verified: - type: required -``` - -###### Array Values - -Arrays are particularly powerful for permission systems and multi-value attributes. - -**Validation behavior** - -- **Required**: Passes if the array exists (including empty arrays `[]`) -- **Exact Match**: Checks if the entire array exactly matches one of the allowed arrays -- **Contains**: Checks if the array contains any of the specified values (most common use case) - -**Example** - -Claims: - -```json -{ - "roles": ["user", "editor"], - "permissions": ["read:posts", "write:posts", "delete:own"], - "departments": ["engineering", "product"], - "tags": [] -} -``` - -Validation configuration: - -```yaml -customClaimValidation: - permissions: - type: contains - allowedValues: - - write:posts - - admin:system - roles: - type: contains - allowedValues: - - admin - - editor - - moderator - tags: - type: required -``` - -###### Object Values - -Complex object claims can be validated, though typically you'll want to validate specific nested properties using [dot notation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#nested-claims-dot-notation" >}}). - -**Validation Behavior** - -- **Required**: Passes if the object exists (including empty objects `{}`) -- **Exact Match**: Performs deep object comparison (rarely used) -- **Contains**: Converts to JSON string and performs substring matching - -**Example** - -Claims: - -```json -{ - "user_metadata": { - "department": "Engineering", - "level": 5, - "location": "US" - }, - "preferences": {} -} -``` - -Configuration: - -```yaml -customClaimValidation: - user_metadata: - type: required - preferences: - type: required -``` - -###### Type Coercion and Edge Cases - -**Null and Undefined Values** - -- null values: Always fail validation (treated as missing) -- undefined/missing claims: Fail all validation types except when validation is not configured - -**Mixed-Type Arrays** - -Arrays containing different data types are supported. The `contains` validation will attempt to match values using appropriate type comparison, - -```json -{ - "mixed_permissions": ["read", 42, true, "admin"] -} -``` - -**Type Mismatches** - -When the expected value type doesn't match the claim type, Tyk performs intelligent conversion: - -- Numbers to strings: `42` become `"42"` -- Booleans to strings: `true` becomes "`true"` -- Objects/arrays to strings: Converted to JSON representation - -###### Best Practices - -- Be Explicit About Types: When configuring `allowedValues`, use the same data type as expected in the token -- Use Arrays for Multi-Value Validation: Prefer array-based claims for permissions and roles -- Consider Empty Values: Remember that empty strings, arrays, and objects pass `required` validation -- Test Type Coercion: Verify behavior when token types don't match expected types - -#### Nested Claims (Dot Notation) - -JSON Web Tokens often contain complex, hierarchical data structures with nested objects and arrays. Tyk's custom claims validation framework supports dot notation syntax, allowing you to validate specific values deep within nested claim structures without having to validate entire objects. - -Dot notation uses periods (`.`) to traverse nested object properties, similar to JavaScript object property access. This enables precise validation of deeply nested values while maintaining clean, readable configuration. - -**Basic Syntax:** - -- `user.name` - Access the `name` property within the `user` object -- `metadata.department.code` - Access the `code` property within `department` within `metadata` -- `permissions.api.read` - Access the `read` property within `api` within `permissions` - -##### Nested Object Validation - -The most common use case for dot notation is validating properties within nested objects, such as user metadata, organizational information, or configuration settings. - -[OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693#name-act-actor-claim) relies upon nesting for the `act` (actor) claim. - -**Example Token** - -```json -{ - "user": { - "name": "John Doe", - "email": "john.doe@company.com", - "profile": { - "department": "Engineering", - "level": "senior", - "location": { - "country": "US", - "region": "West" - } - } - } -} -``` - -You could set the following configuration to validate the requester's department and level: - -```yaml -{ - "customClaimValidation": { - "user.profile.department": { - "type": "exact_match", - "allowedValues": ["Engineering", "Sales", "Marketing"] - }, - "user.profile.level": { - "type": "contains", - "allowedValues": ["senior", "lead", "principal"] - } - } -} -``` - -#### Non-blocking Validation - -The non-blocking validation feature specifically enables a gradual rollout approach to validation rules by allowing you to monitor validation failures without rejecting requests. - -##### How Non-blocking Validation Works - -When configured, a validation rule can be set to "non-blocking" mode, which means: - -1. If validation passes, the request proceeds normally -2. If validation fails, instead of rejecting the request: - - a warning is logged in the gateway [system logs]({{< ref "api-management/logs-metrics#system-logs" >}}) - - the request is allowed to proceed to the upstream API - -This allows you to: - -- Monitor how new validation rules would affect traffic without disrupting users -- Gradually roll out stricter validation requirements -- Debug validation issues in production environments - -##### Configuring Non-Blocking Mode - -Non-blocking mode can be configured for any custom claim validation rule with the addition of the boolean `nonBlocking` flag, for example: - -```yaml -{ - "customClaimValidation": { - "user.profile.department": { - "type": "exact_match", - "allowedValues": ["Engineering", "Sales", "Marketing"] - }, - "user.profile.level": { - "type": "contains", - "allowedValues": ["senior", "lead", "principal"] - }, - "user.preferences.notifications": { - "type": "required", - "nonBlocking": true - } - } -} -``` - -The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. - -## Managing Authorization - -The claims within the JSON Web Token are used to configure the Authorization for the request - i.e. which resources it can access and what limits should be applied to that access. - -Tyk creates an internal [session object]({{< ref "api-management/policies#what-is-a-session-object" >}}) for the request. The session is used to apply the appropriate security policies to ensure that rate limits, quotas, and access controls specific to the user are correctly applied. The session also enable tracking and analytics for the user's API usage. - -### Identifying the Session Owner - -In order that this session can be correctly associated with the authenticated user, Tyk must extract a unique identity from the token. - -The JWT specification [defines](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2) the optional `sub` claim which identifies the principal that is the subject of the JWT. In OAuth/OIDC contexts this will usually be the end user (resource owner) on whose behalf the token was issued and so is typically used to identify the session owner. - -Tyk provides a flexible approach to identifying the session owner, to account for other use cases where the `sub` field is not supplied or appropriate. The identity is extracted from the token by checking the following fields in order of precedence: - -1. The standard Key ID header (`kid`) in the JWT (unless the `skipKid` option is enabled) -2. The subject identity claim identified by the value(s) stored in `subjectClaims` (which allows API administrators to designate any JWT claim as the identity source (e.g., user_id, email, etc.). -3. The `sub` registered claim - -{{< note success >}} -**Note** - -Prior to Tyk 5.10, the subject identity claim was retrieved from `identityBaseField`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. -{{< /note >}} - -When an identity has been determined, it is stored in the session object in three locations: -- in the `Alias` field -- it is used to generate a hashed session Id stored in the `keyID` field -- in the session metadata as `TykJWTSessionID` - -Note that session objects can be cached to improve performance, so the identity extraction is only performed on the first request with a JWT, or when the cache is refreshed. - -In this example, `skipKid` has been set to `true`, so Tyk checks the `subjectClaims` and determines that the value in the custom claim `user_id` within the JWT should be used as the identity for the session object. - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - skipKid: true - subjectClaims: [user_id] -``` - -### Identifying the Tyk Policies to be applied - -[Security Policies]({{< ref "api-management/policies" >}}) are applied (or mapped) to the session object to configure authorization for the request. Policies must be [registered]({{< ref "api-management/policies#how-you-can-create-policies" >}}) with Tyk, such that they have been allocated a unique *Tyk Policy Id*. - -Tyk supports three different types of policy mapping, which are applied in this priority order: - -1. Direct policy mapping -2. Scope policy mapping -3. Default policy mapping - -Note that, whilst a *default policy* must be configured for each API using JWT Auth, this will only be applied if there are no policies mapped in step 1 or 2. If *scope policies* are activated, these will be applied on top of the previously applied direct policies as explained in more detail in the section on [combining policies]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#combining-policies" >}}). - -#### Direct policies - -You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. - -In this example, Tyk has been configured to check the `pol` claim in the JWT to find the *Policy Ids* for the policies to be applied to the session object: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - basePolicyClaims: [pol] -``` - -In the JWT, you should then provide the list of policy Ids as an array of values in that claim, for example you might declare: - -``` - "pol": ["685a8af28c24bdac0dc21c28", "685bd90b8c24bd4b6d79443d"] -``` - -{{< note success >}} -**Note** - -Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. -{{< /note >}} - -#### Default policies - -You **must** configure one or more *default policies* that will be applied if no specific policies are identified in the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy Ids. - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - defaultPolicies: - - 685a8af28c24bdac0dc21c28 - - 685bd90b8c24bd4b6d79443d -``` - -#### Scope policies - -Directly mapping policies to APIs relies upon the sharing of Tyk Policy Ids with the IdP (so that they can be included in the JWT) and may not provide the flexibility required. Tyk supports a more advanced approach where policies are applied based upon *scopes* declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. - -Within the JWT, you identify a Private Claim that will hold the authorization (or access) scopes for the API. You then provide, within that claim, a list of *scopes*. In your API definition, you configure the `scopes.claims` to instruct Tyk where to look for the scopes and then you declare a mapping of scopes to policies within the `scopes.scopeToPolicyMapping` object. - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - scopes: - scopeToPolicyMapping: - - scope: read:users - policyId: 685bd90b8c24bd4b6d79443d - - scope: write:users - policyId: 685a8af28c24bdac0dc21c28 - claims: [accessScopes] -``` - -In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read:users` or `write:users`. If neither scope is declared in the claim, or the claim is missing, then the default policy will be applied. - -{{< note success >}} -**Note** - -Prior to Tyk 5.10, the authorization scopes claim was retrieved from `scopes.claimName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. -{{< /note >}} - -Multiple scopes can be declared by setting the value of the authorization scopes claim in any of four configurations: - -- a string with space delimited list of values (by standard)
- `"permissions": "read:users write:users"` -- an array of strings
- `"permissions": ["read:users", "write:users"]` -- a string with space delimited list of values inside a nested key
- `"permissions": { "access": "read:users write:users" }` -- an array of strings inside a nested key
- `"permissions": { "access": ["read:users", "write:users"] }` - -If there is a nested key then you must use dot notation in the value configured for `scopes.claims` so, for the first two examples above, `scopes.claims` should be set to `permissions` whilst for the the two nested examples you would use `permissions.access`. - -This example of a fragment of a JWT, if provided to an API with the configuration above, will cause Tyk to apply both policies to the session object: - -```json -{ - "sub": "1234567890", - "name": "Alice Smith", - "accessScopes": ["read:users", "write:users"] -} -``` - -#### Combining policies - -Where multiple policies are mapped to a session (for example, if several scopes are declared in the JWT claim, or if you set multiple *default policies*) Tyk will apply all the matching policies to the request, combining their access rights and using the most permissive rate limits and quotas. It's important when creating those policies to ensure that they do not conflict with each other. - -Policies are combined as follows: - -1. Apply direct mapped policies declared via `basePolicyClaims` -2. Apply scope mapped policies declared in `scopeToPolicyMapping` based upon scopes in the JWT -3. If no policies have been applied in steps 1 or 2, apply the default policies from `defaultPolicies` - -When multiple policies are combined the following logic is applied: - -- **access rights** A user gets access to an endpoint if ANY of the applied policies grant access -- **rate limits** Tyk uses the most permissive values (highest quota, lowest rate limit) -- **other settings** The most permissive settings from any policy are applied - -#### Policy Best Practices - -When creating multiple policies that might be applied to the same JWT, we recommend using [partitioned policies]({{< ref "api-management/policies#partitioned-policies" >}}) - policies that control specific aspects of API access rather than trying to configure everything in a single policy. - -For example: - -- Create one policy that grants read-only access to specific endpoints -- Create another policy that grants write access to different endpoints -- Create a third policy that sets specific rate limits - -To ensure these policies work correctly when combined: - -- Set `per_api` to `true` in each policy. This ensures that the policy's settings only apply to the specific APIs listed in that policy, not to all APIs globally. -- Avoid listing the same `API ID` in multiple policies with conflicting settings. Instead, create distinct policies with complementary settings that can be safely combined. - - -### Session Updates - -When a JWT's claims change (for example, configuring different scopes or policies), Tyk will update the session with the new policies on the next request made with the token. - -### Missing Policies - -If a policy Id is mapped to a session, but there is no policy with that Id, Tyk will fail safe and reject the request returning the `HTTP 403 Forbidden` response with `Key not authorized: no matching policy`. Tyk Gateway will also log the error: `Policy ID found is invalid!`. - -### Using Multiple Identity Providers - -When using multiple Identity Providers, you may need to check different claim locations for the same information. Tyk supports multiple claim locations for the subject identity and policy Ids. - -Prior to Tyk 5.10 and for Tyk Classic APIs, the Gateway could be configured to check single claims for the subject identity, base policy and scope-to-policy mapping. This did not support the scenario where different IdPs used different claims - for example, for the policy mapping, Keycloak uses `scope`, whereas Okta uses `scp`. - -From Tyk 5.10+, Tyk OAS APIs can be configured to check multiple claim names to locate these data in the received token. - -| API Configuration Type | Tyk Version | Subject Identity Locator | Base Policy Locator | Scope-to-Policy Mapping Locator | -|-------------|----------|---|---|---| -| Tyk OAS | pre-5.10 | `identityBaseField` | `policyFieldName` | `scopes.claimName` | -| Tyk OAS | 5.10+ | `subjectClaims` | `basePolicyClaims` | `scopes.claims`| -| Tyk Classic | all | `jwt_identity_base_field` | `jwt_policy_field_name` | `jwt_scope_claim_name` | - -For example: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - # Legacy single field (still supported) - identityBaseField: "sub" - - # New multi-location support (Tyk 5.10+) - subjectClaims: - - "sub" - - "username" - - "user_id" -``` - ## Split Token Flow Split Token Flow addresses a fundamental security concern with JWT tokens: when a JWT is stored on a client device (browser, mobile app, etc.), all of its contents can be easily decoded since JWTs are only base64-encoded, not encrypted. This means sensitive information in the payload is potentially exposed. diff --git a/tyk-docs/data/menu.yaml b/tyk-docs/data/menu.yaml index 7c1a34e2f4..65e0bb7542 100644 --- a/tyk-docs/data/menu.yaml +++ b/tyk-docs/data/menu.yaml @@ -657,9 +657,21 @@ menu: category: Page show: True - title: "JSON Web Tokens" - path: /basic-config-and-security/security/authentication-authorization/json-web-tokens - category: Page + category: Directory show: True + menu: + - title: "Overview" + path: /basic-config-and-security/security/authentication-authorization/json-web-tokens + category: Page + show: True + - title: "Claim Validation" + path: /api-management/authentication/jwt-claim-validation + category: Page + show: True + - title: "Authorization" + path: /api-management/authentication/jwt-authorization + category: Page + show: True - title: "HMAC Signatures" path: /basic-config-and-security/security/authentication-authorization/hmac-signatures category: Page From de109faf06051936af324b13017c2a8c8885f43d Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Tue, 14 Oct 2025 19:31:01 +0530 Subject: [PATCH 02/17] Incorporated Inital Review Change --- .../authentication/jwt-claim-validation.md | 69 ++++++++++++++++--- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index 3a97cbb680..cc482ddeb3 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -28,6 +28,14 @@ JWT claim validation - with the exception of [temporal claims]({{< ref "basic-co ### What are JWT Claims? A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The payload contains the claims - a set of key-value pairs that carry information about the token and its subject. +
+ +{{< note success >}} +**Viewing JWT Claims** + +To inspect the claims in a JWT, use online tools like [jwt.io](https://jwt.io) for quick debugging +{{< /note >}} + ```json { "iss": "https://auth.company.com", @@ -67,9 +75,12 @@ Custom Claims are application-specific and can contain any information relevant After [verifying]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) that the token hasn't been tampered with, Tyk processes claims in this order: -- [Registered Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#registered-claims-validation" >}}): Checks standard claims against your configuration -- [Custom Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#custom-claims-validation" >}}): Applies your business rules to custom claims -- [Authorization]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#managing-authorization" >}}): Uses validated claims to determine API access and apply policies +1. **Claims Extraction**: All claims from the JWT payload are extracted and stored in context variables with the format `jwt_claims_CLAIMNAME`. For example, a claim named `role` becomes accessible as `jwt_claims_role`. + +2. **Claims Validation**: + - [Registered Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#registered-claims-validation" >}}): Checks standard claims against your configuration + - [Custom Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#custom-claims-validation" >}}): Applies your business rules to custom claims + - [Authorization]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#managing-authorization" >}}): Uses validated claims to determine API access and apply policies If any validation step fails, Tyk rejects the request with a specific error message indicating which claim validation failed and why. @@ -164,7 +175,7 @@ x-tyk-api-gateway: - "admin" ``` -Useful for restricting API access to specific types of subjects or known entities. If `allowedSubjects` is empty, no audience validation is performed. +Useful for restricting API access to specific types of subjects or known entities. If `allowedSubjects` is empty, no subject validation is performed. #### JWT ID Validation (jti) @@ -273,7 +284,7 @@ Exact match type validation verifies that a claim's value exactly matches one of **Behavior:** - ✅ Passes if the claim value exactly matches any value in the allowedValues array -- ❌ Fails if the claim value doesn't match any allowed value or if the claim is missing +- ❌ Fails if the claim value doesn't match any allowed value, if the claim is missing, or if allowedValues is empty - Case-sensitive for string comparisons - Type-sensitive (string "true" ≠ boolean true) @@ -582,6 +593,46 @@ JSON Web Tokens often contain complex, hierarchical data structures with nested - `user.name` - Access the `name` property within the `user` object - `metadata.department.code` - Access the `code` property within `department` within `metadata` - `permissions.api.read` - Access the `read` property within `api` within `permissions` +- `permissions.0.resource` - Access the `resource` property of the first element in the `permissions` array + +{{< note success >}} +**Note** + +Array elements can be accessed using numeric indices in dot notation (e.g., `permissions.0.read` for the first element). The index follows the dot notation format rather than bracket notation (`permissions[0]`). +{{< /note >}} + +#### Nested Array Validation + +**Example Token** + +```json +{ + "permissions": [ + { + "resource": "users", + "actions": ["read", "write"] + }, + { + "resource": "reports", + "actions": ["read"] + } + ] +} +``` + +You can validate specific array elements: + +```yaml +customClaimValidation: + "permissions.0.resource": + type: exact_match + allowedValues: ["users"] + "permissions.1.actions.0": + type: exact_match + allowedValues: ["read"] +``` + +This allows for precise validation of specific elements within arrays, while the `contains` validation type remains useful for checking array contents without caring about position. #### Nested Object Validation @@ -635,10 +686,11 @@ When configured, a validation rule can be set to "non-blocking" mode, which mean 1. If validation passes, the request proceeds normally 2. If validation fails, instead of rejecting the request: - - a warning is logged in the gateway [system logs]({{< ref "api-management/logs-metrics#system-logs" >}}) - - the request is allowed to proceed to the upstream API + - A warning is logged to the Tyk Gateway log file at the `WARN` log level + - The validation process continues to evaluate other custom claims + - The request is allowed to proceed to the upstream API -This allows you to: +This behavior allows you to: - Monitor how new validation rules would affect traffic without disrupting users - Gradually roll out stricter validation requirements @@ -668,4 +720,3 @@ Non-blocking mode can be configured for any custom claim validation rule with th ``` The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. - From ace8139eb27c587abba9d9781cd11545a1f1ae7f Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Tue, 14 Oct 2025 20:17:08 +0530 Subject: [PATCH 03/17] Check factual correctness --- .../authentication/jwt-claim-validation.md | 290 +++++++++++------- 1 file changed, 176 insertions(+), 114 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index cc482ddeb3..71802748e8 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -20,7 +20,9 @@ By validating JWT claims, you can enforce fine-grained access control policies, {{< note success >}} **Note** -JWT claim validation - with the exception of [temporal claims]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#temporal-claims-exp-iat-nbf" >}}) - is available exclusively for Tyk OAS APIs and from Tyk 5.10.0 onwards. +JWT claim validation has different support levels across API types: +- **Temporal claims** (`exp`, `iat`, `nbf`): Supported in both Tyk Classic APIs and Tyk OAS APIs +- **All other claims** (identity claims and custom claims): Available exclusively in Tyk OAS APIs from Tyk 5.10.0 onwards {{< /note >}} ## JWT Claims Fundamentals @@ -86,7 +88,9 @@ If any validation step fails, Tyk rejects the request with a specific error mess ## Registered Claims Validation -Tyk can validate the seven registered JWT claims defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1). These claims are grouped into **temporal claims** (time-based validation) and **identity claims** (content-based validation). +Tyk can validate the seven registered JWT claims defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1). These claims are grouped into: +- **Temporal claims** (time-based validation): Supported in both Tyk Classic APIs and OAS APIs +- **Identity claims** (content-based validation): Available only in Tyk OAS APIs ### Temporal Claims (exp, iat, nbf) @@ -263,11 +267,16 @@ Required type validation ensures that a specific claim exists in the JWT token, **Example Configuration:** ```yaml -customClaimValidation: - department: - type: required - user_metadata: - type: required +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + department: + type: required + user_metadata: + type: required ``` #### Exact Match @@ -291,18 +300,23 @@ Exact match type validation verifies that a claim's value exactly matches one of **Example Configuration:** ```yaml -customClaimValidation: - role: - type: exact_match - allowedValues: - - admin - - editor - - viewer - subscription_tier: - type: exact_match - allowedValues: - - premium - - standard +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + role: + type: exact_match + allowedValues: + - admin + - editor + - viewer + subscription_tier: + type: exact_match + allowedValues: + - premium + - standard ``` #### Contains @@ -332,17 +346,22 @@ Other Types: Example Configuration: ```yaml -customClaimValidation: - permissions: - type: contains - allowedValues: - - admin:system - - write:api - department_code: - type: contains - allowedValues: - - ENG - - SALES +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + permissions: + type: contains + allowedValues: + - admin:system + - write:api + department_code: + type: contains + allowedValues: + - ENG + - SALES ``` With this configuration, a token might contain these claims: @@ -389,18 +408,23 @@ Claims: Validation configuration: ```yaml -customClaimValidation: - department: - type: exact_match - allowedValues: - - Engineering - - Sales - - Marketing - email: - type: contains - allowedValues: - - "@company.com" - - "@partner.com" +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + department: + type: exact_match + allowedValues: + - Engineering + - Sales + - Marketing + email: + type: contains + allowedValues: + - "@company.com" + - "@partner.com" ``` ##### Numeric Values @@ -428,17 +452,22 @@ Claims: Validation configuration: ```yaml -customClaimValidation: - user_level: - type: exact_match - allowedValues: - - 1 - - 2 - - 3 - - 4 - - 5 - account_balance: - type: required +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + user_level: + type: exact_match + allowedValues: + - 1 + - 2 + - 3 + - 4 + - 5 + account_balance: + type: required ``` ##### Boolean Values @@ -466,13 +495,18 @@ Claims: Validation configuration: ```yaml -customClaimValidation: - is_admin: - type: exact_match - allowedValues: - - true - email_verified: - type: required +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + is_admin: + type: exact_match + allowedValues: + - true + email_verified: + type: required ``` ##### Array Values @@ -501,20 +535,25 @@ Claims: Validation configuration: ```yaml -customClaimValidation: - permissions: - type: contains - allowedValues: - - write:posts - - admin:system - roles: - type: contains - allowedValues: - - admin - - editor - - moderator - tags: - type: required +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + permissions: + type: contains + allowedValues: + - write:posts + - admin:system + roles: + type: contains + allowedValues: + - admin + - editor + - moderator + tags: + type: required ``` ##### Object Values @@ -545,11 +584,16 @@ Claims: Configuration: ```yaml -customClaimValidation: - user_metadata: - type: required - preferences: - type: required +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + user_metadata: + type: required + preferences: + type: required ``` ##### Type Coercion and Edge Cases @@ -599,6 +643,8 @@ JSON Web Tokens often contain complex, hierarchical data structures with nested **Note** Array elements can be accessed using numeric indices in dot notation (e.g., `permissions.0.read` for the first element). The index follows the dot notation format rather than bracket notation (`permissions[0]`). + +When a nested path doesn't exist (e.g., `user.profile.level` but `profile` doesn't exist) or when an array index is out of bounds (e.g., `permissions.999.resource`), the claim is treated as missing. This will cause validation to fail for blocking rules or generate a warning for non-blocking rules. {{< /note >}} #### Nested Array Validation @@ -623,13 +669,18 @@ Array elements can be accessed using numeric indices in dot notation (e.g., `per You can validate specific array elements: ```yaml -customClaimValidation: - "permissions.0.resource": - type: exact_match - allowedValues: ["users"] - "permissions.1.actions.0": - type: exact_match - allowedValues: ["read"] +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + "permissions.0.resource": + type: exact_match + allowedValues: ["users"] + "permissions.1.actions.0": + type: exact_match + allowedValues: ["read"] ``` This allows for precise validation of specific elements within arrays, while the `contains` validation type remains useful for checking array contents without caring about position. @@ -662,18 +713,24 @@ The most common use case for dot notation is validating properties within nested You could set the following configuration to validate the requester's department and level: ```yaml -{ - "customClaimValidation": { - "user.profile.department": { - "type": "exact_match", - "allowedValues": ["Engineering", "Sales", "Marketing"] - }, - "user.profile.level": { - "type": "contains", - "allowedValues": ["senior", "lead", "principal"] - } - } -} +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + user.profile.department: + type: exact_match + allowedValues: + - Engineering + - Sales + - Marketing + user.profile.level: + type: contains + allowedValues: + - senior + - lead + - principal ``` ### Non-blocking Validation @@ -701,22 +758,27 @@ This behavior allows you to: Non-blocking mode can be configured for any custom claim validation rule with the addition of the boolean `nonBlocking` flag, for example: ```yaml -{ - "customClaimValidation": { - "user.profile.department": { - "type": "exact_match", - "allowedValues": ["Engineering", "Sales", "Marketing"] - }, - "user.profile.level": { - "type": "contains", - "allowedValues": ["senior", "lead", "principal"] - }, - "user.preferences.notifications": { - "type": "required", - "nonBlocking": true - } - } -} +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + user.profile.department: + type: exact_match + allowedValues: + - Engineering + - Sales + - Marketing + user.profile.level: + type: contains + allowedValues: + - senior + - lead + - principal + user.preferences.notifications: + type: required + nonBlocking: true ``` The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. From de3da0ff6737653ad54636a3afa1e9813a839d9e Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Tue, 14 Oct 2025 20:18:19 +0530 Subject: [PATCH 04/17] Grammar Check --- .../authentication/jwt-claim-validation.md | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index 71802748e8..e45023b3f3 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -8,7 +8,7 @@ date: 2025-01-10 ## Introduction -JSON Web Tokens contain claims - key-value pairs that provide information about the token and its subject. Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. +JSON Web Tokens contain claims, which are key-value pairs that provide information about the token and its subject. Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. Tyk supports validation of both: @@ -68,7 +68,7 @@ Registered Claims are standardized by the JWT specification ([RFC 7519](https:// | `sub` | Subject | Identifies the subject of the token | | `exp` | Expiration Time | When the token expires | | `iat` | Issued At | When the token was issued | -| `nbf` | Not Before | When the token becomes valid | +| `nbf` | Not Before | When the token becomes valid | | `jti` | JWT ID | Unique identifier for the token | Custom Claims are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. @@ -94,7 +94,7 @@ Tyk can validate the seven registered JWT claims defined in [RFC 7519](https://d ### Temporal Claims (exp, iat, nbf) -Temporal claims define when a JWT is valid. Tyk automatically validates these claims when present in the token. +Temporal claims define the validity period of a JWT. Tyk automatically validates these claims when present in the token. - **Expiration Time (exp)**: the `exp` claim specifies when the token expires (as a Unix timestamp). Tyk rejects tokens where the current time is after the expiration time. - **Issued At (iat)**: the `iat` claim specifies when the token was issued. Tyk rejects tokens that claim to be issued in the future. @@ -122,7 +122,7 @@ x-tyk-api-gateway: {{< note success >}} **Note** -Temporal claim validation and the associated clock skew controls were supported by Tyk prior to 5.10.0 and also for [Tyk Classic APIs]({{< ref "api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis" >}}) +Temporal claim validation and the associated clock skew controls were supported by Tyk before 5.10.0 and also for [Tyk Classic APIs]({{< ref "api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis" >}}) {{< /note >}} ### Identity Claims (iss, aud, sub, jti) @@ -131,7 +131,7 @@ Identity claims provide information about the token's origin and intended use. U #### Issuer Validation (iss) -Validates that the token was issued by a trusted Identity Provider: +Validates that a trusted Identity Provider issued the token: ```yaml x-tyk-api-gateway: @@ -161,7 +161,7 @@ x-tyk-api-gateway: - "mobile-app" ``` -The `aud` claim can be a string or array. Tyk accepts tokens if any audience value matches any configured audience. If `allowedAudiences` is empty, no audience validation is performed. +The `aud` claim can be a string or an array. Tyk accepts tokens if any audience value matches any configured audience. If `allowedAudiences` is empty, no audience validation is performed. #### Subject Validation (sub) @@ -231,7 +231,7 @@ x-tyk-api-gateway: subjectClaims: ["sub", "username"] ``` -In this example we expect one Identity Provider to present the subject in the `sub` claim, and the other to present it in the `username` claim. +In this example, we expect one Identity Provider to present the subject in the `sub` claim, and the other to present it in the `username` claim. ## Custom Claims Validation @@ -239,7 +239,7 @@ Custom claims validation allows you to enforce business-specific rules on JWT to **Use Cases**: -- **Role-based access control**: Validate that users have required roles (for example `admin`, `editor` ,`viewer`) +- **Role-based access control**: Validate that users have required roles (for example, `admin`, `editor`, `viewer`) - **Department restrictions**: Ensure users belong to authorized departments - **Feature flags**: Check if users have access to specific features or API endpoints - **Geographic restrictions**: Validate user location or region-based access @@ -247,7 +247,7 @@ Custom claims validation allows you to enforce business-specific rules on JWT to ### Validation Types -Three distinct validation types are supported by the custom claims validation. These validation types can be applied to any custom claim in your JWT tokens, providing flexible control over your authorization logic. +The custom claims validation supports three distinct validation types. These validation types can be applied to any custom claim in your JWT tokens, providing flexible control over your authorization logic. #### Required @@ -285,9 +285,9 @@ Exact match type validation verifies that a claim's value exactly matches one of **Use Cases:** -- Role validation (e.g. `admin`, `editor`, `viewer`) -- Environment-specific access (e.g. `production`, `staging`, `development`) -- Subscription tier validation (e.g. `premium`, `standard`, `basic`) +- Role validation (e.g., `admin`, `editor`, `viewer`) +- Environment-specific access (e.g., `production`, `staging`, `development`) +- Subscription tier validation (e.g., `premium`, `standard`, `basic`) - Boolean flag validation (`true`, `false`) **Behavior:** @@ -325,7 +325,7 @@ The Contains type validation checks whether a claim's value contains or includes **Use Cases:** -- Permission arrays (`["read:users", "write:posts", "admin:system"]`) +- Permission arrays (`["read: users", "write: posts", "admin: system"]`) - Tag-based access control - Partial string matching for departments or locations - Multi-value scope validation @@ -341,7 +341,7 @@ Strings: - ❌ Fails if none of the specified substrings are found Other Types: -- Converts to string and performs substring matching +- Converts to a string and performs substring matching Example Configuration: @@ -355,7 +355,7 @@ x-tyk-api-gateway: permissions: type: contains allowedValues: - - admin:system + - admin: system - write:api department_code: type: contains @@ -368,13 +368,13 @@ With this configuration, a token might contain these claims: ```json { - "permissions": ["read:users", "write:posts", "admin:system"], + "permissions": ["read: users", "write: posts", "admin: system"], "department_code": "ENG-BACKEND", } ``` In this example: -- `permissions` validation passes because the array contains `"admin:system"` +- `permissions` validation passes because the array contains `"admin: system"` - `department_code` validation passes because the string contains `"ENG"` ### Data Type Support @@ -435,7 +435,7 @@ Numeric claims (integers and floating-point numbers) are validated with type-awa - **Required**: Passes if the number exists (including `0`) - **Exact Match**: Performs numeric equality comparison (`42` matches `42.0`) -- **Contains**: Converts to string and performs substring matching +- **Contains**: Converts to a string and performs substring matching **Example** @@ -526,7 +526,7 @@ Claims: ```json { "roles": ["user", "editor"], - "permissions": ["read:posts", "write:posts", "delete:own"], + "permissions": ["read: posts", "write: posts", "delete: own"], "departments": ["engineering", "product"], "tags": [] } @@ -544,8 +544,8 @@ x-tyk-api-gateway: permissions: type: contains allowedValues: - - write:posts - - admin:system + - write: posts + - admin: system roles: type: contains allowedValues: @@ -564,7 +564,7 @@ Complex object claims can be validated, though typically you'll want to validate - **Required**: Passes if the object exists (including empty objects `{}`) - **Exact Match**: Performs deep object comparison (rarely used) -- **Contains**: Converts to JSON string and performs substring matching +- **Contains**: Converts to a JSON string and performs substring matching **Example** @@ -617,7 +617,7 @@ Arrays containing different data types are supported. The `contains` validation When the expected value type doesn't match the claim type, Tyk performs intelligent conversion: -- Numbers to strings: `42` become `"42"` +- Numbers to strings: `42` becomes `"42"` - Booleans to strings: `true` becomes "`true"` - Objects/arrays to strings: Converted to JSON representation @@ -637,7 +637,7 @@ JSON Web Tokens often contain complex, hierarchical data structures with nested - `user.name` - Access the `name` property within the `user` object - `metadata.department.code` - Access the `code` property within `department` within `metadata` - `permissions.api.read` - Access the `read` property within `api` within `permissions` -- `permissions.0.resource` - Access the `resource` property of the first element in the `permissions` array +- `permissions 0.resource` - Access the `resource` property of the first element in the `permissions` array {{< note success >}} **Note** @@ -735,7 +735,7 @@ x-tyk-api-gateway: ### Non-blocking Validation -The non-blocking validation feature specifically enables a gradual rollout approach to validation rules by allowing you to monitor validation failures without rejecting requests. +The non-blocking validation feature enables a gradual rollout approach to validation rules, allowing you to monitor validation failures without rejecting requests. #### How Non-blocking Validation Works @@ -782,3 +782,4 @@ x-tyk-api-gateway: ``` The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. + From bb3549042e059f6ef53fdb3e5baff51ad7f6f077 Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Wed, 15 Oct 2025 12:12:04 +0530 Subject: [PATCH 05/17] Fixes --- .../authentication/jwt-claim-validation.md | 212 +++++++++--------- 1 file changed, 111 insertions(+), 101 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index e45023b3f3..6e4ba38bfd 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -6,72 +6,81 @@ keywords: ["Authentication", "JWT", "JSON Web Tokens", "Claims", "Validation"] date: 2025-01-10 --- -## Introduction +## Availability + +| Component | Editions | +|-------------| ------------------------- | +| Tyk Gateway | Community and Enterprise | -JSON Web Tokens contain claims, which are key-value pairs that provide information about the token and its subject. Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. +## Introduction -Tyk supports validation of both: +A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The payload contains the claims, a set of key-value pairs that carry information about the token and its subject. -- **Registered claims**: standardized claims defined in the JWT specification (such as `iss`, `aud`, `exp`) -- **Custom claims**: application-specific claims that contain business logic or additional metadata +Tyk can validate these claims to ensure that incoming JWTs meet your security requirements before granting access to your APIs. By validating JWT claims, you can enforce fine-grained access control policies, ensure tokens originate from trusted sources, and verify that users have the appropriate permissions for your APIs. {{< note success >}} -**Note** +**Viewing JWT Claims** -JWT claim validation has different support levels across API types: -- **Temporal claims** (`exp`, `iat`, `nbf`): Supported in both Tyk Classic APIs and Tyk OAS APIs -- **All other claims** (identity claims and custom claims): Available exclusively in Tyk OAS APIs from Tyk 5.10.0 onwards +To inspect the claims in a JWT, use online tools like [jwt.io](https://jwt.io) for quick debugging {{< /note >}} + + ## JWT Claims Fundamentals -### What are JWT Claims? -A JSON Web Token consists of three parts separated by dots: `header.payload.signature`. The payload contains the claims - a set of key-value pairs that carry information about the token and its subject. +### Registered vs Custom Claims -
+JWT claims can be categorized into two types: -{{< note success >}} -**Viewing JWT Claims** +- **Registered Claims**: -To inspect the claims in a JWT, use online tools like [jwt.io](https://jwt.io) for quick debugging -{{< /note >}} + Registered Claims are standardized by the JWT specification ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1)) and have predefined meanings. + + These claims are further grouped into: + + - **Temporal Claims:** time-based validation + - **Identity Claims:** content-based validation + + | Claim | Name | Purpose | Type | + | ----- | --------------- | ---------------------------------------- | -------- | + | `iss` | Issuer | Identifies who issued the token | Identity | + | `aud` | Audience | Identifies who the token is intended for | Identity | + | `sub` | Subject | Identifies the subject of the token | Identity | + | `exp` | Expiration Time | When the token expires | Temporal | + | `iat` | Issued At | When the token was issued | Temporal | + | `nbf` | Not Before | When the token becomes valid | Temporal | + | `jti` | JWT ID | Unique identifier for the token | Identity | + +- **Custom Claims**: + + Custom Claims are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. + +**Example JWT Payload with Both Registered and Custom Claims**: ```json { + // Registered claims "iss": "https://auth.company.com", "aud": "api.company.com", "sub": "user123", "exp": 1735689600, "iat": 1735603200, + + // Custom claims "department": "engineering", "role": "admin" } ``` -Claims serve different purposes: - -- **Identity information**: who the token represents (`sub`, `iss`) -- **Access control**: what the token can access (`aud`, custom permissions) -- **Validity period**: when the token is valid (`exp`, `iat`, `nbf`) -- **Business logic**: application-specific data (`department`, `role`) - -### Registered vs Custom Claims - -Registered Claims are standardized by the JWT specification ([RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1)) and have predefined meanings: +### Supported Claims and API Types -| Claim | Name | Purpose | -|-------|------------|---------| -| `iss` | Issuer | Identifies who issued the token | -| `aud` | Audience | Identifies who the token is intended for | -| `sub` | Subject | Identifies the subject of the token | -| `exp` | Expiration Time | When the token expires | -| `iat` | Issued At | When the token was issued | -| `nbf` | Not Before | When the token becomes valid | -| `jti` | JWT ID | Unique identifier for the token | - -Custom Claims are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. +| Claim Category | Sub-Category | Tyk OAS APIs | Tyk Classic APIs | Version | +| --------------------- | ----------------------------------------- | ------------------------- | ----------------------------- | ------------------ | +| **Registered Claims** | **Temporal** (`exp`, `iat`, `nbf`) | ✅ Yes | ✅ Yes | All versions | +| **Registered Claims** | **Identity** (`iss`, `aud`, `sub`, `jti`) | ✅ Yes | ❌ Yes | 5.10+ | +| **Custom Claims** | — | ✅ Yes | ❌ No | 5.10+ | ### How Tyk Processes JWT Claims @@ -88,11 +97,11 @@ If any validation step fails, Tyk rejects the request with a specific error mess ## Registered Claims Validation -Tyk can validate the seven registered JWT claims defined in [RFC 7519](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1). These claims are grouped into: +[Registered Claims]({{< ref "#registered-vs-custom-claims" >}}) are grouped into: - **Temporal claims** (time-based validation): Supported in both Tyk Classic APIs and OAS APIs - **Identity claims** (content-based validation): Available only in Tyk OAS APIs -### Temporal Claims (exp, iat, nbf) +### Temporal Claims Temporal claims define the validity period of a JWT. Tyk automatically validates these claims when present in the token. @@ -125,7 +134,7 @@ x-tyk-api-gateway: Temporal claim validation and the associated clock skew controls were supported by Tyk before 5.10.0 and also for [Tyk Classic APIs]({{< ref "api-management/gateway-config-tyk-classic#configuring-authentication-for-tyk-classic-apis" >}}) {{< /note >}} -### Identity Claims (iss, aud, sub, jti) +### Identity Claims Identity claims provide information about the token's origin and intended use. Unlike temporal claims, these require explicit configuration to enable validation. @@ -628,69 +637,26 @@ When the expected value type doesn't match the claim type, Tyk performs intellig - Consider Empty Values: Remember that empty strings, arrays, and objects pass `required` validation - Test Type Coercion: Verify behavior when token types don't match expected types -### Nested Claims (Dot Notation) +### Nested Claims -JSON Web Tokens often contain complex, hierarchical data structures with nested objects and arrays. Tyk's custom claims validation framework supports dot notation syntax, allowing you to validate specific values deep within nested claim structures without having to validate entire objects. +JSON Web Tokens often contain complex, hierarchical data structures with nested objects and arrays. Tyk's custom claims validation framework supports validating nested claim structures using dot notation syntax. **Basic Syntax:** - `user.name` - Access the `name` property within the `user` object -- `metadata.department.code` - Access the `code` property within `department` within `metadata` -- `permissions.api.read` - Access the `read` property within `api` within `permissions` -- `permissions 0.resource` - Access the `resource` property of the first element in the `permissions` array +- `permissions.0.resource` - Access the `resource` property of the first element in the `permissions` array {{< note success >}} -**Note** +**Dot Notation** -Array elements can be accessed using numeric indices in dot notation (e.g., `permissions.0.read` for the first element). The index follows the dot notation format rather than bracket notation (`permissions[0]`). +Tyk uses [gjson](https://github.com/tidwall/gjson) to parse dot notation paths. -When a nested path doesn't exist (e.g., `user.profile.level` but `profile` doesn't exist) or when an array index is out of bounds (e.g., `permissions.999.resource`), the claim is treated as missing. This will cause validation to fail for blocking rules or generate a warning for non-blocking rules. {{< /note >}} -#### Nested Array Validation - -**Example Token** - -```json -{ - "permissions": [ - { - "resource": "users", - "actions": ["read", "write"] - }, - { - "resource": "reports", - "actions": ["read"] - } - ] -} -``` - -You can validate specific array elements: - -```yaml -x-tyk-api-gateway: - server: - authentication: - securitySchemes: - jwtAuth: - customClaimValidation: - "permissions.0.resource": - type: exact_match - allowedValues: ["users"] - "permissions.1.actions.0": - type: exact_match - allowedValues: ["read"] -``` - -This allows for precise validation of specific elements within arrays, while the `contains` validation type remains useful for checking array contents without caring about position. - #### Nested Object Validation The most common use case for dot notation is validating properties within nested objects, such as user metadata, organizational information, or configuration settings. -[OAuth 2.0 Token Exchange](https://datatracker.ietf.org/doc/html/rfc8693#name-act-actor-claim) relies upon nesting for the `act` (actor) claim. - **Example Token** ```json @@ -733,9 +699,65 @@ x-tyk-api-gateway: - principal ``` + +#### Nested Array Validation + +Arrays are commonly used in JWT claims to represent lists of permissions, roles, or other multi-value attributes. Tyk supports validating specific elements within arrays using dot notation with numeric indices. + +**Example Token** + +```json +{ + "permissions": [ + { + "resource": "users", + "actions": ["read", "write"] + }, + { + "resource": "reports", + "actions": ["read"] + } + ] +} +``` + +You can validate specific array elements: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + customClaimValidation: + "permissions.0.resource": + type: exact_match + allowedValues: ["users"] + "permissions.1.actions.0": + type: exact_match + allowedValues: ["read"] +``` + +{{< note warning >}} +**Dot Notation** + +When a nested path doesn't exist (e.g., `user.profile.level` but `profile` doesn't exist) or when an array index is out of bounds (e.g., `permissions.999.resource`), the claim is treated as missing. This will cause validation to fail for blocking rules or generate a warning for non-blocking rules. + +{{< /note >}} + +#### Recommendations + +Test your nested claim validation rules with representative JWT tokens to ensure they behave as expected. Use online tools like [gjson.dev](https://gjson.dev/) to experiment with dot notation paths and verify they correctly access the desired values. + ### Non-blocking Validation -The non-blocking validation feature enables a gradual rollout approach to validation rules, allowing you to monitor validation failures without rejecting requests. +Non-blocking validation allows JWT claims to fail validation with a warning logged but still permits the request to proceed, enabling gradual rollout of validation rules by monitoring before enforcing. + +This behavior allows you to: + +- Monitor how new validation rules would affect traffic without disrupting users +- Gradually roll out stricter validation requirements +- Debug validation issues in production environments #### How Non-blocking Validation Works @@ -747,12 +769,6 @@ When configured, a validation rule can be set to "non-blocking" mode, which mean - The validation process continues to evaluate other custom claims - The request is allowed to proceed to the upstream API -This behavior allows you to: - -- Monitor how new validation rules would affect traffic without disrupting users -- Gradually roll out stricter validation requirements -- Debug validation issues in production environments - #### Configuring Non-Blocking Mode Non-blocking mode can be configured for any custom claim validation rule with the addition of the boolean `nonBlocking` flag, for example: @@ -770,12 +786,6 @@ x-tyk-api-gateway: - Engineering - Sales - Marketing - user.profile.level: - type: contains - allowedValues: - - senior - - lead - - principal user.preferences.notifications: type: required nonBlocking: true From 959be3522976a8c19d41e378e01c24463f34398a Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Wed, 15 Oct 2025 12:12:59 +0530 Subject: [PATCH 06/17] Fixes --- .../api-management/authentication/jwt-claim-validation.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index 6e4ba38bfd..642e3cd356 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -751,7 +751,7 @@ Test your nested claim validation rules with representative JWT tokens to ensure ### Non-blocking Validation -Non-blocking validation allows JWT claims to fail validation with a warning logged but still permits the request to proceed, enabling gradual rollout of validation rules by monitoring before enforcing. +Non-blocking validation allows JWT claims to fail validation with a warning logged, while still permitting the request to proceed. This behavior allows you to: @@ -791,5 +791,4 @@ x-tyk-api-gateway: nonBlocking: true ``` -The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. - +The `nonBlocking` flag in the validation rule for `user.preferences.notifications` means that if this claim is missing from the received token, the token will not fail validation, but a warning will be logged. \ No newline at end of file From 97ac335d5264604fa29416200a4f2918750c539c Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Wed, 15 Oct 2025 16:47:25 +0530 Subject: [PATCH 07/17] JWT Auth --- .../authentication/jwt-authorization.md | 252 ++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 tyk-docs/content/api-management/authentication/jwt-authorization.md diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md new file mode 100644 index 0000000000..07f388cc83 --- /dev/null +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -0,0 +1,252 @@ +--- +title: JWT Authorization +description: How to implement JWT authorization in Tyk API Gateway. +tags: ["Authentication", "Authorization", "JWT", "JSON Web Tokens", "Claims", "Validation"] +keywords: ["Authentication", "Authorization", "JWT", "JSON Web Tokens", "Claims", "Validation"] +date: 2025-01-10 +--- + +## Introduction + +JSON Web Token claims are used to configure the Authorization for the request. + +Tyk creates an internal [session object]({{< ref "api-management/policies#what-is-a-session-object" >}}) for the request. The session is used to apply the appropriate security policies to ensure that rate limits, quotas, and access controls specific to the user are correctly applied. The session also enable tracking and analytics for the user's API usage. + +## JWT Authorization Flow + +When a request with a JWT token arrives at Tyk, the following process occurs: + +1. **Token Extraction**: Token is extracted from the request. + +2. **Token Validation**: The token's signature is verified using the configured signing method. + +3. **Claims Validation**: Token claims are validated as per the configuration. + +4. **Identity Extraction**: The user identity is extracted from the token, using one of: + - The `kid` header (unless `skipKid` is enabled) + - A custom claim specified in `identityBaseField` + - The standard `sub` claim as fallback + +5. **Policy Resolution**: Tyk determines which policy to apply to the request: + - From a claim specified in `policyFieldName` + - From a client ID in `clientBaseField` + - From scope-to-policy mapping + - From default policies + +6. **Session Creation**: A session is created or updated with the resolved policies, which determines access rights, rate limits, and quotas. + +## Identifying the Session Owner + +In order that this session can be correctly associated with the authenticated user, Tyk must extract a unique identity from the token. + +The JWT specification [defines](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2) the optional `sub` claim which identifies the principal that is the subject of the JWT. In OAuth/OIDC contexts this will usually be the end user (resource owner) on whose behalf the token was issued and so is typically used to identify the session owner. + +Tyk provides a flexible approach to identifying the session owner, to account for other use cases where the `sub` field is not supplied or appropriate. The identity is extracted from the token by checking the following fields in order of precedence: + +1. The standard Key ID header (`kid`) in the JWT (unless the `skipKid` option is enabled) +2. The subject identity claim identified by the value(s) stored in `subjectClaims` (which allows API administrators to designate any JWT claim as the identity source (e.g., user_id, email, etc.). +3. The `sub` registered claim + +{{< note success >}} +**Note** + +Prior to Tyk 5.10, the subject identity claim was retrieved from `identityBaseField`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. +{{< /note >}} + +When an identity has been determined, it is stored in the session object in three locations: +- in the `Alias` field +- it is used to generate a hashed session Id stored in the `keyID` field +- in the session metadata as `TykJWTSessionID` + +Note that session objects can be cached to improve performance, so the identity extraction is only performed on the first request with a JWT, or when the cache is refreshed. + +In this example, `skipKid` has been set to `true`, so Tyk checks the `subjectClaims` and determines that the value in the custom claim `user_id` within the JWT should be used as the identity for the session object. + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + skipKid: true + subjectClaims: [user_id] +``` + +## Identifying the Tyk Policies to be applied + +[Security Policies]({{< ref "api-management/policies" >}}) are applied (or mapped) to the session object to configure authorization for the request. Policies must be [registered]({{< ref "api-management/policies#how-you-can-create-policies" >}}) with Tyk, such that they have been allocated a unique *Tyk Policy Id*. + +Tyk supports three different types of policy mapping, which are applied in this priority order: + +1. Direct policy mapping +2. Scope policy mapping +3. Default policy mapping + +Note that, whilst a *default policy* must be configured for each API using JWT Auth, this will only be applied if there are no policies mapped in step 1 or 2. If *scope policies* are activated, these will be applied on top of the previously applied direct policies as explained in more detail in the section on [combining policies]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#combining-policies" >}}). + +### Direct policies + +You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. + +In this example, Tyk has been configured to check the `pol` claim in the JWT to find the *Policy Ids* for the policies to be applied to the session object: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + basePolicyClaims: [pol] +``` + +In the JWT, you should then provide the list of policy Ids as an array of values in that claim, for example you might declare: + +``` + "pol": ["685a8af28c24bdac0dc21c28", "685bd90b8c24bd4b6d79443d"] +``` + +{{< note success >}} +**Note** + +Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. +{{< /note >}} + +### Default policies + +You **must** configure one or more *default policies* that will be applied if no specific policies are identified in the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy Ids. + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + defaultPolicies: + - 685a8af28c24bdac0dc21c28 + - 685bd90b8c24bd4b6d79443d +``` + +### Scope policies + +Directly mapping policies to APIs relies upon the sharing of Tyk Policy Ids with the IdP (so that they can be included in the JWT) and may not provide the flexibility required. Tyk supports a more advanced approach where policies are applied based upon *scopes* declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. + +Within the JWT, you identify a Private Claim that will hold the authorization (or access) scopes for the API. You then provide, within that claim, a list of *scopes*. In your API definition, you configure the `scopes.claims` to instruct Tyk where to look for the scopes and then you declare a mapping of scopes to policies within the `scopes.scopeToPolicyMapping` object. + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + scopes: + scopeToPolicyMapping: + - scope: read:users + policyId: 685bd90b8c24bd4b6d79443d + - scope: write:users + policyId: 685a8af28c24bdac0dc21c28 + claims: [accessScopes] +``` + +In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read:users` or `write:users`. If neither scope is declared in the claim, or the claim is missing, then the default policy will be applied. + +{{< note success >}} +**Note** + +Prior to Tyk 5.10, the authorization scopes claim was retrieved from `scopes.claimName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. +{{< /note >}} + +Multiple scopes can be declared by setting the value of the authorization scopes claim in any of four configurations: + +- a string with space delimited list of values (by standard)
+ `"permissions": "read:users write:users"` +- an array of strings
+ `"permissions": ["read:users", "write:users"]` +- a string with space delimited list of values inside a nested key
+ `"permissions": { "access": "read:users write:users" }` +- an array of strings inside a nested key
+ `"permissions": { "access": ["read:users", "write:users"] }` + +If there is a nested key then you must use dot notation in the value configured for `scopes.claims` so, for the first two examples above, `scopes.claims` should be set to `permissions` whilst for the the two nested examples you would use `permissions.access`. + +This example of a fragment of a JWT, if provided to an API with the configuration above, will cause Tyk to apply both policies to the session object: + +```json +{ + "sub": "1234567890", + "name": "Alice Smith", + "accessScopes": ["read:users", "write:users"] +} +``` + +### Combining policies + +Where multiple policies are mapped to a session (for example, if several scopes are declared in the JWT claim, or if you set multiple *default policies*) Tyk will apply all the matching policies to the request, combining their access rights and using the most permissive rate limits and quotas. It's important when creating those policies to ensure that they do not conflict with each other. + +Policies are combined as follows: + +1. Apply direct mapped policies declared via `basePolicyClaims` +2. Apply scope mapped policies declared in `scopeToPolicyMapping` based upon scopes in the JWT +3. If no policies have been applied in steps 1 or 2, apply the default policies from `defaultPolicies` + +When multiple policies are combined the following logic is applied: + +- **access rights** A user gets access to an endpoint if ANY of the applied policies grant access +- **rate limits** Tyk uses the most permissive values (highest quota, lowest rate limit) +- **other settings** The most permissive settings from any policy are applied + +### Policy Best Practices + +When creating multiple policies that might be applied to the same JWT, we recommend using [partitioned policies]({{< ref "api-management/policies#partitioned-policies" >}}) - policies that control specific aspects of API access rather than trying to configure everything in a single policy. + +For example: + +- Create one policy that grants read-only access to specific endpoints +- Create another policy that grants write access to different endpoints +- Create a third policy that sets specific rate limits + +To ensure these policies work correctly when combined: + +- Set `per_api` to `true` in each policy. This ensures that the policy's settings only apply to the specific APIs listed in that policy, not to all APIs globally. +- Avoid listing the same `API ID` in multiple policies with conflicting settings. Instead, create distinct policies with complementary settings that can be safely combined. + + +## Session Updates + +When a JWT's claims change (for example, configuring different scopes or policies), Tyk will update the session with the new policies on the next request made with the token. + +## Missing Policies + +If a policy Id is mapped to a session, but there is no policy with that Id, Tyk will fail safe and reject the request returning the `HTTP 403 Forbidden` response with `Key not authorized: no matching policy`. Tyk Gateway will also log the error: `Policy ID found is invalid!`. + +## Using Multiple Identity Providers + +When using multiple Identity Providers, you may need to check different claim locations for the same information. Tyk supports multiple claim locations for the subject identity and policy Ids. + +Prior to Tyk 5.10 and for Tyk Classic APIs, the Gateway could be configured to check single claims for the subject identity, base policy and scope-to-policy mapping. This did not support the scenario where different IdPs used different claims - for example, for the policy mapping, Keycloak uses `scope`, whereas Okta uses `scp`. + +From Tyk 5.10+, Tyk OAS APIs can be configured to check multiple claim names to locate these data in the received token. + +| API Configuration Type | Tyk Version | Subject Identity Locator | Base Policy Locator | Scope-to-Policy Mapping Locator | +|-------------|----------|---|---|---| +| Tyk OAS | pre-5.10 | `identityBaseField` | `policyFieldName` | `scopes.claimName` | +| Tyk OAS | 5.10+ | `subjectClaims` | `basePolicyClaims` | `scopes.claims`| +| Tyk Classic | all | `jwt_identity_base_field` | `jwt_policy_field_name` | `jwt_scope_claim_name` | + +For example: + +```yaml +x-tyk-api-gateway: + server: + authentication: + securitySchemes: + jwtAuth: + # Legacy single field (still supported) + identityBaseField: "sub" + + # New multi-location support (Tyk 5.10+) + subjectClaims: + - "sub" + - "username" + - "user_id" +``` + From 2b8a61050c79bfd965264d342b1f87c50adbcf69 Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Thu, 16 Oct 2025 16:11:49 +0530 Subject: [PATCH 08/17] Added JWT Auth --- .../authentication/jwt-authorization.md | 189 ++++++++++++------ 1 file changed, 132 insertions(+), 57 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index 07f388cc83..66d74a9d09 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -1,6 +1,6 @@ --- title: JWT Authorization -description: How to implement JWT authorization in Tyk API Gateway. +description: How JWT authorization works in Tyk API Gateway. tags: ["Authentication", "Authorization", "JWT", "JSON Web Tokens", "Claims", "Validation"] keywords: ["Authentication", "Authorization", "JWT", "JSON Web Tokens", "Claims", "Validation"] date: 2025-01-10 @@ -8,57 +8,54 @@ date: 2025-01-10 ## Introduction -JSON Web Token claims are used to configure the Authorization for the request. +[JSON Web Tokens (JWT)]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens" >}}) is a popular method for authentication and authorization. -Tyk creates an internal [session object]({{< ref "api-management/policies#what-is-a-session-object" >}}) for the request. The session is used to apply the appropriate security policies to ensure that rate limits, quotas, and access controls specific to the user are correctly applied. The session also enable tracking and analytics for the user's API usage. +In Tyk, after a JWT has been validated during the [authentication]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) step, Tyk uses the claims within the token to determine what security policies (access rights, rate limits and quotas) should be applied to the request. -## JWT Authorization Flow - -When a request with a JWT token arrives at Tyk, the following process occurs: +In this page, we explain how Tyk performs JWT authorization, including how it identifies the user and the policies to be applied. -1. **Token Extraction**: Token is extracted from the request. - -2. **Token Validation**: The token's signature is verified using the configured signing method. +## JWT Authorization Flow -3. **Claims Validation**: Token claims are validated as per the configuration. +When a request with a JWT token arrives at Tyk Gateway, after the authentication (token and claim validation) step, Tyk performs the following steps to authorize the request: -4. **Identity Extraction**: The user identity is extracted from the token, using one of: +1. **Identity Extraction**: The user identity is extracted from the token, using one of: - The `kid` header (unless `skipKid` is enabled) - - A custom claim specified in `identityBaseField` + - A custom claim specified in `subjectClaims` - The standard `sub` claim as fallback -5. **Policy Resolution**: Tyk determines which policy to apply to the request: - - From a claim specified in `policyFieldName` - - From a client ID in `clientBaseField` +2. **Policy Resolution**: Tyk determines which policy to apply to the request: - From scope-to-policy mapping - From default policies -6. **Session Creation**: A session is created or updated with the resolved policies, which determines access rights, rate limits, and quotas. +3. **Update Session**: The session is updated with unique identify and policies (determines access rights, rate limits, and quotas). -## Identifying the Session Owner - -In order that this session can be correctly associated with the authenticated user, Tyk must extract a unique identity from the token. +In the following sections, we explain each of these steps in more detail. -The JWT specification [defines](https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.2) the optional `sub` claim which identifies the principal that is the subject of the JWT. In OAuth/OIDC contexts this will usually be the end user (resource owner) on whose behalf the token was issued and so is typically used to identify the session owner. +## Identifying the Session Owner -Tyk provides a flexible approach to identifying the session owner, to account for other use cases where the `sub` field is not supplied or appropriate. The identity is extracted from the token by checking the following fields in order of precedence: +To associate a session with the authenticated user, Tyk Gateway extracts the unique identity from the JWT token by checking the following fields in order of precedence: 1. The standard Key ID header (`kid`) in the JWT (unless the `skipKid` option is enabled) 2. The subject identity claim identified by the value(s) stored in `subjectClaims` (which allows API administrators to designate any JWT claim as the identity source (e.g., user_id, email, etc.). -3. The `sub` registered claim -{{< note success >}} + When multiple values are provided in the `subjectClaims` array, Tyk processes them as follows: + + 1. Tyk tries each claim **in the exact order they appear** in the array + 2. For each claim, Tyk checks if: + - The claim exists in the token + - The claim value is a string and is not empty + 3. Tyk uses the **first valid, non-empty value** it finds and stops processing further claims + 4. If none of the claims yield a valid identity, Tyk proceeds to check the `sub` claim as a fallback + + {{< note success >}} **Note** Prior to Tyk 5.10, the subject identity claim was retrieved from `identityBaseField`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. -{{< /note >}} + {{< /note >}} -When an identity has been determined, it is stored in the session object in three locations: -- in the `Alias` field -- it is used to generate a hashed session Id stored in the `keyID` field -- in the session metadata as `TykJWTSessionID` +3. The `sub` [registered claim]({{< ref "api-management/authentication/jwt-claim-validation#registered-vs-custom-claims" >}}). -Note that session objects can be cached to improve performance, so the identity extraction is only performed on the first request with a JWT, or when the cache is refreshed. +**Example** In this example, `skipKid` has been set to `true`, so Tyk checks the `subjectClaims` and determines that the value in the custom claim `user_id` within the JWT should be used as the identity for the session object. @@ -72,6 +69,13 @@ x-tyk-api-gateway: subjectClaims: [user_id] ``` +{{< note success >}} +**Note** + +Session objects can be cached to improve performance, so the identity extraction is only performed on the first request with a JWT, or when the cache is refreshed. + +{{< /note >}} + ## Identifying the Tyk Policies to be applied [Security Policies]({{< ref "api-management/policies" >}}) are applied (or mapped) to the session object to configure authorization for the request. Policies must be [registered]({{< ref "api-management/policies#how-you-can-create-policies" >}}) with Tyk, such that they have been allocated a unique *Tyk Policy Id*. @@ -82,11 +86,9 @@ Tyk supports three different types of policy mapping, which are applied in this 2. Scope policy mapping 3. Default policy mapping -Note that, whilst a *default policy* must be configured for each API using JWT Auth, this will only be applied if there are no policies mapped in step 1 or 2. If *scope policies* are activated, these will be applied on top of the previously applied direct policies as explained in more detail in the section on [combining policies]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#combining-policies" >}}). - ### Direct policies -You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. +You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) (not a standard JWT claim) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. In this example, Tyk has been configured to check the `pol` claim in the JWT to find the *Policy Ids* for the policies to be applied to the session object: @@ -115,6 +117,13 @@ Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; s You **must** configure one or more *default policies* that will be applied if no specific policies are identified in the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy Ids. +{{< note success >}} +**Note** + +When using default policies with JWT authentication, the Gateway will return a `403 Forbidden` error if no default policies are configured, if referenced policy IDs don’t exist, or if policies are invalid or incorrectly formatted. + +{{< /note >}} + ```yaml x-tyk-api-gateway: server: @@ -128,7 +137,9 @@ x-tyk-api-gateway: ### Scope policies -Directly mapping policies to APIs relies upon the sharing of Tyk Policy Ids with the IdP (so that they can be included in the JWT) and may not provide the flexibility required. Tyk supports a more advanced approach where policies are applied based upon *scopes* declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. +Directly mapping policies to APIs relies upon the sharing of Tyk Policy Ids with the IdP (so that they can be included in the JWT) and may not provide the flexibility required. + +Tyk supports a more advanced approach where policies are applied based upon *scopes* declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. Within the JWT, you identify a Private Claim that will hold the authorization (or access) scopes for the API. You then provide, within that claim, a list of *scopes*. In your API definition, you configure the `scopes.claims` to instruct Tyk where to look for the scopes and then you declare a mapping of scopes to policies within the `scopes.scopeToPolicyMapping` object. @@ -155,20 +166,51 @@ In this example, Tyk will check the `accessScopes` claim within the incoming JWT Prior to Tyk 5.10, the authorization scopes claim was retrieved from `scopes.claimName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. {{< /note >}} -Multiple scopes can be declared by setting the value of the authorization scopes claim in any of four configurations: +#### Declaring Multiple Scopes -- a string with space delimited list of values (by standard)
- `"permissions": "read:users write:users"` -- an array of strings
- `"permissions": ["read:users", "write:users"]` -- a string with space delimited list of values inside a nested key
- `"permissions": { "access": "read:users write:users" }` -- an array of strings inside a nested key
- `"permissions": { "access": ["read:users", "write:users"] }` +You can declare multiple scopes by setting the value of the **authorization scopes claim** in one of the following ways: -If there is a nested key then you must use dot notation in the value configured for `scopes.claims` so, for the first two examples above, `scopes.claims` should be set to `permissions` whilst for the the two nested examples you would use `permissions.access`. +* **String with space-delimited list of values (standard format)** -This example of a fragment of a JWT, if provided to an API with the configuration above, will cause Tyk to apply both policies to the session object: + ```json + "accessScopes": "read:users write:users" + ``` + +* **Array of strings** + + ```json + "accessScopes": ["read:users", "write:users"] + ``` + +* **String with space-delimited list inside a nested key** + + ```json + "accessScopes": { "access": "read:users write:users" } + ``` + +* **Array of strings inside a nested key** + + ```json + "accessScopes": { "access": ["read:users", "write:users"] } + ``` + +**Important:** + +* If your scopes are defined inside a nested key, use **dot notation** for the `scopes.claims` value. + + * For **examples 1 and 2**, set `scopes.claims` to: + + ``` + accessScopes + ``` + * For **examples 3 and 4**, set `scopes.claims` to: + + ``` + accessScopes.access + ``` + +**Example JWT fragment:** +If this JWT is provided to an API configured as described above, Tyk will apply both policies to the session object. ```json { @@ -212,27 +254,53 @@ To ensure these policies work correctly when combined: ## Session Updates +After authenticating the JWT token and extracting the necessary identity and policy information, Tyk creates or updates a session object that controls access to the API. + +The following [session attributes]({{< ref "api-management/policies#session-object" >}}) are modified based on the policies: + +1. **Access Rights**: Determines which API endpoints the token can access +2. **Rate Limits**: Controls how many requests per second/minute the token can make +3. **Quotas**: Sets maximum number of requests allowed in a time period +4. **Metadata**: Custom metadata from the policies is added to the session +5. **Tags**: Policy tags are added to the session + +In addition to updating the session, Tyk extracts claims from the JWT token and makes them available as context variables for use in other middleware. These context variables can be accessed in URL rewrites, header transforms, and other middleware components using the $tyk_context variable. + When a JWT's claims change (for example, configuring different scopes or policies), Tyk will update the session with the new policies on the next request made with the token. -## Missing Policies +## Advanced Configuration -If a policy Id is mapped to a session, but there is no policy with that Id, Tyk will fail safe and reject the request returning the `HTTP 403 Forbidden` response with `Key not authorized: no matching policy`. Tyk Gateway will also log the error: `Policy ID found is invalid!`. +### Using Multiple Identity Providers -## Using Multiple Identity Providers +When using multiple Identity Providers (IdPs), you may need to check different claim locations for the same information. Tyk supports defining **multiple claim locations** for subject identity and policy IDs. -When using multiple Identity Providers, you may need to check different claim locations for the same information. Tyk supports multiple claim locations for the subject identity and policy Ids. +* **Before Tyk 5.10 (and for Tyk Classic APIs):** -Prior to Tyk 5.10 and for Tyk Classic APIs, the Gateway could be configured to check single claims for the subject identity, base policy and scope-to-policy mapping. This did not support the scenario where different IdPs used different claims - for example, for the policy mapping, Keycloak uses `scope`, whereas Okta uses `scp`. + * The Gateway could only check **single claims** for: -From Tyk 5.10+, Tyk OAS APIs can be configured to check multiple claim names to locate these data in the received token. + * Subject identity + * Base policy + * Scope-to-policy mapping + * This setup didn’t support multiple IdPs using different claim names (e.g **Keycloak** uses `scope` and **Okta** uses `scp`) -| API Configuration Type | Tyk Version | Subject Identity Locator | Base Policy Locator | Scope-to-Policy Mapping Locator | -|-------------|----------|---|---|---| -| Tyk OAS | pre-5.10 | `identityBaseField` | `policyFieldName` | `scopes.claimName` | -| Tyk OAS | 5.10+ | `subjectClaims` | `basePolicyClaims` | `scopes.claims`| -| Tyk Classic | all | `jwt_identity_base_field` | `jwt_policy_field_name` | `jwt_scope_claim_name` | +* **From Tyk 5.10 onwards (Tyk OAS APIs):** -For example: + * You can configure **multiple claim names** for: + + * Subject identity + * Base policy + * Scope-to-policy mapping + * This allows Tyk to locate data across various tokens and IdPs more flexibly. + +**Configuration summary:** + +| API Configuration Type | Tyk Version | Subject Identity Locator | Base Policy Locator | Scope-to-Policy Mapping Locator | +| ---------------------- | ----------- | ------------------------- | ----------------------- | ------------------------------- | +| Tyk OAS | pre-5.10 | `identityBaseField` | `policyFieldName` | `scopes.claimName` | +| Tyk OAS | 5.10+ | `subjectClaims` | `basePolicyClaims` | `scopes.claims` | +| Tyk Classic | all | `jwt_identity_base_field` | `jwt_policy_field_name` | `jwt_scope_claim_name` | + +**Example configuration:** ```yaml x-tyk-api-gateway: @@ -246,7 +314,14 @@ x-tyk-api-gateway: # New multi-location support (Tyk 5.10+) subjectClaims: - "sub" - - "username" + - "username" - "user_id" ``` +#### Backward Compatibility + +The new configuration is fully backward compatible: + +- Existing `identityBaseField`, `policyFieldName`, and `scopes.claimName` settings continue to work +- If both old and new fields are specified, the new fields take precedence +- When using only new fields, the first element in each array is used to set the corresponding legacy field for backward compatibility From f5f2f617af44da29ffe66a0533fbcbc0f48c1d4d Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Thu, 16 Oct 2025 16:29:35 +0530 Subject: [PATCH 09/17] Fixes --- .../api-management/authentication/jwt-authorization.md | 6 +++--- .../api-management/authentication/jwt-claim-validation.md | 8 ++++---- tyk-docs/content/api-management/client-authentication.md | 2 +- .../authentication-authorization/json-web-tokens.md | 2 +- .../content/developer-support/release-notes/gateway.md | 4 ++-- tyk-docs/content/tyk-stack/tyk-operator/create-an-api.md | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index 66d74a9d09..636e6291f3 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -50,7 +50,7 @@ To associate a session with the authenticated user, Tyk Gateway extracts the uni {{< note success >}} **Note** -Prior to Tyk 5.10, the subject identity claim was retrieved from `identityBaseField`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. +Prior to Tyk 5.10, the subject identity claim was retrieved from `identityBaseField`; see [using multiple identity providers]({{< ref "#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. {{< /note >}} 3. The `sub` [registered claim]({{< ref "api-management/authentication/jwt-claim-validation#registered-vs-custom-claims" >}}). @@ -110,7 +110,7 @@ In the JWT, you should then provide the list of policy Ids as an array of values {{< note success >}} **Note** -Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. +Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; see [using multiple identity providers]({{< ref "#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. {{< /note >}} ### Default policies @@ -163,7 +163,7 @@ In this example, Tyk will check the `accessScopes` claim within the incoming JWT {{< note success >}} **Note** -Prior to Tyk 5.10, the authorization scopes claim was retrieved from `scopes.claimName`; see [using multiple identity providers]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. +Prior to Tyk 5.10, the authorization scopes claim was retrieved from `scopes.claimName`; see [using multiple identity providers]({{< ref "#using-multiple-identity-providers" >}}) for details and for the Tyk Classic API alternative. {{< /note >}} #### Declaring Multiple Scopes diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index 642e3cd356..a932b2fb37 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -89,9 +89,9 @@ After [verifying]({{< ref "basic-config-and-security/security/authentication-aut 1. **Claims Extraction**: All claims from the JWT payload are extracted and stored in context variables with the format `jwt_claims_CLAIMNAME`. For example, a claim named `role` becomes accessible as `jwt_claims_role`. 2. **Claims Validation**: - - [Registered Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#registered-claims-validation" >}}): Checks standard claims against your configuration - - [Custom Claims Validation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#custom-claims-validation" >}}): Applies your business rules to custom claims - - [Authorization]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#managing-authorization" >}}): Uses validated claims to determine API access and apply policies + - [Registered Claims Validation]({{< ref "#registered-claims-validation" >}}): Checks standard claims against your configuration + - [Custom Claims Validation]({{< ref "#custom-claims-validation" >}}): Applies your business rules to custom claims + - [Authorization]({{< ref "api-management/authentication/jwt-authorization" >}}): Uses validated claims to determine API access and apply policies If any validation step fails, Tyk rejects the request with a specific error message indicating which claim validation failed and why. @@ -567,7 +567,7 @@ x-tyk-api-gateway: ##### Object Values -Complex object claims can be validated, though typically you'll want to validate specific nested properties using [dot notation]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#nested-claims-dot-notation" >}}). +Complex object claims can be validated, though typically you'll want to validate specific nested properties using [dot notation]({{< ref "#nested-claims" >}}). **Validation Behavior** diff --git a/tyk-docs/content/api-management/client-authentication.md b/tyk-docs/content/api-management/client-authentication.md index b12580ce92..7a44eef999 100644 --- a/tyk-docs/content/api-management/client-authentication.md +++ b/tyk-docs/content/api-management/client-authentication.md @@ -196,7 +196,7 @@ There could be cases when you don’t need to introspect a JWT access token from - a base64 encoded static secret - a valid JWK url in plain text - a valid JWK url in base64 encoded format -- `issuedAtValidationSkew` , `notBeforeValidationSkew`, `expiresAtValidationSkew` can be used to [configure clock skew]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#jwt-validity-and-clock-skew" >}}) for json web token validation. +- `issuedAtValidationSkew` , `notBeforeValidationSkew`, `expiresAtValidationSkew` can be used to [configure clock skew]({{< ref "api-management/authentication/jwt-claim-validation#clock-skew-configuration" >}}) for json web token validation. - `identityBaseField` - the identity key name for claims. If empty it will default to `sub`. ##### Example: Tyk OAS API definition with JWT validation enabled diff --git a/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md b/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md index 696894d728..6dc53286c8 100644 --- a/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md +++ b/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md @@ -183,7 +183,7 @@ This diagram outlines the flow when using JWT Auth to secure access to your API. - if signature validation fails, the request is rejected - if the token is valid and not expired, the request is authenticated as coming from the client, and is accepted -5. Next, Tyk will create an internal session for the request which will be used to control access rights, rate limits, usage quotas and in tracking logs (step 5). The session is linked to Alice using an identity that is [extracted from the JWT claims]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#identifying-the-session-owner" >}}). +5. Next, Tyk will create an internal session for the request which will be used to control access rights, rate limits, usage quotas and in tracking logs (step 5). The session is linked to Alice using an identity that is [extracted from the JWT claims]({{< ref "api-management/authentication/jwt-authorization#identifying-the-session-owner" >}}). 6. In step 6 Tyk will proceed to enforce authorization by checking other claims to determine which Security Policies should be applied to the session: - check for the value in the policy claim within the JWT (identified by the value stored in `basePolicyClaims`) diff --git a/tyk-docs/content/developer-support/release-notes/gateway.md b/tyk-docs/content/developer-support/release-notes/gateway.md index d756639e43..0e8ba00fd3 100644 --- a/tyk-docs/content/developer-support/release-notes/gateway.md +++ b/tyk-docs/content/developer-support/release-notes/gateway.md @@ -106,7 +106,7 @@ This enhancement makes Tyk's JWT middleware the primary validation mechanism for Ideal for organizations that require sophisticated JWT validation beyond standard token checks. -For more details, please see the dedicated [JWT Auth]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#managing-authorization-with-jwt" >}}) section. +For more details, please see the dedicated [JWT Auth]({{< ref "api-management/authentication/jwt-authorization" >}}) section. ##### Advanced JWKS Cache Management for Tyk OAS APIs @@ -125,7 +125,7 @@ Tyk Gateway now provides comprehensive JWKS (JSON Web Key Set) cache control for This enhancement is particularly valuable for organizations migrating to Tyk OAS APIs or those requiring consistent low-latency JWT validation performance with multiple Identity Providers that have different key rotation policies. -For more details, please see the [JWT Auth]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#jwt-signatures" >}}) section. +For more details, please see the [JWT Auth]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) section. ##### Centralized External Service Configuration diff --git a/tyk-docs/content/tyk-stack/tyk-operator/create-an-api.md b/tyk-docs/content/tyk-stack/tyk-operator/create-an-api.md index 1665b078c4..f03bf30b18 100644 --- a/tyk-docs/content/tyk-stack/tyk-operator/create-an-api.md +++ b/tyk-docs/content/tyk-stack/tyk-operator/create-an-api.md @@ -739,7 +739,7 @@ This configuration uses [JWT tokens]({{< ref "basic-config-and-security/security Users can configure JWT authentication by defining the following fields: -- `jwt_signing_method`: Specify the method used to sign the JWT. Refer to the documentation on [JWT Signatures]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#jwt-signatures">}}) for supported methods. +- `jwt_signing_method`: Specify the method used to sign the JWT. Refer to the documentation on [JWT Signatures]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation">}}) for supported methods. - `jwt_source`: Specify the public key used for verifying the JWT. - `jwt_identity_base_field`: Define the identity source, typically set to `sub` (subject), which uniquely identifies the user or entity. - `jwt_policy_field_name`: Specify the claim within the JWT payload that indicates the policy ID to apply. From 629546f2f149c60625b10224504ca68c3a03f573 Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Thu, 16 Oct 2025 16:33:55 +0530 Subject: [PATCH 10/17] F --- .../api-management/authentication/jwt-authorization.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index 636e6291f3..64f74fb9a6 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -42,8 +42,8 @@ To associate a session with the authenticated user, Tyk Gateway extracts the uni 1. Tyk tries each claim **in the exact order they appear** in the array 2. For each claim, Tyk checks if: - - The claim exists in the token - - The claim value is a string and is not empty + - The claim exists in the token + - The claim value is a string and is not empty 3. Tyk uses the **first valid, non-empty value** it finds and stops processing further claims 4. If none of the claims yield a valid identity, Tyk proceeds to check the `sub` claim as a fallback @@ -264,10 +264,14 @@ The following [session attributes]({{< ref "api-management/policies#session-obje 4. **Metadata**: Custom metadata from the policies is added to the session 5. **Tags**: Policy tags are added to the session -In addition to updating the session, Tyk extracts claims from the JWT token and makes them available as context variables for use in other middleware. These context variables can be accessed in URL rewrites, header transforms, and other middleware components using the $tyk_context variable. +In addition to updating the session, Tyk extracts claims from the JWT token and makes them available as context variables for use in other [middleware]({{< ref "api-management/traffic-transformation" >}}). + +{{< note success >}} When a JWT's claims change (for example, configuring different scopes or policies), Tyk will update the session with the new policies on the next request made with the token. +{{< /note >}} + ## Advanced Configuration ### Using Multiple Identity Providers From 07bea8808b1e9c5534536328e86464f30aef56e3 Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Thu, 16 Oct 2025 16:34:52 +0530 Subject: [PATCH 11/17] F --- .../api-management/authentication/jwt-authorization.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index 64f74fb9a6..f47f2eb7d1 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -6,6 +6,12 @@ keywords: ["Authentication", "Authorization", "JWT", "JSON Web Tokens", "Claims" date: 2025-01-10 --- +## Availability + +| Component | Editions | +|-------------| ------------------------- | +| Tyk Gateway | Community and Enterprise | + ## Introduction [JSON Web Tokens (JWT)]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens" >}}) is a popular method for authentication and authorization. From c94db971a27bed3bbf6bd6afd19a8a31522103da Mon Sep 17 00:00:00 2001 From: Sharad Regoti Date: Thu, 16 Oct 2025 16:40:56 +0530 Subject: [PATCH 12/17] Grammar Fixes --- .../authentication/jwt-authorization.md | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index f47f2eb7d1..974bf1347a 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -35,7 +35,7 @@ When a request with a JWT token arrives at Tyk Gateway, after the authentication 3. **Update Session**: The session is updated with unique identify and policies (determines access rights, rate limits, and quotas). -In the following sections, we explain each of these steps in more detail. +In the following sections, we provide a detailed explanation of each of these steps. ## Identifying the Session Owner @@ -107,7 +107,7 @@ x-tyk-api-gateway: basePolicyClaims: [pol] ``` -In the JWT, you should then provide the list of policy Ids as an array of values in that claim, for example you might declare: +In the JWT, you should then provide the list of policy IDs as an array of values in that claim, for example you might declare: ``` "pol": ["685a8af28c24bdac0dc21c28", "685bd90b8c24bd4b6d79443d"] @@ -121,7 +121,7 @@ Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; s ### Default policies -You **must** configure one or more *default policies* that will be applied if no specific policies are identified in the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy Ids. +You **must** configure one or more *default policies* that will be applied if no specific policies are identified in the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy IDs. {{< note success >}} **Note** @@ -143,9 +143,9 @@ x-tyk-api-gateway: ### Scope policies -Directly mapping policies to APIs relies upon the sharing of Tyk Policy Ids with the IdP (so that they can be included in the JWT) and may not provide the flexibility required. +Directly mapping policies to APIs relies on the sharing of Tyk Policy IDs with the IdP (so that they can be included in the JWT) and may not provide the required flexibility. -Tyk supports a more advanced approach where policies are applied based upon *scopes* declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. +Tyk supports a more advanced approach where policies are applied based on scopes declared in the JWT. This keeps separation between the IdP and Tyk-specific concepts, and supports much more flexible configuration. Within the JWT, you identify a Private Claim that will hold the authorization (or access) scopes for the API. You then provide, within that claim, a list of *scopes*. In your API definition, you configure the `scopes.claims` to instruct Tyk where to look for the scopes and then you declare a mapping of scopes to policies within the `scopes.scopeToPolicyMapping` object. @@ -157,14 +157,14 @@ x-tyk-api-gateway: jwtAuth: scopes: scopeToPolicyMapping: - - scope: read:users + - scope: read: users policyId: 685bd90b8c24bd4b6d79443d - - scope: write:users + - scope: write: users policyId: 685a8af28c24bdac0dc21c28 claims: [accessScopes] ``` -In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read:users` or `write:users`. If neither scope is declared in the claim, or the claim is missing, then the default policy will be applied. +In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read: users` or `write: users`. If neither scope is declared in the claim, or the claim is missing, then the default policy will be applied. {{< note success >}} **Note** @@ -179,25 +179,25 @@ You can declare multiple scopes by setting the value of the **authorization scop * **String with space-delimited list of values (standard format)** ```json - "accessScopes": "read:users write:users" + "accessScopes": "read: users write: users" ``` * **Array of strings** ```json - "accessScopes": ["read:users", "write:users"] + "accessScopes": ["read: users", "write: users"] ``` * **String with space-delimited list inside a nested key** ```json - "accessScopes": { "access": "read:users write:users" } + "accessScopes": { "access": "read: users write: users" } ``` * **Array of strings inside a nested key** ```json - "accessScopes": { "access": ["read:users", "write:users"] } + "accessScopes": { "access": ["read: users", "write: users"] } ``` **Important:** @@ -222,21 +222,21 @@ If this JWT is provided to an API configured as described above, Tyk will apply { "sub": "1234567890", "name": "Alice Smith", - "accessScopes": ["read:users", "write:users"] + "accessScopes": ["read: users", "write: users"] } ``` ### Combining policies -Where multiple policies are mapped to a session (for example, if several scopes are declared in the JWT claim, or if you set multiple *default policies*) Tyk will apply all the matching policies to the request, combining their access rights and using the most permissive rate limits and quotas. It's important when creating those policies to ensure that they do not conflict with each other. +Where multiple policies are mapped to a session (for example, if several scopes are declared in the JWT claim, or if you set multiple *default policies*), Tyk will apply all the matching policies to the request, combining their access rights and using the most permissive rate limits and quotas. It's important when creating those policies to ensure that they do not conflict with each other. Policies are combined as follows: -1. Apply direct mapped policies declared via `basePolicyClaims` -2. Apply scope mapped policies declared in `scopeToPolicyMapping` based upon scopes in the JWT +1. Apply direct-mapped policies declared via `basePolicyClaims` +2. Apply scope-mapped policies declared in `scopeToPolicyMapping` based upon scopes in the JWT 3. If no policies have been applied in steps 1 or 2, apply the default policies from `defaultPolicies` -When multiple policies are combined the following logic is applied: +When multiple policies are combined, the following logic is applied: - **access rights** A user gets access to an endpoint if ANY of the applied policies grant access - **rate limits** Tyk uses the most permissive values (highest quota, lowest rate limit) @@ -266,7 +266,7 @@ The following [session attributes]({{< ref "api-management/policies#session-obje 1. **Access Rights**: Determines which API endpoints the token can access 2. **Rate Limits**: Controls how many requests per second/minute the token can make -3. **Quotas**: Sets maximum number of requests allowed in a time period +3. **Quotas**: Sets the maximum number of requests allowed in a time period 4. **Metadata**: Custom metadata from the policies is added to the session 5. **Tags**: Policy tags are added to the session @@ -274,7 +274,7 @@ In addition to updating the session, Tyk extracts claims from the JWT token and {{< note success >}} -When a JWT's claims change (for example, configuring different scopes or policies), Tyk will update the session with the new policies on the next request made with the token. +When a JWT's claims change (for example, by configuring different scopes or policies), Tyk updates the session with the new policies on the subsequent request made with the token. {{< /note >}} @@ -335,3 +335,4 @@ The new configuration is fully backward compatible: - Existing `identityBaseField`, `policyFieldName`, and `scopes.claimName` settings continue to work - If both old and new fields are specified, the new fields take precedence - When using only new fields, the first element in each array is used to set the corresponding legacy field for backward compatibility + From 8cda6538fdc237c4e52a0aa51f6a18a263d2ab2a Mon Sep 17 00:00:00 2001 From: Master Date: Fri, 17 Oct 2025 16:04:10 +0530 Subject: [PATCH 13/17] Update tyk-docs/content/api-management/authentication/jwt-authorization.md --- .../content/api-management/authentication/jwt-authorization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index 974bf1347a..5b97a60871 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -6,7 +6,7 @@ keywords: ["Authentication", "Authorization", "JWT", "JSON Web Tokens", "Claims" date: 2025-01-10 --- -## Availability +## Availability | Component | Editions | |-------------| ------------------------- | From 471e2c4f4410a8b9b7a7ea662ee5f9dbd035f3b9 Mon Sep 17 00:00:00 2001 From: Master Date: Thu, 23 Oct 2025 12:20:50 +0530 Subject: [PATCH 14/17] Apply suggestions from code review Co-authored-by: andyo-tyk <99968932+andyo-tyk@users.noreply.github.com> --- .../authentication/jwt-authorization.md | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-authorization.md b/tyk-docs/content/api-management/authentication/jwt-authorization.md index 5b97a60871..619db00ad7 100644 --- a/tyk-docs/content/api-management/authentication/jwt-authorization.md +++ b/tyk-docs/content/api-management/authentication/jwt-authorization.md @@ -14,32 +14,34 @@ date: 2025-01-10 ## Introduction -[JSON Web Tokens (JWT)]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens" >}}) is a popular method for authentication and authorization. +[JSON Web Tokens (JWT)](https://www.jwt.io/introduction) are a popular method for client authentication and authorization that can be used to secure access to your APIs via Tyk's [JWT Auth]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens" >}}) method. -In Tyk, after a JWT has been validated during the [authentication]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) step, Tyk uses the claims within the token to determine what security policies (access rights, rate limits and quotas) should be applied to the request. +After the JWT signature has been [validated]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}), Tyk uses the **claims** within the token to determine which security policies (access rights, rate limits and quotas) should be applied to the request. + +From Tyk 5.10, Tyk can perform optional [validation]({{< ref "basic-config-and-security/security/authentication-authorization/jwt-claim-validation" >}}) of these claims. In this page, we explain how Tyk performs JWT authorization, including how it identifies the user and the policies to be applied. ## JWT Authorization Flow -When a request with a JWT token arrives at Tyk Gateway, after the authentication (token and claim validation) step, Tyk performs the following steps to authorize the request: +When a request with a JWT arrives at Tyk Gateway, after the authentication (signature and claim validation) step, Tyk performs the following steps to authorize the request: -1. **Identity Extraction**: The user identity is extracted from the token, using one of: +1. **Identity Extraction**: The user identity is extracted from the token according to this order of precedence: - The `kid` header (unless `skipKid` is enabled) - - A custom claim specified in `subjectClaims` - - The standard `sub` claim as fallback + - A custom claim (specified in `subjectClaims`) + - The standard `sub` claim (fallback) -2. **Policy Resolution**: Tyk determines which policy to apply to the request: +2. **Policy Resolution**: Tyk determines which [policy]({{< ref "api-management/policies#what-is-a-security-policy" >}}) to apply to the request: - From scope-to-policy mapping - From default policies -3. **Update Session**: The session is updated with unique identify and policies (determines access rights, rate limits, and quotas). +3. **Update Session**: The [session]({{< ref "api-management/policies#what-is-a-session-object" >}}) is updated with the identity and policies. In the following sections, we provide a detailed explanation of each of these steps. ## Identifying the Session Owner -To associate a session with the authenticated user, Tyk Gateway extracts the unique identity from the JWT token by checking the following fields in order of precedence: +A unique identity is stored in the session object to associate it with the authenticated user. This identifier is extracted from the JWT by checking the following fields in order of precedence: 1. The standard Key ID header (`kid`) in the JWT (unless the `skipKid` option is enabled) 2. The subject identity claim identified by the value(s) stored in `subjectClaims` (which allows API administrators to designate any JWT claim as the identity source (e.g., user_id, email, etc.). @@ -51,7 +53,7 @@ To associate a session with the authenticated user, Tyk Gateway extracts the uni - The claim exists in the token - The claim value is a string and is not empty 3. Tyk uses the **first valid, non-empty value** it finds and stops processing further claims - 4. If none of the claims yield a valid identity, Tyk proceeds to check the `sub` claim as a fallback + 4. If none of the claims yield a valid identity, Tyk proceeds to the next stage (the `sub` claim) {{< note success >}} **Note** @@ -94,7 +96,9 @@ Tyk supports three different types of policy mapping, which are applied in this ### Direct policies -You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private Claim](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) (not a standard JWT claim) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. +You can optionally specify policies to be applied to the session via the *policy claim* in the JWT. This is a [Private](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3) Claim (not a registered claim) and can be anything you want, but typically we recommend the use of `pol`. You must instruct Tyk where to look for the policy claim by configuring the `basePolicyClaims` field in the API definition. + +Note that we typically refer to Private Claims as Custom Claims. In this example, Tyk has been configured to check the `pol` claim in the JWT to find the *Policy Ids* for the policies to be applied to the session object: @@ -107,7 +111,7 @@ x-tyk-api-gateway: basePolicyClaims: [pol] ``` -In the JWT, you should then provide the list of policy IDs as an array of values in that claim, for example you might declare: +In the JWT, you should then provide the list of Tyk policy IDs as an array of values in that claim, for example you might declare: ``` "pol": ["685a8af28c24bdac0dc21c28", "685bd90b8c24bd4b6d79443d"] @@ -121,12 +125,12 @@ Prior to Tyk 5.10, the base policy claim was retrieved from `policyFieldName`; s ### Default policies -You **must** configure one or more *default policies* that will be applied if no specific policies are identified in the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy IDs. +You **must** configure one or more *default policies* that will be applied if no specific policies are identified from the JWT claims. These are configured using the `defaultPolicies` field in the API definition, which accepts a list of policy IDs. This prevents a session from being created with no authorization to interact with APIs on the Gateway. {{< note success >}} **Note** -When using default policies with JWT authentication, the Gateway will return a `403 Forbidden` error if no default policies are configured, if referenced policy IDs don’t exist, or if policies are invalid or incorrectly formatted. +The Gateway will return `HTTP 403 Forbidden` if no default policies are configured, if the referenced policies don’t exist, or if policies are invalid or incorrectly formatted. {{< /note >}} @@ -164,7 +168,7 @@ x-tyk-api-gateway: claims: [accessScopes] ``` -In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read: users` or `write: users`. If neither scope is declared in the claim, or the claim is missing, then the default policy will be applied. +In this example, Tyk will check the `accessScopes` claim within the incoming JWT and apply the appropriate policy if that claim contains the value `read: users` or `write: users`. If neither scope is declared in the claim, or the claim is missing, the default policy will be applied. {{< note success >}} **Note** @@ -239,7 +243,7 @@ Policies are combined as follows: When multiple policies are combined, the following logic is applied: - **access rights** A user gets access to an endpoint if ANY of the applied policies grant access -- **rate limits** Tyk uses the most permissive values (highest quota, lowest rate limit) +- **consumption limits** Tyk uses the most permissive values (highest quota, highest throughput ) - **other settings** The most permissive settings from any policy are applied ### Policy Best Practices @@ -260,7 +264,7 @@ To ensure these policies work correctly when combined: ## Session Updates -After authenticating the JWT token and extracting the necessary identity and policy information, Tyk creates or updates a session object that controls access to the API. +After authenticating the token and extracting the necessary identity and policy information, Tyk creates or updates a session object that controls access to the API. The following [session attributes]({{< ref "api-management/policies#session-object" >}}) are modified based on the policies: @@ -270,7 +274,7 @@ The following [session attributes]({{< ref "api-management/policies#session-obje 4. **Metadata**: Custom metadata from the policies is added to the session 5. **Tags**: Policy tags are added to the session -In addition to updating the session, Tyk extracts claims from the JWT token and makes them available as context variables for use in other [middleware]({{< ref "api-management/traffic-transformation" >}}). +In addition to updating the session, Tyk extracts claims from the JWT and makes them available as context variables for use in other [middleware]({{< ref "api-management/traffic-transformation" >}}). {{< note success >}} @@ -282,7 +286,7 @@ When a JWT's claims change (for example, by configuring different scopes or poli ### Using Multiple Identity Providers -When using multiple Identity Providers (IdPs), you may need to check different claim locations for the same information. Tyk supports defining **multiple claim locations** for subject identity and policy IDs. +When using multiple Identity Providers (IdPs), you may need to check different claim locations for the same information. Tyk supports definition of **multiple claim locations** for subject identity and policy IDs. * **Before Tyk 5.10 (and for Tyk Classic APIs):** From 1cad7eb1b19751640aa759d17027301643281480 Mon Sep 17 00:00:00 2001 From: Master Date: Thu, 23 Oct 2025 12:22:21 +0530 Subject: [PATCH 15/17] Update tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md Co-authored-by: andyo-tyk <99968932+andyo-tyk@users.noreply.github.com> --- .../security/authentication-authorization/json-web-tokens.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md b/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md index 6dc53286c8..a50efd0f54 100644 --- a/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md +++ b/tyk-docs/content/basic-config-and-security/security/authentication-authorization/json-web-tokens.md @@ -183,7 +183,7 @@ This diagram outlines the flow when using JWT Auth to secure access to your API. - if signature validation fails, the request is rejected - if the token is valid and not expired, the request is authenticated as coming from the client, and is accepted -5. Next, Tyk will create an internal session for the request which will be used to control access rights, rate limits, usage quotas and in tracking logs (step 5). The session is linked to Alice using an identity that is [extracted from the JWT claims]({{< ref "api-management/authentication/jwt-authorization#identifying-the-session-owner" >}}). +5. Next, Tyk will create an internal session for the request which will be used to control access rights, consumption limits and to identify the request in tracking logs (step 5). The session is linked to Alice using an identity that is [extracted from the JWT claims]({{< ref "api-management/authentication/jwt-authorization#identifying-the-session-owner" >}}). 6. In step 6 Tyk will proceed to enforce authorization by checking other claims to determine which Security Policies should be applied to the session: - check for the value in the policy claim within the JWT (identified by the value stored in `basePolicyClaims`) From 4c160591430445384741ad2b96b2724c9b6ee104 Mon Sep 17 00:00:00 2001 From: Master Date: Thu, 23 Oct 2025 12:22:38 +0530 Subject: [PATCH 16/17] Update tyk-docs/content/api-management/authentication/jwt-claim-validation.md Co-authored-by: andyo-tyk <99968932+andyo-tyk@users.noreply.github.com> --- .../api-management/authentication/jwt-claim-validation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index a932b2fb37..ddfa0d5377 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -86,7 +86,7 @@ JWT claims can be categorized into two types: After [verifying]({{< ref "basic-config-and-security/security/authentication-authorization/json-web-tokens#signature-validation" >}}) that the token hasn't been tampered with, Tyk processes claims in this order: -1. **Claims Extraction**: All claims from the JWT payload are extracted and stored in context variables with the format `jwt_claims_CLAIMNAME`. For example, a claim named `role` becomes accessible as `jwt_claims_role`. +1. **Claims Extraction**: All claims from the JWT payload are extracted and stored in [context variables]({{< ref "api-management/traffic-transformation/request-context-variables" >}}) with the format `jwt_claims_CLAIMNAME`. For example, a claim named `role` becomes accessible as `jwt_claims_role`. 2. **Claims Validation**: - [Registered Claims Validation]({{< ref "#registered-claims-validation" >}}): Checks standard claims against your configuration From db67893f3c8e0781eb085b63f968cbd5f7be3438 Mon Sep 17 00:00:00 2001 From: Master Date: Thu, 23 Oct 2025 12:22:56 +0530 Subject: [PATCH 17/17] Update tyk-docs/content/api-management/authentication/jwt-claim-validation.md Co-authored-by: andyo-tyk <99968932+andyo-tyk@users.noreply.github.com> --- .../api-management/authentication/jwt-claim-validation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md index ddfa0d5377..22659f850b 100644 --- a/tyk-docs/content/api-management/authentication/jwt-claim-validation.md +++ b/tyk-docs/content/api-management/authentication/jwt-claim-validation.md @@ -55,7 +55,7 @@ JWT claims can be categorized into two types: - **Custom Claims**: - Custom Claims are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. + Custom Claims, referred to as Private Claims in the [JWT Specification](https://datatracker.ietf.org/doc/html/rfc7519#section-4.3), are application-specific and can contain any information relevant to your use case, such as user roles, permissions, department, or metadata. **Example JWT Payload with Both Registered and Custom Claims**: