Prepare for the PgBouncer and IPv4 deprecations on 26th January 2024

Platform

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

  1. In your organization's settings, navigate to the OAuth Apps tab.
  2. In the upper-right section of the page, click Add application.
  3. 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 to code.
  • state: Information about the state of your app. Note that redirect_uri and state 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 setting code_challenge_method to S256. 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.

_12
router.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. The state property returned here should be compared to the state 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 value authorization_code.
  • code: The code 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 as code_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.

_26
router.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.


_10
import { SupabaseManagementAPI } from 'supabase-management-js'
_10
_10
const 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:


_10
postgresql://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.