---
title: The pg_session_jwt extension
subtitle: Handle authenticated sessions through JWTs in Postgres
enableTableOfContents: true
updatedOn: '2025-12-12T17:42:01.028Z'
---
Neon Data API
Custom authentication providers
Row-Level Security (RLS)
pg_session_jwt on GitHub
The `pg_session_jwt` extension is a Postgres extension designed to handle authenticated sessions through JSON Web Tokens (JWTs). When configured with a JWK (JSON Web Key), it verifies JWT authenticity. When operating without a JWK, it falls back to using PostgREST-compatible JWT claims.
This extension powers the [Neon Data API](/docs/data-api/overview), enabling secure session management and Row-Level Security (RLS) based on user identity.
## Features
- **JWT session initialization** using a JWK (JSON Web Key) for secure JWT validation
- **Flexible authentication modes** — use either JWK-validated JWTs or PostgREST-compatible JWT claims
- **User ID retrieval** directly from the database for use in RLS policies
- **JSONB-based storage** and retrieval of session information
## How it works
The extension can operate in two modes:
### With JWK validation
When a JWK is configured, the extension validates JWT signatures and extracts user information from verified tokens. This is the mode used by the Neon Data API.
### With PostgREST-compatible JWT claims
When operating without a JWK, the extension works with PostgREST-compatible JWT claims via the `request.jwt.claims` parameter. This provides compatibility with PostgREST's JWT handling.
## Functions
The `pg_session_jwt` extension provides functions in the `auth` schema:
### auth.user_id()
Returns the user ID (`sub` claim) from the current session's JWT.
```sql
SELECT auth.user_id();
```
This function is commonly used in RLS policies to filter data by the authenticated user:
```sql
CREATE POLICY "Users can only see their own data"
ON todos
FOR SELECT
USING (user_id = auth.user_id());
```
### auth.session()
Returns the entire JWT payload as JSONB, giving you access to all claims in the token.
```sql
SELECT auth.session();
```
### auth.jwt()
Alias for `auth.session()`.
### auth.uid()
Similar to `auth.user_id()` but returns UUID type. Expects the `sub` claim to be a valid UUID, otherwise returns NULL.
```sql
SELECT auth.uid();
```
## Usage with Neon Data API
The `pg_session_jwt` extension is automatically configured when you enable the [Neon Data API](/docs/data-api/overview). The Data API handles JWT validation using your configured authentication provider's JWKS URL.
When making requests to the Data API, include your JWT in the `Authorization` header:
```http
GET https://your-project.data.neon.tech/v1/todos
Authorization: Bearer
```
The Data API validates the token and makes the user identity available via `auth.user_id()` for your RLS policies.
## Usage with custom setups
For custom implementations outside of the Neon Data API, you can configure the extension manually:
### Initialize with JWK
Set the JWK at connection time using libpq options:
```bash
export PGOPTIONS="-c pg_session_jwt.jwk=$MY_JWK"
```
Then in your session:
```sql
-- Initialize the session with the configured JWK
SELECT auth.init();
-- Set the JWT for the current session
SELECT auth.jwt_session_init('your.jwt.token');
-- Now you can use auth functions
SELECT auth.user_id();
```
### Using PostgREST-compatible claims
When no JWK is configured, set claims via the `request.jwt.claims` parameter:
```sql
SET request.jwt.claims = '{"sub": "user-123", "role": "authenticated"}';
SELECT auth.user_id(); -- Returns 'user-123'
```
When using the fallback mode without JWK validation, `request.jwt.claims` is a regular Postgres parameter that can be modified by any database user. Ensure your application sets these claims securely before executing user queries.
## References
- [pg_session_jwt on GitHub](https://github.com/neondatabase/pg_session_jwt)
- [Neon Data API documentation](/docs/data-api/overview)
- [Custom authentication providers](/docs/data-api/custom-authentication-providers)
- [Row-Level Security guide](/docs/guides/neon-rls)