Skip to content

Getting Started

This guide walks you through installing Flarelette JWT Kit and creating your first authenticated token.

Installation

TypeScript/JavaScript

npm install @chrislyons-dev/flarelette-jwt

Requirements:

  • Node.js 18+ or Cloudflare Workers runtime
  • TypeScript 5.0+ (if using TypeScript)

Python

pip install flarelette-jwt

Requirements:

  • Cloudflare Workers Python runtime (Pyodide)
  • Python 3.11+ (Pyodide-based)

Cloudflare Workers Only

The Python package is designed exclusively for Cloudflare Workers Python runtime (Pyodide). It uses the js module to access WebCrypto APIs, which is not available in standard Python environments.

Your First Token

Step 1: Configure Environment

Create a .env file or configure your runtime environment:

# Required configuration
JWT_ISS=https://your-service.example.com
JWT_AUD=your-api-audience
JWT_SECRET_NAME=MY_JWT_SECRET

# Optional (shown with defaults)
JWT_TTL_SECONDS=900  # 15 minutes
JWT_LEEWAY=90        # 90 seconds clock skew tolerance

Step 2: Generate a Secret

For development:

npx flarelette-jwt-secret --len=64 --dotenv

This outputs a secure base64url-encoded secret:

JWT_SECRET=<64-byte-base64url-string>

For production (Cloudflare Workers):

# Store secret in Cloudflare
wrangler secret put MY_JWT_SECRET

# Configure wrangler.toml to reference it
[vars]
JWT_SECRET_NAME = "MY_JWT_SECRET"
JWT_ISS = "https://gateway.example.com"
JWT_AUD = "api.example.com"

Step 3: Sign Your First Token

TypeScript:

import { sign, verify } from '@chrislyons-dev/flarelette-jwt'

async function example() {
  // Create a token
  const token = await sign({
    sub: 'user123',
    permissions: ['read:data', 'write:data'],
    roles: ['user'],
  })

  console.log('Token:', token)

  // Verify the token
  const payload = await verify(token)
  if (payload) {
    console.log('Valid token for user:', payload.sub)
    console.log('Permissions:', payload.permissions)
  } else {
    console.log('Invalid token')
  }
}

Python:

from flarelette_jwt import sign, verify
import asyncio

async def example():
    # Create a token
    token = await sign({
        "sub": "user123",
        "permissions": ["read:data", "write:data"],
        "roles": ["user"]
    })

    print(f"Token: {token}")

    # Verify the token
    payload = await verify(token)
    if payload:
        print(f"Valid token for user: {payload.get('sub')}")
        print(f"Permissions: {payload.get('permissions')}")
    else:
        print("Invalid token")

asyncio.run(example())

Using High-Level Helpers

The kit provides high-level functions for common patterns.

Creating Tokens with Options

TypeScript:

import { createToken } from '@chrislyons-dev/flarelette-jwt'

const token = await createToken(
  {
    sub: 'user123',
    permissions: ['read:data'],
  },
  {
    ttlSeconds: 600, // Override default TTL
    aud: 'special-api', // Override default audience
  }
)

Python:

from flarelette_jwt import create_token

token = await create_token(
    {"sub": "user123", "permissions": ["read:data"]},
    ttl_seconds=600,  # Override default TTL
    aud="special-api"  # Override default audience
)

Authorization with Policies

TypeScript:

import { checkAuth, policy } from '@chrislyons-dev/flarelette-jwt'

const authPolicy = policy()
  .needAll('read:data', 'write:data')
  .rolesAny('admin', 'editor')
  .build()

const auth = await checkAuth(token, authPolicy)
if (auth) {
  console.log('Authorized user:', auth.sub)
  console.log('Permissions:', auth.permissions)
} else {
  console.log('Authorization failed')
}

Python:

from flarelette_jwt import check_auth, policy

auth_policy = (
    policy()
    .need_all('read:data', 'write:data')
    .roles_any('admin', 'editor')
    .build()
)

auth = await check_auth(token, **auth_policy)
if auth:
    print(f"Authorized user: {auth['sub']}")
    print(f"Permissions: {auth['permissions']}")
else:
    print("Authorization failed")

Next Steps

Common Issues

"JWT secret missing" Error

Cause: Environment variable not set or secret-name indirection not resolving.

Solution:

  1. Verify JWT_SECRET_NAME points to an actual environment variable
  2. For Workers, ensure you ran wrangler secret put <NAME>
  3. Check your wrangler.toml has the correct JWT_SECRET_NAME value

Algorithm Mismatch

Cause: Token was signed with one algorithm but consumer expects another.

Solution:

  • Verify both producer and consumer use the same environment configuration
  • Check which mode is active using the envMode() function (TypeScript) or mode() function (Python)
  • See Core Concepts for mode detection rules

Token Always Returns Null

Cause: Verification failure due to mismatched claims or expired token.

Solution:

  1. Check JWT_ISS and JWT_AUD match between producer and consumer
  2. Verify token hasn't expired (default 15 min TTL)
  3. Use parse() to inspect token contents without verification:
    import { parse } from '@chrislyons-dev/flarelette-jwt'
    const { header, payload } = parse(token)
    console.log('Algorithm:', header.alg)
    console.log('Issuer:', payload.iss)
    console.log('Expires:', new Date(payload.exp * 1000))