JwtVerify()
Verifies a JSON Web Token (JWT) signature and returns the claims (the data payload).
Also validates expiration, not-before, issuer, and audience if specified.
Requires Extension: Crypto Extension
JwtVerify( token=string, key=any, algorithms=any, issuer=string, audience=string, clockSkew=numeric, throwOnError=boolean );
Returns: any
| Argument | Description | Default |
|---|---|---|
|
token
string,
required
|
edit
JWT string to verify. |
|
|
key
any,
required
|
edit
Verification key. For HMAC: string or byte array. For RSA/EC: PEM string or Java PublicKey object. |
|
|
algorithms
any,
optional
|
edit
Allowed algorithms. Array or comma-separated string. Security best practice to restrict algorithms. |
|
|
issuer
string,
optional
|
edit
Required issuer (iss claim). Validation fails if token issuer doesn't match. |
|
|
audience
string,
optional
|
edit
Required audience (aud claim). Validation fails if audience is not in token's audience list. |
|
|
clockSkew
numeric,
optional
|
edit
Clock skew tolerance in seconds for exp/nbf validation. Default 0. |
|
|
throwOnError
boolean,
optional
|
edit
If true (default), throws on invalid token. If false, returns struct with valid, claims, error. Note: defaults to true unlike hash verify functions, since JWT validation failures typically indicate a security issue. |
true |
Usage Notes
editAlways restrict algorithms in production. Without the algorithms parameter, any algorithm is accepted. This can enable algorithm confusion attacks where an attacker switches from RS256 to HS256 and signs with the public key. Always specify which algorithms you expect:
claims = JwtVerify( token = token, key = secret, algorithms = "HS256" );
throwOnError behaviour: By default, invalid tokens throw an exception. Pass throwOnError=false to get a result struct instead — useful for login flows where you want to handle errors gracefully without try/catch:
- Valid:
{ valid: true, claims: { sub: "user123", ... } } - Invalid:
{ valid: false, error: "Token has expired" }
Clock skew: Distributed systems often have small clock differences. Use clockSkew (in seconds) to add tolerance when checking exp and nbf claims. A value of 30–60 seconds is typical.
Issuer and audience validation: Always validate these in production to ensure the token was issued by the expected provider and intended for your application.
Examples
edit// Verify an HMAC-signed token - returns the claims struct on success
secret = "my-super-secret-key-that-is-at-least-256-bits-long";
token = JwtSign( { sub: "user123", role: "admin" }, secret, "HS256" );
claims = JwtVerify( token = token, key = secret );
// claims.sub == "user123", claims.role == "admin"
// Verify an RSA-signed token with the public key
keyPair = GenerateKeyPair( "RSA-2048" );
token = JwtSign( claims = { sub: "user123" }, key = keyPair.private, algorithm = "RS256" );
claims = JwtVerify( token = token, key = keyPair.public );
// By default, invalid tokens throw an exception. Use throwOnError=false to get
// a result struct instead - useful for login flows where you want to handle errors gracefully
result = JwtVerify( token = token, key = "wrong-key", throwOnError = false );
// result.valid == false, result.error contains the error message
result = JwtVerify( token = token, key = keyPair.public, throwOnError = false );
// result.valid == true, result.claims contains the decoded claims
// Validate issuer and audience - throws if they don't match
token = JwtSign(
claims = { sub: "user123" },
key = secret,
algorithm = "HS256",
issuer = "https://myapp.com",
audience = "api"
);
claims = JwtVerify(
token = token,
key = secret,
issuer = "https://myapp.com",
audience = "api"
);
// Allow clock skew for expiration checks (useful for distributed systems)
// This allows tokens up to 60 seconds past their expiration
claims = JwtVerify( token = token, key = secret, clockSkew = 60 );
// Restrict which algorithms are accepted (security best practice)
claims = JwtVerify( token = token, key = secret, algorithms = [ "HS256", "HS384" ] );
// or as a comma-separated string
claims = JwtVerify( token = token, key = secret, algorithms = "HS256,HS384" );
// Positional arguments: token, key
claims = JwtVerify( token, secret );
See also
- Cryptography
- JwksLoad()
- JwtDecode()
- JwtSign()
- Search Issue Tracker open_in_new
- Search Lucee Test Cases open_in_new (good for further, detailed examples)