A comprehensive Client/Server OAuth2 library for Bleumoon.
  • Luau 99.1%
  • Nix 0.9%
Find a file
reinitialized 4ceb43d084
fix: move entry logic to src/init.luau for correct alias resolution
BleuMoon's init.luau parent-directory context resolution causes @src
aliases in root init.luau to resolve against the parent directory's
.luaurc instead of the package's own .luaurc. This makes @src point to
the consumer project's src/ instead of the package's src/.

Fix: move all entry logic to src/init.luau where the parent-directory
context resolves to the package root (which has the correct .luaurc).
Root init.luau becomes a thin proxy: require("./bleuauth/src").
2026-03-19 17:10:16 -05:00
.forgejo/workflows Initial commit 2026-02-12 21:20:42 -06:00
.github fix type resolution issues 2026-03-10 15:20:30 -05:00
.vscode release 0.3.3 2026-03-18 11:25:28 -05:00
docs fix type resolution issues 2026-03-10 15:20:30 -05:00
src fix: move entry logic to src/init.luau for correct alias resolution 2026-03-19 17:10:16 -05:00
tests release 0.3.2 2026-03-06 14:55:52 -06:00
.editorconfig Initial commit 2026-02-12 21:20:42 -06:00
.gitignore release 0.2.5 2026-03-02 17:36:23 -06:00
.luaurc release 0.3.3 2026-03-18 11:25:28 -05:00
bleumoon.lock fix type resolution issues 2026-03-10 15:20:30 -05:00
bleumoon.toml fix: move entry logic to src/init.luau for correct alias resolution 2026-03-19 17:10:16 -05:00
CHANGELOG.md fix: move entry logic to src/init.luau for correct alias resolution 2026-03-19 17:10:16 -05:00
flake.lock release 0.3.3 2026-03-18 11:25:28 -05:00
flake.nix fix flake issue 2026-03-19 11:56:49 -05:00
init.luau fix: move entry logic to src/init.luau for correct alias resolution 2026-03-19 17:10:16 -05:00
LICENSE Initial commit 2026-02-12 21:20:42 -06:00
README.md release v0.2.3 2026-02-18 17:25:24 -06:00
stylua.toml Initial commit 2026-02-12 21:20:42 -06:00

BleuAuth

A comprehensive OAuth2 Client/Server library for BleuMoon — the standalone Luau runtime.

Features

  • OAuth2 Server — Authorization endpoint, token endpoint, introspection (RFC 7662), revocation (RFC 7009), and discovery (RFC 8414)
  • OAuth2 Client — Authorization Code (with PKCE), Client Credentials, and Refresh Token grants
  • Resource Server Middleware — Bearer token validation via JWT verification and token introspection
  • JWT — Encode, decode, and verify JWTs (RFC 7519/7515/7518) with HMAC (HS256/384/512) and asymmetric (RS256/ES256/EdDSA) algorithms
  • JWK/JWKS — Key pair generation and JSON Web Key Set endpoints (RFC 7517)
  • PKCE — Proof Key for Code Exchange (RFC 7636) with S256 method, required by default (OAuth 2.1)
  • Pluggable Storage — In-memory (testing) and SQLite (production) storage backends

Prerequisites

Tip: If you have Nix with flakes enabled, both tools are provided automatically via nix develop.

Quick Start

local bleuauth = require("./src")

-- Create an in-memory storage backend
local storage = bleuauth.createMemoryStorage()

-- Generate an RSA key pair for JWT signing
local keys = bleuauth.generateKeyPair("RS256")

-- Register a client
storage:createClient({
    clientId = "my-app",
    clientSecret = "secret",
    redirectUris = { "https://myapp.example.com/callback" },
    grantTypes = { "authorization_code", "client_credentials" },
    scopes = { "read", "write" },
    clientType = "confidential",
    createdAt = os.time(),
})

-- Create and start the OAuth2 server
local server = bleuauth.createServer({
    issuer = "https://auth.example.com",
    storage = storage,
    signingKey = keys.privateKey,
    signingAlgorithm = "RS256",
    signingKid = keys.kid,
    publicKey = keys.publicKey,
    supportedScopes = { "read", "write" },
    authenticateUser = function(request, clientId, scope)
        -- Your user authentication logic here
        return "user-id-123"
    end,
})

server:start(8080)

Architecture

src/
├── init.luau              # Library entry point (exports everything)
├── types/init.luau        # All shared type definitions
├── utils/
│   ├── init.luau          # Utility re-exports
│   ├── pkce.luau          # PKCE utilities (RFC 7636)
│   └── errors.luau        # OAuth2 error builders (RFC 6749 §5.2)
├── jwt/
│   ├── init.luau          # JWT encode/decode/verify
│   ├── algorithms.luau    # Algorithm implementations
│   └── jwk.luau           # JWK/JWKS key management
├── server/
│   ├── init.luau          # Server factory with HTTP binding
│   ├── config.luau        # Configuration defaults & validation
│   ├── authorize.luau     # Authorization endpoint (GET /authorize)
│   ├── token.luau         # Token endpoint (POST /token)
│   ├── introspect.luau    # Introspection endpoint (POST /introspect)
│   ├── revoke.luau        # Revocation endpoint (POST /revoke)
│   └── discovery.luau     # Metadata & JWKS endpoints
├── client/init.luau       # OAuth2 client implementation
├── middleware/init.luau    # Resource server middleware
└── storage/
    ├── init.luau          # Storage re-exports
    ├── memory.luau        # In-memory storage (testing)
    └── sqlite.luau        # SQLite storage (production)

Note: Base64url encoding and URL/form encoding utilities live in the bleuutils package and are re-exported from there.

Supported Grant Types

Grant Type RFC Description
Authorization Code RFC 6749 §4.1 For server-side web apps (with mandatory PKCE)
Client Credentials RFC 6749 §4.4 For machine-to-machine communication
Refresh Token RFC 6749 §6 For obtaining new access tokens

Note: Implicit grant and ROPC are intentionally omitted per OAuth 2.1 recommendations.

JWT Algorithms

Algorithm Type Status
HS256 / HS384 / HS512 HMAC Fully working
RS256 RSA-SHA256 Fully working
ES256 ECDSA P-256 Fully working
EdDSA Ed25519 Fully working

Running Tests

bleumoon run tests/init

Formatting

stylua --check .   # Check
stylua .           # Apply

Known Issues

  • crypto.randomBuffer() returns a string (not a buffer type) in BleuMoon v2.0.x. BleuAuth uses crypto.randomBytes() instead.

License

This project is licensed under the MIT License.