Secure your data with Auth0 and Neon Authorize
Implement Row-level Security policies in Postgres using Auth0 and Neon Authorize
Sample project
Related docs
Use Auth0 with Neon Authorize to add secure, database-level authorization to your application. This guide assumes you already have an application using Auth0 for user authentication. It shows you how to integrate Auth0 with Neon Authorize, then provides sample Row-level Security (RLS) policies to help you model your own application schema.
How it works
Auth0 handles user authentication by generating JSON Web Tokens (JWTs), which are securely passed to Neon Authorize. Neon Authorize validates these tokens and uses the embedded user identity metadata to enforce the Row-Level Security policies that you define directly in Postgres, securing database queries based on that user identity. This authorization flow is made possible using the Postgres extension pg_session_jwt, which you'll install as part of this guide.
Prerequisites
To follow along with this guide, you will need:
- A Neon account. Sign up at Neon if you don't have one.
- An Auth0 account with an existing application (e.g., a todos app) that uses Auth0 for user authentication. If you don't have an app, check our demo for similar schema and policies in action.
Integrate Auth0 with Neon Authorize
In this first set of steps, we'll integrate Auth0 as an authorization provider in Neon. When these steps are complete, Auth0 will start passing JWTs to your Neon database, which you can then use to create policies.
1. Get your Auth0 JWKS URL
To integrate Auth0 with Neon, you'll need to provide your Auth0 JWKS (JSON Web Key Set) URL. This URL provides the public keys needed to verify the signatures of JWTs issued by your Auth0 application. The URL follows this format.
First, open the Settings for your application in the Auth0 dashboard:
Copy your Domain and use that to form your JWKS URL. For example, here's the Auth0 default domain (automatically assigned to your Auth0 tenant when you create an account).
2. Add Auth0 as an authorization provider in the Neon Console
Once you have the JWKS URL, go to the Neon Console and add Auth0 as an authentication provider under the Authorize page. Paste your copied URL and Auth0 will be automatically recognized and selected.
At this point, you can use the Get Started setup steps from the Authorize page in Neon to complete the setup — this guide is modelled on those steps. Or feel free to keep following along in this guide, where we'll give you a bit more context.
3. Install the pg_session_jwt extension in your database
Neon Authorize uses the pg_session_jwt extension to handle authenticated sessions through JSON Web Tokens (JWTs). This extension allows secure transmission of authentication data from your application to Postgres, where you can enforce Row-Level Security (RLS) policies based on the user's identity.
To install the extension in the neondb
database, run:
4. Set up Postgres roles
The integration creates the authenticated
and anonymous
roles for you. Let's define table-level permissions for these roles. To allow both roles to read and write to tables in your public schema, run:
- Authenticated role: This role is intended for users who are logged in. Your application should send the authorization token when connecting using this role.
- Anonymous role: This role is intended for users who are not logged in. It should allow limited access, such as reading public content (e.g., blog posts) without authentication.
5. Install the Neon Serverless Driver
Neon’s Serverless Driver manages the connection between your application and the Neon Postgres database. For Neon Authorize, you must use HTTP. While it is technically possible to access Neon's HTTP API without using our driver, we recommend using the driver for best performance. The driver supports connecting over both WebSockets and HTTP, so make sure you use the HTTP connection method when working with Neon Authorize.
Install it using the following command:
To learn more about the driver, see Neon Serverless Driver.
6. Set up environment variables
Here is an example of setting up administrative and authenticated database connections in your .env
file. Copy the connection strings for both the neondb_owner
and authenticated
roles. You can find them from Connection Details in the Neon Console, or using the Neon CLI:
Add these to your .env
file.
The DATABASE_URL
is intended for admin tasks and can run any query while the DATABASE_AUTHENTICATED_URL
should be used for connections from authorized users, where you pass the required authorization token. You can see an example in Run your first authorized query below.
Add RLS policies
Now that you’ve integrated Auth0 with Neon Authorize, you can securely pass JWTs to your Neon database. Let's start looking at how to add RLS policies to your schema and how you can execute authenticated queries from your application.
1. Add Row-Level Security policies
Below are examples of RLS policies for a todos table, designed to restrict access so that users can only create, view, update, or delete their own todos.
2. Run your first authorized query
With RLS policies in place, you can now query the database using JWTs from Auth0 , restricting access based on the user's identity. Here are examples of how you could run authenticated queries from both the backend and the frontend of our sample todos application. Highlighted lines in the code samples emphasize key actions related to authentication and querying.
'use server';
import { neon } from '@neondatabase/serverless';
import { getAccessToken } from '@auth0/nextjs-auth0';
export async function TodoList() {
const sql = neon(process.env.DATABASE_AUTHENTICATED_URL!, {
authToken: async () => {
const { accessToken } = await getAccessToken();
if (!accessToken) {
throw new Error('No access token');
}
return accessToken;
},
});
// WHERE filter is optional because of RLS.
// But we send it anyway for performance reasons.
const todos = await
sql('SELECT * FROM todos WHERE user_id = auth.user_id()');
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.task}</li>
))}
</ul>
);
}
Need help?
Join our Discord Server to ask questions or see what others are doing with Neon. Users on paid plans can open a support ticket from the console. For more details, see Getting Support.