| Crates.io | pgjwt_rs |
| lib.rs | pgjwt_rs |
| version | 0.1.1 |
| created_at | 2025-10-26 01:44:22.236929+00 |
| updated_at | 2025-10-26 01:44:22.236929+00 |
| description | PostgreSQL extension for JWT verification with RS256 and Ed25519 support |
| homepage | https://github.com/vishvish/pgjwt_rs |
| repository | https://github.com/vishvish/pgjwt_rs |
| max_upload_size | |
| id | 1900862 |
| size | 140,279 |
PostgreSQL extension for JWT verification with RS256 and Ed25519 support.
This extension provides cryptographically secure JWT validation at the database layer using the Rust jsonwebtoken crate. Unlike the pure-SQL pgjwt extension which only supports HMAC algorithms, pgjwt_rs supports asymmetric key algorithms:
The popular pgjwt extension only supports HMAC-based JWT validation (HS256/384/512), which requires sharing secret keys between services. This is insecure for multi-service architectures because:
Asymmetric key cryptography with pgjwt_rs:
jwt_decode_payload(token TEXT) -> JSONBExtract the payload from a JWT without verification. Useful for getting the issuer to look up the correct public key.
SELECT jwt_decode_payload('eyJhbGc...');
-- Returns: {"iss": "auth_guard", "sub": "...", ...}
jwt_verify_rs256(token TEXT, public_key TEXT) -> TABLE(header JSONB, payload JSONB, valid BOOLEAN)Verify a JWT token using RS256 algorithm.
SELECT * FROM jwt_verify_rs256(
'eyJhbGciOiJSUzI1NiI...',
'-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----'
);
jwt_verify_ed25519(token TEXT, public_key TEXT) -> TABLE(header JSONB, payload JSONB, valid BOOLEAN)Verify a JWT token using Ed25519 algorithm.
SELECT * FROM jwt_verify_ed25519(
'eyJhbGciOiJFZERTQSI...',
'-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE=
-----END PUBLIC KEY-----'
);
jwt_verify(token TEXT, public_key TEXT, algorithm TEXT) -> TABLE(header JSONB, payload JSONB, valid BOOLEAN)Verify a JWT token with the specified algorithm ('RS256' or 'EdDSA').
SELECT * FROM jwt_verify(
'eyJhbGc...',
'-----BEGIN PUBLIC KEY-----...',
'RS256'
);
postgresql-server-dev on Debian/Ubuntu, postgresql-devel on RHEL)cargo-pgrx version 0.16.1# Install cargo-pgrx (matching pgrx version)
cargo install --locked cargo-pgrx --version 0.16.1
# Initialize pgrx for PostgreSQL 18 (one-time setup)
cargo pgrx init --pg18 $(which pg_config)
# Build and package the extension
chmod +x package.sh
./package.sh
# Install (as superuser)
sudo cp pkg/usr/lib/postgresql/pgjwt_rs.so $(pg_config --pkglibdir)/
sudo cp pkg/usr/share/postgresql/extension/* $(pg_config --sharedir)/extension/
On macOS, the library extension will be .dylib instead of .so.
This repository publishes release artifacts when you push a version tag. Steps:
Cargo.toml.v0.1.0.The CI release workflow will build the extension and attach a tarball to the GitHub Release.
CREATE EXTENSION pgjwt_rs;
-- Create a function to validate service JWTs
CREATE OR REPLACE FUNCTION validate_service_jwt(token TEXT)
RETURNS TABLE(
service_name TEXT,
tenant_id UUID,
scopes TEXT[],
valid BOOLEAN
) AS $$
DECLARE
payload JSONB;
jwt_result RECORD;
public_key_pem TEXT;
algorithm TEXT;
BEGIN
-- Get unverified payload to find issuer
payload := jwt_decode_payload(token);
-- Look up public key for the claimed service
SELECT pk.public_key, pk.algorithm
INTO public_key_pem, algorithm
FROM auth_schema.jwt_keys pk
WHERE pk.service_name = payload->>'iss'
AND pk.is_active = true;
IF public_key_pem IS NULL THEN
RETURN QUERY SELECT NULL::TEXT, NULL::UUID, NULL::TEXT[], FALSE;
RETURN;
END IF;
-- Verify JWT with correct algorithm
SELECT * INTO jwt_result
FROM jwt_verify(token, public_key_pem, algorithm);
IF jwt_result.valid THEN
payload := jwt_result.payload;
RETURN QUERY SELECT
(payload->>'iss')::TEXT,
(payload->>'tenant_id')::UUID,
ARRAY(SELECT jsonb_array_elements_text(payload->'scopes')),
TRUE;
ELSE
RETURN QUERY SELECT NULL::TEXT, NULL::UUID, NULL::TEXT[], FALSE;
END IF;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
This extension focuses on cryptographic verification and intentionally defers claim validation to SQL so you can express policy close to data:
exp) are not enforced by the extension. Tokens without exp will be accepted at the cryptographic level.exp, nbf, and aud checks are disabled in Rust and can be applied in SQL, e.g. by checking now() < to_timestamp((payload->>'exp')::bigint) if present.Rationale: application-specific TTLs, audiences, and clock tolerance are often best handled in database logic or service code rather than hard-coded in the extension.
Built with Rust and compiled to native code, pgjwt_rs provides:
First, generate test key pairs:
# Generate RS256 test keys
openssl genrsa -out test_private.pem 2048
openssl rsa -in test_private.pem -pubout -out test_public.pem
# Generate Ed25519 test keys
openssl genpkey -algorithm ed25519 -out test_ed25519_private.pem
openssl pkey -in test_ed25519_private.pem -pubout -out test_ed25519_public.pem
Then run tests:
# Run Rust unit tests (with coverage)
cargo install cargo-llvm-cov
cargo llvm-cov --html
# Run PostgreSQL integration tests
cargo pgrx test pg18
# Run with test database (opens psql with extension loaded)
cargo pgrx run pg18
# Build for specific PostgreSQL version
cargo build --release --features pg18 --no-default-features
AGPL-3.0-only - see LICENSE file for details.
Built with: