Appearance
JWT validator
Validates a JSON Web Token: from Http authentication (type 2 JWT, or Bearer), or a token sent as a TextRecord. It checks the signature with a shared secret, a public key or the keys of an OpenID Connect provider (Entra ID, Auth0, Keycloak, ...), then the lifetime, issuer, audience and required claims, and puts the claims into the flow metadata. An invalid token raises an error that the Http listener answers with 401 (403 for a missing required claim).
Pins
| Pin | Kind | Types | Description |
|---|---|---|---|
| Input | input | Viaducta.Plugins.Http.Types.HttpAuthentificationData, Viaducta.Plugins.TextPlugin.Types.TextRecord | Uses Jwt, else Token; or the TextRecord Value (Bearer in front is allowed). |
| Output | output | Viaducta.Plugins.JWTValidator.JwtClaimsData | Optional. The claims of a valid token: UserName, UserId, Email, Issuer, Audience, IssuedAt, ValidTo, Claims, Token. |
Configuration
| Field | Type | Default | Description |
|---|---|---|---|
KeySource | int | 0 | 0 the SigningKey below; 1 OpenID Connect provider (MetadataAddress is the authority or its .well-known/openid-configuration URL); 2 JWKS URL (MetadataAddress). |
MetadataAddress | string | For KeySource 1 and 2. HTTPS only, plain http is allowed for localhost. | |
Algorithm | int | 0 | KeySource 0: the algorithm the issuer signs with, the same numbers as in the JWT issuer (0 HS256 ... 11 PS512). Other algorithms are rejected. With 1 and 2 the RS*, ES* and PS* algorithms are accepted. |
SigningKey | string | KeySource 0: HS* the shared secret of the JWT issuer; RS*, ES*, PS* the public key (or certificate) in PEM format. | |
KeyEncoding | int | 0 | Shared secret only: 0 text (UTF-8), 1 Base64. |
ValidateLifetime | boolean | true | Rejects expired tokens, tokens not valid yet and tokens without exp. |
ClockSkew | string | 00:01:00 | Tolerance for clock differences in the lifetime check, up to one hour. Empty means one minute. |
ValidateIssuer | boolean | true | Checks iss. Always on when Issuer is set. With an OpenID Connect provider and an empty Issuer the provider's issuer is expected; otherwise Issuer must be set. |
Issuer | string | Expected iss, comma separated for several. | |
ValidateAudience | boolean | false | Checks aud. Always on when Audience is set; on without an Audience stops the flow at start. |
Audience | string | Expected aud, comma separated for several. | |
TokenUse | int | 0 | 0 Access: refresh tokens of the JWT issuer (token_use = refresh) are rejected. 1 Refresh: only refresh tokens, for a refresh endpoint. 2 Any. |
RequiredClaims | string | Claims the token must have, else 403. Entries separated by ; are all required; an entry is a claim name (must be present) or name=value with | between accepted values, e.g. role=admin|editor; scope=orders.read. scope and scp are matched per space separated scope. |
Behaviour
- Status codes:
401for a missing, malformed, expired or untrusted token (withWWW-Authenticate: Bearer error="invalid_token"),403for a missing required claim (error="insufficient_scope"),503when the provider's keys cannot be loaded. - The error message names the reason (
The token has expired,The token signature is not valid,The token issuer is not accepted, ...) without the library's diagnostics. - On success the
UserInfometadata (Viaducta.Plugins.Http.Types.UserInfoMetaData) is filled:UserName=sub,Email=emailclaim,UserId=userIdclaim,Token= the token,Claims= all claims of the token (includingiss,aud,exp, ...). A claim with several values (roles, several audiences) is written as a JSON array, e.g.["admin","editor"].ApiKeyset by Http authentication is kept. - Provider keys are cached for 12 hours. A token signed with an unknown key (
kid) reloads them at most every 5 minutes, so key rotation works without a restart. When a reload fails the old keys keep working. - A wrong configuration (missing key, unreadable PEM, missing
Issuer/Audiencefor an enabled check, http metadata address) stops the flow at start.
Notes
- Flows saved with older versions keep their stored check settings; turn on
ValidateLifetimewhere it is off. - In the Http listener's authentication branch the
UserInfometadata reaches theOutputbranch when the validator is the only connection of Http authentication. With several connections each gets its own copy of the metadata. - Use an expression setting (
=Secrets.JwtKey) forSigningKey.
Example
json
{ "ValidateLifetime": true, "ValidateIssuer": true, "Issuer": "my-api", "Audience": "my-clients", "SigningKey": "=Secrets.JwtKey", "RequiredClaims": "role=admin|editor" }json
{ "KeySource": 1, "MetadataAddress": "https://login.microsoftonline.com/{tenant}/v2.0", "Audience": "api://my-api", "RequiredClaims": "scp=orders.read" }Http listener (Authentificate) → Http authentification (AuthentificationType 2) → JWT validator