# JWT +

{% hint style="danger" %}
This module is only available to [+/++ subscribers](https://www.boxlang.io/plans) but can be installed in conjunction with the [`bx-plus` Module](/boxlang-+-++/modules/bx-plus.md) with a limited trial.
{% endhint %}

The `bx-jwt` module is a production-ready BoxLang library for creating, signing, verifying, encrypting, and decrypting JSON Web Tokens (JWT/JWE). It implements:

* **JWS** (JSON Web Signature) — signed tokens using HMAC, RSA, or EC keys
* **JWE** (JSON Web Encryption) — encrypted tokens using RSA or symmetric keys
* **RFC 7518** — JSON Web Algorithms
* **RFC 7519** — JSON Web Token

## 🚀 Key Features

* 🔑 **HMAC Signing** — HS256, HS384, HS512 with RFC 7518 minimum key length enforcement
* 🔐 **RSA Signing** — RS256, RS384, RS512
* 📐 **EC Signing** — ES256 (P-256), ES384 (P-384), ES512 (P-521)
* 🔒 **JWE Encryption** — RSA-OAEP-256, direct symmetric (`dir`) with A256GCM
* 🗝️ **Named Key Registry** — register keys by name in module config; reference by name in BIFs
* 🏗️ **Fluent Builder** — `jwtNew()` returns a chainable builder for elegant token creation
* ♻️ **Token Refresh** — `jwtRefresh()` re-issues tokens with fresh time claims
* 🔓 **Decode Without Verify** — `jwtDecode()` to inspect headers/claims before choosing a key
* ✅ **Boolean Validation** — `jwtValidate()` returns true/false without throwing
* 🔧 **Key Generation** — `jwtGenerateSecret()` and `jwtGenerateKeyPair()` helpers
* ⏱️ **Clock Skew** — configurable tolerance for `exp` / `nbf` validation
* 📋 **Default Claims** — auto-inject `iss`, `aud`, `exp`, `iat`, `jti` from module settings
* 🚫 **`alg:none` Protection** — unconditionally rejects unsigned tokens
* 📋 **Algorithm Allowlist** — restrict permitted algorithms via module settings

## 📦 Installation

```bash
# Operating Systems using the Quick Installer
install-bx-module bx-jwt

# Using CommandBox for web servers
box install bx-jwt
```

## 🎯 Registered BIFs

This module registers the following Built-In Functions (BIFs):

| Function               | Purpose                                                                | Documentation                                                                                         |
| ---------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `jwtNew()`             | Returns a fluent `JwtBuilder` for chainable token construction         | [Fluent Builder](/boxlang-+-++/modules/bx-jwt/fluent-builder.md)                                      |
| `jwtCreate()`          | Signs a payload and returns a compact JWS token string                 | [JWTCreate](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtcreate.md)                   |
| `jwtVerify()`          | Verifies a JWS signature & claims; throws on failure                   | [JWTVerify](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtverify.md)                   |
| `jwtValidate()`        | Like `jwtVerify()` but returns true/false instead of throwing          | [JWTValidate](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtvalidate.md)               |
| `jwtDecode()`          | Decodes a JWS token **without** verifying the signature                | [JWTDecode](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtdecode.md)                   |
| `jwtRefresh()`         | Re-issues a token with fresh `iat`, `jti`, optional new `exp`          | [JWTRefresh](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtrefresh.md)                 |
| `jwtEncrypt()`         | Encrypts a payload as a compact JWE token                              | [JWTEncrypt](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtencrypt.md)                 |
| `jwtDecrypt()`         | Decrypts a JWE token and returns the claims struct                     | [JWTDecrypt](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtdecrypt.md)                 |
| `jwtGenerateSecret()`  | Generates a cryptographically random Base64 HMAC secret (default: 256) | [JWTGenerateSecret](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtgeneratesecret.md)   |
| `jwtGenerateKeyPair()` | Generates an RSA or EC key pair as PEM strings                         | [JWTGenerateKeyPair](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions/jwtgeneratekeypair.md) |

## ⚡ Quick Start

### Sign & Verify (HMAC)

```javascript
secret  = jwtGenerateSecret( 256 );
token   = jwtCreate( { sub: "user-123", iss: "my-api", roles: [ "admin" ] }, secret, "HS256" );
payload = jwtVerify( token, secret, "HS256" );
writeOutput( payload.sub ); // user-123
```

### Sign & Verify (RSA)

```javascript
keys    = jwtGenerateKeyPair( "RS256" );
token   = jwtCreate( { sub: "user-123" }, keys.privateKey, "RS256" );
payload = jwtVerify( token, keys.publicKey, "RS256" );
```

### Fluent Builder

```javascript
token = jwtNew()
    .subject( "user-123" )
    .issuer( "my-api" )
    .audience( "mobile-client" )
    .claim( "roles", [ "admin", "user" ] )
    .expireIn( 3600 )
    .header( "kid", "v1" )
    .sign( secret, "HS256" );
```

### Encrypt & Decrypt (JWE)

```javascript
token   = jwtEncrypt( { sub: "user-123", ssn: "123-45-6789" }, secret, { keyAlgorithm: "dir", encAlgorithm: "A256GCM" } );
payload = jwtDecrypt( token, secret, { keyAlgorithm: "dir", encAlgorithm: "A256GCM" } );
```

## 📚 Usage Guides

* [Signing (JWS)](/boxlang-+-++/modules/bx-jwt/signing-jws.md) — HMAC, RSA, and EC signing patterns
* [Encryption (JWE)](/boxlang-+-++/modules/bx-jwt/encryption-jwe.md) — RSA-OAEP and symmetric encryption
* [Key Management](/boxlang-+-++/modules/bx-jwt/key-management.md) — the named key registry and runtime keys
* [Fluent Builder](/boxlang-+-++/modules/bx-jwt/fluent-builder.md) — `jwtNew()` chainable API walkthrough
* [Key Rotation](/boxlang-+-++/modules/bx-jwt/key-rotation.md) — `kid`-based rotation patterns
* [Security Best Practices](/boxlang-+-++/modules/bx-jwt/security-best-practices.md) — allowlists, key sizes, clock skew
* [Configuration](/boxlang-+-++/modules/bx-jwt/configuration.md) — full ModuleConfig settings reference

## 🔌 Reference

* [Built-In Functions](/boxlang-+-++/modules/bx-jwt/reference/built-in-functions.md) — one page per BIF
* [Fluent API (JwtBuilder)](/boxlang-+-++/modules/bx-jwt/reference/fluent-api.md) — chainable methods reference
* [Algorithms](/boxlang-+-++/modules/bx-jwt/reference/algorithms.md) — supported JWS/JWE algorithm tables

## ✅ Requirements

* **BoxLang Runtime** 1.0.0+
* **BoxLang+ License** ([learn more](https://www.boxlang.io/plans))

## 📄 License

Licensed under the [BoxLang Plus Subscription License](https://www.boxlang.io/license).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://boxlang.ortusbooks.com/boxlang-+-++/modules/bx-jwt.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
