Skip to main content

Module jwt

Module jwt 

Source
Expand description

JSON Web Tokens (HS256) for API clients.

For API clients that cannot keep a session cookie (mobile apps, scripts): they send Authorization: Bearer <token> instead. token_from also reads it from a query parameter or a cookie, trying several Locations in order (Loco’s auth.jwt.location).

The signing key is derived from the SECRET_KEY_BASE Worker secret (HMAC-SHA256 of a fixed label), so apps have one secret to create, upload and rotate: rotating it signs everyone out of sessions and tokens at once, unless the old value is kept in SECRET_KEY_BASE_PREVIOUS for a while. Tokens carry only the subject (usually the user id), iat and exp; decode rejects expired tokens, bad signatures and any alg other than ALGORITHM (including none) with Error::Unauthorized (401). Keep TTLs short (ocre g auth issues one-hour tokens) and use crate::token API keys for long-lived access.

Cost: one HMAC-SHA256 over a few hundred bytes; no D1, KV or other binding is used.

encode and decode read the key from the Worker’s environment; encode_with and decode_with take a Key and run anywhere.

use axum::{extract::State, http::{HeaderMap, Uri}};
use ocre::{Ctx, Error, Result, jwt::{self, Claims, Location}};

// POST /api/auth/token, after checking the password:
async fn token(State(ctx): State<Ctx>) -> Result<String> {
    let user_id = 42;
    jwt::encode(&ctx, &Claims::new(user_id.to_string(), 3600))
}

// Later, from `Authorization: Bearer <token>` or, for browsers, a cookie:
async fn me(State(ctx): State<Ctx>, headers: HeaderMap, uri: Uri) -> Result<String> {
    let locations = [Location::Bearer, Location::Cookie("token")];
    let token = jwt::token_from(&headers, &uri, &locations).ok_or(Error::Unauthorized)?;
    let claims = jwt::decode(&ctx, &token)?; // 401 when invalid or expired
    let user_id: i64 = claims.sub.parse().map_err(|_| Error::Unauthorized)?;
    Ok(user_id.to_string())
}

Structs§

Claims
The payload of a token: who it is for and when it expires.
Key
An HS256 signing key, derived from SECRET_KEY_BASE.

Enums§

Location
Where token_from looks for a token (Loco’s auth.jwt.location).

Constants§

ALGORITHM
The only JWT algorithm Ocre signs with and accepts: HS256 (HMAC-SHA256).

Functions§

decode
Verifies a token from a client with the key derived from SECRET_KEY_BASE and returns its claims.
decode_with
Verifies token with key at Unix time now (seconds) and returns its claims.
encode
Signs claims with the HS256 key derived from the SECRET_KEY_BASE Worker secret.
encode_with
Signs claims with key and returns the compact token header.payload.signature.
token_from
The token of the first locations entry that has a non-empty one.