auth
Authentication and authorisation - password hashing, JWT, OAuth 2.0, API keys, TOTP 2FA, sessions, RBAC, rate limiting, and account lockout.
Load with: use auth
What this module does
auth covers the full authentication surface for a web app or API.
Hash and verify passwords with bcrypt, argon2, or scrypt. Issue and verify JWTs
with HS256 and configurable expiry. Build OAuth 2.0 flows for Google, GitHub, and Discord.
Generate and hash API keys. Handle TOTP two-factor codes. Manage login sessions
with lockout and rate limiting. Check user permissions against roles.
Write middleware that handles Bearer JWT, ApiKey, and session auth in one handler.
Most functions are overloaded - authp, authj, autho,
authl, authc, authr each have multiple signatures
that do different things depending on their arguments.
Quick example
use auth
# Hash a password (bcrypt by default)
hashed = authp("hunter2", nil)
# Verify it
ok = authp("hunter2", hashed)
prn(ok) # tru
# Issue a JWT
token = authj({sub: "user123", role: "admin"}, "my-secret", {expires: 3600})
# Verify a JWT
result = authj(token, "my-secret")
prn(result.valid) # tru
prn(result.payload) # {sub: "user123", role: "admin", ...}
Functions
Password hashing
authp(password, algorithm)
Hashes a password using the given algorithm. Accepts "bcrypt" (default if nil), "argon2", or "scrypt". Falls back to bcrypt for unknown algorithms. Calls the corresponding host native (__auth_bcrypt_hash etc.).
authp(password, hash)
Verifies a plain-text password against a stored hash. Calls __auth_password_verify. Returns tru on match.
JWT
authj(payload, secret, options)
Issues a signed HS256 JWT. The payload object is merged with standard claims:
iat (issued-at, in seconds), a random jti (JWT ID, first 16 chars of a SHA-256 hash).
Options can include:
expires- seconds until expiry (setsexp)not_before- seconds until the token becomes valid (setsnbf)issuer- setsissaudience- setsaud
Delegates to jwt.jwtwe.
authj(token, secret)
Verifies a JWT. Checks the signature via jwt.jwtve and validates exp against the current time. Returns {valid: tru, payload} or {valid: fls, error}.
OAuth 2.0
autho(provider, client_id, client_secret, options)
Creates an OAuth 2.0 config object with provider, client_id, client_secret, auth_url, token_url, scopes (default ["openid", "profile", "email"]), and redirect_uri.
autho(config, state)
Builds the OAuth authorisation URL to redirect the user to. Encodes client_id, response_type: "code", redirect_uri, scope, and state as query parameters.
autho(config, code)
Exchanges an authorisation code for tokens by POSTing to token_url. On success, also fetches user info via the provider-specific endpoint and returns {tokens, user}. Returns {error} if the exchange fails.
autho(provider, access_token)
Fetches user info from a provider's userinfo endpoint using an access token. Supports "google", "github", and "discord". Returns the parsed user object or nil for unknown providers.
API keys
autha(prefix)
Generates a new API key in the format {prefix}_{64-char-hex}. The hex is two concatenated SHA-256 hashes of random numbers. Default prefix is "sk".
autha(key)
Returns a SHA-256 hash of the API key for safe storage. Store this hash, not the key itself.
Two-factor authentication (TOTP)
autht()
Generates a new TOTP secret via __auth_totp_generate_secret().
autht(secret, account, issuer)
Generates a QR code URI for a TOTP secret via totp.totpq. Feed this to a QR code renderer for the user to scan with their authenticator app.
autht(token, secret)
Verifies a 6-digit TOTP token against a secret via totp.totpv. Returns tru if valid.
Sessions
authl(session, user, options)
Logs a user in via a session. Checks the failed login count against max_attempts (default 5) - returns {success: fls, error: "Account locked"} if exceeded. Otherwise stores user_id and user in the session, resets the failed counter, and optionally sets a remember flag. Returns {success: tru, user}.
authl(session)
Logs out - deletes user_id and user from the session and regenerates the session ID.
authc(session)
Checks whether the session has an authenticated user. Returns {authenticated: tru, user} or {authenticated: fls}.
Permissions and roles (RBAC)
authc(user, permission)
Checks if user has a given permission. Checks the user's direct permissions list first, then checks each role in user.roles via authroleperms. Returns tru or fls.
authr(role)
Returns the permission list for a built-in role. Built-in roles: admin → ["*"], user → ["read", "write"], guest → ["read"]. Returns [] for unknown roles.
Middleware
authm(options)
Returns a middleware function (req, res, next) that handles three auth strategies in order:
- Bearer JWT - reads
Authorization: Bearer {token}, verifies it, and setsreq.userandreq.auth_type = "jwt". - ApiKey - reads
Authorization: ApiKey {key}, calls anoptions.validate_api_keyfunction if provided, and setsreq.userandreq.auth_type = "apikey". - Session - checks
req.session.user_idand setsreq.userandreq.auth_type = "session".
If none match and options.required is tru, responds with 401. Options: secret (JWT secret), required (bool), validate_api_key (function).
Rate limiting and account lockout
authr(store, identifier, max_attempts, window_secs)
Rate-limits auth attempts for an identifier (e.g. username or IP). Stores the count under key "auth:{identifier}" in store via redis.rrdrl.
authl(session, max_attempts)
Checks whether the session's account is locked. Returns {locked: tru, remaining: 0} if failed logins have reached max_attempts, or {locked: fls, remaining: n} otherwise.
authl(session)
Increments the failed_logins counter in the session. Call this after a failed login attempt.
authl(session)
Resets the failed_logins counter to 0. Call this after a successful login.
Notes
authp,authj,autho,authl,authc, andauthrare all overloaded - which behaviour runs depends on the number and types of arguments.- Password hashing for bcrypt, argon2, and scrypt relies on host natives (
__auth_*). - The middleware (
authm) depends onsrvfor request/response helpers and onjwtfor token verification. - OAuth user-info fetching depends on
netandjsn. - Rate limiting depends on
redis.