rembrembdocs

Auth Hooks

Use HTTP or Postgres Functions to customize your authentication flow


What is a hook#

A hook is an endpoint that allows you to alter the default Supabase Auth flow at specific execution points. Developers can use hooks to add custom behavior that's not supported natively.

Hooks help you:

The following hooks are available:

Hook

Available on Plan

Before User Created

Free, Pro

Custom Access Token

Free, Pro

Send SMS

Free, Pro

Send Email

Free, Pro

MFA Verification Attempt

Teams and Enterprise

Password Verification Attempt

Teams and Enterprise

Supabase supports 2 ways to configure a hook in your project:

A Postgres function can be configured as a hook. The function should take in a single argument -- the event of type JSONB -- and return a JSONB object. Since the Postgres function runs on your database, the request does not leave your project's instance.

Security model#

Sign the payload and grant permissions selectively in order to guard the integrity of the payload.

When you configure a Postgres function as a hook, Supabase will automatically apply the following grants to the function for these reasons:

1-- Grant access to function to supabase_auth_admin2grant execute3  on function public.custom_access_token_hook4  to supabase_auth_admin;56-- Grant access to schema to supabase_auth_admin7grant usage on schema public to supabase_auth_admin;89-- Revoke function permissions from authenticated, anon and public10revoke execute11  on function public.custom_access_token_hook12  from authenticated, anon, public;

You will need to alter your row-level security (RLS) policies to allow the supabase_auth_admin role to access tables that you have RLS policies on. You can read more about RLS policies here.

Alternatively, you can create your Postgres function via the dashboard with the security definer tag. The security definer tag specifies that the function is to be executed with the privileges of the user that owns it.

Currently, functions created via the dashboard take on the postgres role. Read more about the security definer tag in our database guide

Using Hooks#

Developing#

Let us develop a Hook locally and then deploy it to the cloud. As a recap, here’s a list of available Hooks

Hook

Suggested Function Name

When it is called

What it Does

Send SMS

send_sms

Each time an SMS is sent

Allows you to customize message content and SMS Provider

Send Email

send_email

Each time an Email is sent

Allows you to customize message content and Email Provider

Custom Access Token

custom_access_token

Each time a new JWT is created

Returns the claims you wish to be present in the JWT.

MFA Verification Attempt

mfa_verification_attempt

Each time a user tries to verify an MFA factor.

Returns a decision on whether to reject the attempt and future ones, or to allow the user to keep trying.

Password Verification Attempt

password_verification_attempt

Each time a user tries to sign in with a password.

Return a decision whether to allow the user to reject the attempt, or to allow the user to keep trying.

Edit config.toml to set up the Auth Hook locally.

Modify the auth.hook.<hook_name> field and set uri to a value of pg-functions://postgres/<schema>/<function_name>

1[auth.hook.<hook_name>]2enabled = true3uri = "pg-functions://...."

You need to assign additional permissions so that Supabase Auth can access the hook as well as the tables it interacts with.

The supabase_auth_admin role does not have permissions to the public schema. You need to grant the role permission to execute your hook:

1grant execute2  on function public.custom_access_token_hook3  to supabase_auth_admin;

You also need to grant usage to supabase_auth_admin:

1grant usage on schema public to supabase_auth_admin;

Also revoke permissions from the authenticated and anon roles to ensure the function is not accessible by Supabase Serverless APIs.

1revoke execute2  on function public.custom_access_token_hook3  from authenticated, anon;

For security, we recommend against the use the security definer tag. The security definer tag specifies that the function is to be executed with the privileges of the user that owns it. When a function is created via the Supabase dashboard with the tag, it will have the extensive permissions of the postgres role which make it easier for undesirable actions to occur.

We recommend that you do not use any tag and explicitly grant permissions to supabase_auth_admin as described above.

Read more about security definer tag in our database guide.

Once done, save your Auth Hook as a migration in order to version the Auth Hook and share it with other team members. Run supabase migration new to create a migration.

If you're using the Supabase SQL Editor, there's an issue when using the ? (Does the string exist as a top-level key within the JSON value?) operator. Use a direct connection to the database if you need to use it when defining a function.

Here is an example hook signature:

1create or replace function public.custom_access_token_hook(event jsonb)2returns jsonb3language plpgsql4as $$5declare6  -- Insert variables here7begin8  -- Insert logic here9  return event;10end;11$$;

You can visit SQL Editor > Templates for hook templates.

Deploying#

In the dashboard, navigate to Authentication > Hooks and select the appropriate function type (SQL or HTTP) from the dropdown menu.

Error handling#

You should return an error when facing a runtime error. Runtime errors are specific to your application and arise from specific business rules rather than programmer errors.

Runtime errors could happen when:

The error is a JSON object and has the following properties:

Here's an example:

1{2  "error": {3    "http_code": 429,4    "message": "You can only verify a factor once every 10 seconds."5  }6}

Errors returned from a Postgres Hook are not retry-able. When an error is returned, the error is propagated from the hook to Supabase Auth and translated into an HTTP error which is returned to your application. Supabase Auth will only take into account the error and disregard the rest of the payload.

Outside of runtime errors, both HTTP Hooks and Postgres Hooks return timeout errors. Postgres Hooks have 2 seconds to complete processing while HTTP Hooks should complete in 5 seconds. Both HTTP Hooks and Postgres Hooks are run in a transaction do limit the duration of execution to avoid delays in authentication process.

Available Hooks#

Each Hook description contains an example JSON Schema which you can use in conjunction with JSON Schema Faker in order to generate a mock payload. For HTTP Hooks, you can also use the Standard Webhooks Testing Tool to simulate a request.

[

Custom Access Token

Customize the access token issued by Supabase Auth

](custom-access-token-hook/index.md)

[

Send SMS

Use a custom SMS provider to send authentication messages

](send-sms-hook/index.md)

[

Send Email

Use a custom email provider to send authentication messages

](send-email-hook/index.md)

[

MFA Verification

Add additional checks to the MFA verification flow

](mfa-verification-hook/index.md)

[

Password verification

Add additional checks to the password verification flow

](password-verification-hook/index.md)