Build a Supabase Integration (Beta)
This guide steps through building a Supabase Integration using OAuth2 and the management API, allowing you to manage users' organizations and projects on their behalf.
Using OAuth2.0 you can retrieve an access and refresh token that grant your application full access to the Management API on behalf of the user.
Create an OAuth app
- In your organization's settings, navigate to the OAuth Apps tab.
- In the upper-right section of the page, click Add application.
- Fill in the required details and click Confirm.
Show a "Connect Supabase" button
In your user interface, add a "Connect Supabase" button to kick off the OAuth flow. Follow the design guidelines outlined in our brand assets.
Implementing the OAuth 2.0 flow
Once you've published your OAuth App on Supabase, you can use the OAuth 2.0 protocol get authorization from Supabase users to manage their organizations and projects.
You can use your preferred OAuth2 client or follow the steps below. You can see an example implementation in TypeScript using Supabase Edge Functions on our GitHub.
Redirecting to the authorize URL
Within your app's UI, redirect the user to https://api.supabase.com/v1/oauth/authorize
. Make sure to include all required query parameters such as:
client_id
: Your client id from the app creation above.redirect_uri
: The URL where Supabase will redirect the user to after providing consent.response_type
: Set this tocode
.state
: Information about the state of your app. Note thatredirect_uri
andstate
together cannot exceed 4kB in size.- (Recommended) PKCE: We strongly recommend using the PKCE flow for increased security. Generate a random value before taking the user to the authorize endpoint. This value is called code verifier. Hash it with SHA256 and include it as the
code_challenge
parameter, while settingcode_challenge_method
toS256
. In the next step, you would need to provide the code verifier to get the first access and refresh token. - [deprecated]
scope
: Scopes are configured when you create your OAuth app. Read the docs for more details.
_12router.get('/connect-supabase/login', async (ctx) => {_12 // Construct the URL for the authorization redirect and get a PKCE codeVerifier._12 const { uri, codeVerifier } = await oauth2Client.code.getAuthorizationUri()_12 console.log(uri.toString())_12 // console.log: https://api.supabase.com/v1/oauth/authorize?response_type=code&client_id=7673bde9-be72-4d75-bd5e-b0dba2c49b38&redirect_uri=http%3A%2F%2Flocalhost%3A54321%2Ffunctions%2Fv1%2Fconnect-supabase%2Foauth2%2Fcallback&scope=all&code_challenge=jk06R69S1bH9dD4td8mS5kAEFmEbMP5P0YrmGNAUVE0&code_challenge_method=S256_12_12 // Store the codeVerifier in the user session (cookie)._12 ctx.state.session.flash('codeVerifier', codeVerifier)_12_12 // Redirect the user to the authorization endpoint._12 ctx.response.redirect(uri)_12})
Find the full example on GitHub.
Handling the callback
Once the user consents to providing API access to your OAuth App, Supabase will redirect the user to the redirect_uri
provided in the previous step. The URL will contain these query parameters:
code
: An authorization code you should exchange with Supabase to get the access and refresh token.state
: The value you provided in the previous step, to help you associate the request with the user. Thestate
property returned here should be compared to thestate
you sent previously.
Exchange the authorization code for an access and refresh token by calling POST https://api.supabase.com/v1/oauth/token
with the following query parameters as content-type application/x-www-form-urlencoded
:
grant_type
: The valueauthorization_code
.code
: Thecode
returned in the previous step.redirect_uri
: This must be exactly the same URL used in the first step.- (Recommended)
code_verifier
: If you used the PKCE flow in the first step, include the code verifier ascode_verifier
.
As per OAuth2 spec, provide the client id and client secret as basic auth header:
client_id
: The unique client ID identifying your OAuth App.client_secret
: The secret that authenticates your OAuth App to Supabase.
_26router.get('/connect-supabase/oauth2/callback', async (ctx) => {_26 // Make sure the codeVerifier is present for the user's session._26 const codeVerifier = ctx.state.session.get('codeVerifier') as string_26 if (!codeVerifier) throw new Error('No codeVerifier!')_26_26 // Exchange the authorization code for an access token._26 const tokens = await fetch(config.tokenUri, {_26 method: 'POST',_26 headers: {_26 'Content-Type': 'application/x-www-form-urlencoded',_26 Accept: 'application/json',_26 Authorization: `Basic ${btoa(`${config.clientId}:${config.clientSecret}`)}`,_26 },_26 body: new URLSearchParams({_26 grant_type: 'authorization_code',_26 code: ctx.request.url.searchParams.get('code') || '',_26 redirect_uri: config.redirectUri,_26 code_verifier: codeVerifier,_26 }),_26 }).then((res) => res.json())_26 console.log('tokens', tokens)_26_26 // Store the tokens in your DB for future use._26_26 ctx.response.body = 'Success'_26})
Find the full example on GitHub.
Refreshing an access token
You can use the POST /v1/oauth/token
endpoint to refresh an access token using the refresh token returned at the end of the previous section.
If the user has revoked access to your application, you will not be able to refresh a token. Furthermore, access tokens will stop working. Make sure you handle HTTP Unauthorized errors when calling any Supabase API.
Calling the Management API
Refer to the Management API reference to learn more about authentication with the Management API.
Use the JavaScript (TypeScript) SDK
For convenience, when working with JavaScript/TypeScript, you can use the supabase-management-js library.
_10import { SupabaseManagementAPI } from 'supabase-management-js'_10_10const client = new SupabaseManagementAPI({ accessToken: '<access token>' })
Integration recommendations
There are a couple common patterns you can consider adding to your integration that can facilitate a great user experience.
Store API keys in env variables
Some integrations, e.g. like Cloudflare Workers provide convenient access to the API URL and API keys to allow user to speed up development.
Using the management API, you can retrieve a project's API credentials using the /projects/{ref}/api-keys
endpoint.
Pre-fill database connection details
If your integration directly connects to the project's database, you can pref-fill the Postgres connection details for the user, it follows this schema:
_10postgresql://postgres:[DB-PASSWORD]@db.[REF].supabase.co:5432/postgres
Note that you cannot retrieve the database password via the management API, so for the user's existing projects you will need to collect their database password in your UI.
Create new organizations and projects
If you don't need access to the user's existing project, we recommend creating a new project under a new organization. Use the /v1/organizations
endpoint to create a new organization named after your integration, afterward use the /v1/projects
endpoint to create a new project.
When creating a new project, you can either ask the user to provide a database password, or you can generate a secure password for them. In any case, make sure to securely store the database password on your end which will allow you to construct the Postgres URI.
Configure custom Auth SMTP
You can configure the user's custom SMTP settings using the /config/auth
endpoint.
Current limitations
Only some features are available until we roll out fine-grained access control. If you need full database access, you will need to prompt the user for their database password.