# JwtSign()

Creates a signed JSON Web Token (JWT) — a compact, URL-safe token commonly used for API authentication and authorization.

Sign with a shared secret (HMAC) or a private key (RSA, EC, Ed25519).

**Requires Extension:** [Crypto Extension](https://download.lucee.org/#17AB52DE-B300-A94B-E058FC978BE4542D)

```
JwtSign( claims=struct, key=any, algorithm=string, expiresIn=numeric, issuer=string, audience=string, kid=string );
```

**Returns:** string

# Arguments

| Argument | Type | Required | Description | Default |
|----------|------|----------|-------------|---------|
| claims | struct | Yes | JWT payload claims. Standard claims: sub, iss, aud, exp, nbf, iat, jti. Custom claims allowed. |  |
| key | any | Yes | Signing key. For HMAC: string or byte array. For RSA/EC: PEM string or Java PrivateKey object. |  |
| algorithm | string | No | JWS algorithm: HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512. Auto-detected if omitted. |  |
| expiresIn | numeric | No | Token expiration in seconds from now. Sets the 'exp' claim. |  |
| issuer | string | No | Token issuer. Sets the 'iss' claim (overrides claims struct). |  |
| audience | string | No | Token audience. Sets the 'aud' claim (overrides claims struct). |  |
| kid | string | No | Key ID to include in the JWT header. |  |

# Usage Notes

**Algorithm selection:** If you omit the `algorithm` parameter, it's auto-detected from the key type:

- RSA key → RS256
- P-256 → ES256, P-384 → ES384, P-521 → ES512
- Ed25519 → EdDSA

For HMAC (HS256/HS384/HS512), the algorithm must be specified explicitly since the key is just a string.

**Claims:** The `iat` (issued-at) claim is set automatically. If you set `exp` explicitly in your claims struct, it takes precedence over the `expiresIn` parameter.

**Key security:** For HMAC, your secret must be at least as long as the hash output (32 bytes for HS256, 48 for HS384, 64 for HS512). Short secrets are technically accepted but cryptographically weak.

For asymmetric algorithms (RS256, ES256, etc.), sign with the private key and verify with the public key using [JwtVerify()](jwtverify.md).

# Examples

```cfml
// Sign a JWT with a shared HMAC secret (simplest approach)
secret = "my-super-secret-key-that-is-at-least-256-bits-long";
token = JwtSign(
	claims = { sub: "user123", role: "admin" },
	key = secret,
	algorithm = "HS256"
);
// token is a string like: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOi...

// Set expiration and issuer
token = JwtSign(
	claims = { sub: "user123", role: "admin" },
	key = secret,
	algorithm = "HS256",
	expiresIn = 3600, // expires in 1 hour (seconds)
	issuer = "https://myapp.com",
	audience = "api"
);

// The iat (issued-at) claim is set automatically
// If you set exp explicitly in claims, it takes precedence over expiresIn

// Sign with RSA keys (asymmetric - sign with private, verify with public)
keyPair = GenerateKeyPair( "RSA-2048" );
token = JwtSign(
	claims = { sub: "user123", admin: true },
	key = keyPair.private,
	algorithm = "RS256"
);

// Sign with EC keys
keyPair = GenerateKeyPair( "P-256" );
token = JwtSign(
	claims = { sub: "user123" },
	key = keyPair.private,
	algorithm = "ES256"
);

// Algorithm auto-detection: if you omit algorithm, it's inferred from the key type
// RSA key -> RS256, P-256 -> ES256, P-384 -> ES384, P-521 -> ES512, Ed25519 -> EdDSA
keyPair = GenerateKeyPair( "Ed25519" );
token = JwtSign( claims = { sub: "user123" }, key = keyPair.private );
// Algorithm is automatically set to EdDSA

// Positional arguments are also supported: claims, key, algorithm
token = JwtSign( { sub: "user123" }, secret, "HS256" );
```







# Categories

[Cryptography](../../categories/crypto.md)

# See Also

[GenerateKeyPair()](generatekeypair.md), [JwtDecode()](jwtdecode.md), [JwtVerify()](jwtverify.md)