https://github.com/midoru0121/nextjs-auth0-supabase-integration-example
Auth0 and Supabase Integration Example with Next.js
https://github.com/midoru0121/nextjs-auth0-supabase-integration-example
auth0 nextjs supabase
Last synced: 4 months ago
JSON representation
Auth0 and Supabase Integration Example with Next.js
- Host: GitHub
- URL: https://github.com/midoru0121/nextjs-auth0-supabase-integration-example
- Owner: midoru0121
- Created: 2025-01-27T07:06:45.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-02-02T07:22:08.000Z (5 months ago)
- Last Synced: 2025-02-02T08:18:35.903Z (5 months ago)
- Topics: auth0, nextjs, supabase
- Language: TypeScript
- Homepage:
- Size: 102 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
[日本語](https://github.com/midoru0121/auth0-supabase-integration-example/blob/main/README_ja.md)
# nextjs-auth0-supabase-integration-example
This is the flow of the application. Assumption: The signing algorithm for both Supabase and Auth0 is set to `RS256`.
- Authenticate the user using Auth0.
- Immediately after logging in via Auth0, assign the role previously created in Auth0 to the user.
- Include the above role in the payload, sign it with Supabase’s JWT secret, and store it in the @auth0/nextjs-auth0 session.
- From here on, it can be accessed as a session inside Next.js’s RSC. This JWT will be used as an access token for Supabase.
- Access Supabase from within Next.js’s RSC (when doing this, attach the above access token as a Bearer token in the request).
- On the Supabase side, decode the JWT for the RLS policy and check if the role is included.
- If the role is not included, deny access to the table.
- If the role is included, grant access to the table.## Setting Up Auth0
### Creating an Auth0 Application
After registering with Auth0, create an application and select `Regular Web Applications`.
Click `Settings` to navigate to the configuration page.

Note down `Domain`, `Client Id`, and `Client Secret`, as they will be needed later.

Set `Allowed Callback URLs` to `http://localhost:3000/api/auth/callback`.
Set `Allowed Logout URLs` to `http://localhost:3000`.
Then, set `OAuth` and `JSON Web Token Signature` to `RS256`. Also, check that the `OIDC Conformant` box is checked.

Go to `Connections` and enable `google-oauth-2` to allow sign-ups via Google accounts.

### Configuring the Auth0 Management API
Select the Auth0 Management API, choose `Machine to Machine Applications`, and check the `Authorized` button. Then, expand the details.


Add the following permissions: `read:users`, `update:users`, and `read:roles`.

### Creating a Role
Click `Roles` and create an `Authenticated` role. This role will be assigned to users by default.


Note the `Role ID` of the `Authenticated` role, as it will be used later.

## Setting Up Auth0 Post Login Action
To assign a default role upon user login, set up a `Post Login Action`.
Go to `Actions` > `Triggers` and click `post-login`.

Select `Build from scratch`.

Name the action and click `Create`.

Go to `Secrets` and add `DOMAIN`, `CLIENT_SECRET`, `CLIENT_ID`, and `DEFAULT_ROLE_ID`.

Click `Add Dependency` and add `auth0` and `axios`.

Paste the following code:
```javascript
exports.onExecutePostLogin = async (event, api) => {
// Import Axiosconst axios = require("axios").default;
// Import Auth0 Management API client
const { ManagementClient } = require("auth0");
// Define a namespace for custom claims
const roleNamespace = "https://auth0-supabase-interation-example.com/roles";// If the user already has roles, exit the process
if (
event.authorization &&
event.authorization.roles &&
event.authorization.roles.length > 0
) {
console.log("The user has roles.");
// Set existing roles as custom claims
const roles = event.authorization.roles.join(",");
api.idToken.setCustomClaim(roleNamespace, roles);return;
}try {
// Get the access token for the Management API
const options = {
method: "POST",
url: `https://${event.secrets.DOMAIN}/oauth/token`,
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: new URLSearchParams({
grant_type: "client_credentials",
client_id: event.secrets.CLIENT_ID,
client_secret: event.secrets.CLIENT_SECRET,
audience: `https://${event.secrets.DOMAIN}/api/v2/`,
scope: "read:roles update:users",
}),
};const response = await axios.request(options);
// Initialize the Management API client
const management = new ManagementClient({
domain: event.secrets.DOMAIN,
token: response.data.access_token,
});// Assign roles to the user
const params = { id: event.user.user_id };
const data = { roles: [event.secrets.DEFAULT_ROLE_ID] };await management.users.assignRoles(params, data);
// Get role details from the API
const roleResponse = await axios.get(
`https://${event.secrets.DOMAIN}/api/v2/roles/${event.secrets.DEFAULT_ROLE_ID}`,
{
headers: {
Authorization: `Bearer ${response.data.access_token}`,
},
}
);
// Set the role name of the user as a custom claim in the ID token
api.idToken.setCustomClaim(roleNamespace, roleResponse.data.name);console.log("Success");
} catch (e) {
// Log the error
console.log(e);
}
};
```Click `Deploy`.

Return to the `post-login` configuration and place the deployed action right after `User Logged In`.

## Creating a Supabase Project
After registering with Supabase, go to `Settings -> API` and note the `Project URL`, `anon key`, and `JWT_SECRET`.


Create a `todo` table.

Add a `title` (text type) column and click `Save`.

Insert some sample data.

Set an RLS policy on the `todo` table to restrict access to users without the `Authenticated` role.
```sql
alter policy "JWT Authenticated can view todo"
on "public"."todo"
to public
using (
((auth.jwt() -> 'userRoles'::text) ? 'Authenticated'::text)
);
```
Click `Save Policy`.
## Running the Application
Create a `.env.local` file:
```bash
# .env.local
AUTH0_SECRET=any-secure-value
AUTH0_BASE_URL=http://localhost:3000
AUTH0_ISSUER_BASE_URL=https://.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
SUPABASE_JWT_SECRET=your-supabase-jwt-secret
```Start the application and visit http://localhost:3000.
```bash
pnpm dev
```
Click `Login` and authenticate via email or Google OAuth. Then, visit http://localhost:3000/protected to verify data retrieval.
