jwt
Policy Information Point for validating and monitoring JSON Web Tokens (JWT). Attributes update automatically based on token lifecycle events such as maturity and expiration.
This Policy Information Point validates JSON Web Tokens and monitors their validity state over time.
JWT tokens are validated against multiple criteria:
Signature Verification
Tokens must be signed with RS256 algorithm. Public keys for signature verification are sourced from:
- A whitelist of trusted public keys configured in policy variables
- A remote key server that provides public keys on demand
Time-based Validation
Tokens are validated against time claims:
nbf(not before): Token becomes valid at this timestampexp(expiration): Token becomes invalid at this timestamp
Validity states transition automatically as time progresses, triggering policy re-evaluation when tokens become mature or expire.
Configuration
Configure the JWT PIP through policy variables in pdp.json:
{
"algorithm": "DENY_UNLESS_PERMIT",
"variables": {
"jwt": {
"publicKeyServer": {
"uri": "http://authz-server:9000/public-key/{id}",
"method": "POST",
"keyCachingTtlMillis": 300000
},
"whitelist": {
"key-id-1": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...",
"key-id-2": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEB..."
}
}
}
}
Public Key Server Configuration
uri: URL template for fetching public keys. Use{id}placeholder for key IDmethod: HTTP method for requests (GET or POST). Defaults to GET if omittedkeyCachingTtlMillis: Cache duration for retrieved keys in milliseconds. Defaults to 300000 (5 minutes)
Whitelist Configuration
The whitelist maps key IDs to Base64-encoded public keys. Whitelisted keys take precedence over the key server. Keys must be Base64 URL-safe encoded X.509 SubjectPublicKeyInfo structures.
Validity States
VALID: Token signature is trusted and time claims are satisfiedEXPIRED: Token has passed its expiration timeIMMATURE: Token has not yet reached its not-before timeNEVER_VALID: Token’s not-before time is after its expiration timeUNTRUSTED: Signature verification failed or public key unavailableINCOMPATIBLE: Token uses unsupported algorithm or has critical parametersINCOMPLETE: Required claims (key ID) are missingMALFORMED: Token is not a valid JWT structure
Access Control Examples
Basic token validation:
policy "require_valid_jwt"
permit
where
var token = subject.jwt;
token.<jwt.valid>;
Check specific validity state:
policy "allow_immature_tokens_for_testing"
permit action == "test:access"
where
var token = subject.jwt;
var state = token.<jwt.validity>;
state == "VALID" || state == "IMMATURE";
Grant access only when token is valid, deny when expired:
policy "time_sensitive_access"
permit action == "document:read"
where
var token = subject.credentials.bearer;
var state = token.<jwt.validity>;
state == "VALID";
obligation
{
"type": "logAccess",
"tokenState": state
}
Reject untrusted or tampered tokens:
policy "reject_untrusted_tokens"
deny
where
var token = subject.jwt;
var state = token.<jwt.validity>;
state == "UNTRUSTED" || state == "MALFORMED";
Reactive Behavior
The validity attributes are reactive streams that emit new values when the token’s state changes. This triggers automatic policy re-evaluation without requiring the client to re-submit requests.
Example timeline for a token with nbf=now+10s and exp=now+30s:
- t=0s: Emits IMMATURE
- t=10s: Emits VALID (policy re-evaluated)
- t=30s: Emits EXPIRED (policy re-evaluated)
valid
Input Entity of Attribute Finder
Name: rawToken [TEXT]
(TEXT jwt).<valid> validates a JWT token and returns true if the token is currently valid.
This attribute takes the JWT token as the left-hand input and returns a boolean stream that updates automatically as the token transitions between validity states.
A token is considered valid when:
- Signature verification succeeds with a trusted public key
- Current time is within the token’s validity period (after nbf, before exp)
- Token structure and claims meet requirements (RS256 algorithm, key ID present)
The attribute returns true only when the validity state is VALID. All other states
(EXPIRED, IMMATURE, UNTRUSTED, etc.) result in false.
Example:
policy "api_access"
permit action == "api:call"
where
var token = subject.credentials.bearer;
token.<jwt.valid>;
Example with token extracted from authorization header:
policy "rest_api_access"
permit action.http.method == "GET"
where
var authHeader = resource.http.headers.Authorization;
var token = authHeader.substring(7);
token.<jwt.valid>;
validity
Input Entity of Attribute Finder
Name: rawToken [TEXT]
(TEXT jwt).<validity> returns the current validity state of a JWT token as a text value.
This attribute provides detailed information about why a token is or is not valid. The stream emits new states as the token lifecycle progresses, enabling policies to react to state changes.
Possible return values:
VALID: Token is currently valid and trustedEXPIRED: Token validity period has endedIMMATURE: Token validity period has not yet begunNEVER_VALID: Token configuration is invalid (nbf after exp)UNTRUSTED: Signature verification failed or key unavailableINCOMPATIBLE: Unsupported algorithm or critical parametersINCOMPLETE: Required claims missing (e.g., key ID)MALFORMED: Invalid JWT structure
Example checking for multiple acceptable states:
policy "grace_period_access"
permit action == "service:use"
where
var token = subject.jwt;
var state = token.<jwt.validity>;
state == "VALID" || state == "IMMATURE";
Example with state-specific obligations:
policy "monitored_access"
permit action == "resource:access"
where
var token = subject.credentials.jwt;
var state = token.<jwt.validity>;
state == "VALID" || state == "IMMATURE";
obligation
{
"type": "auditLog",
"tokenState": state,
"userId": token.<jwt.parseJwt>.payload.sub
}
Example denying specific invalid states:
policy "deny_tampered_tokens"
deny
where
var token = subject.jwt;
var state = token.<jwt.validity>;
state == "UNTRUSTED" || state == "MALFORMED" || state == "INCOMPATIBLE";
obligation
{
"type": "securityAlert",
"reason": "Invalid token detected",
"state": state
}
Example handling expiration gracefully:
policy "token_refresh_hint"
permit action == "api:call"
where
var token = subject.jwt;
var state = token.<jwt.validity>;
state == "VALID";
advice
{
"type": "tokenStatus",
"message": state == "VALID" ? "Token valid" : "Token refresh required"
}