Skip to main content

Supabase

Get Started​

Supabase provides us a great and cheap Auth system for our projects. It gives us a lot of configuration options to adjust it for our needs.

To get started with Supabase Auth, make sure followed up State management/Supabase and Database/Supabase sections as they're required for this module.

tl;dr

  • Terraform Backend configured
  • Supabase secrets in GitHub repository
info

All secrets and variables associated with Supabase (i.e. JWT Secret, JWT Issuer), will be automatically attached to the running application (if heroku.enabled = true)

Initialize​

To enabled Supabase Auth module, just change supabase.auth.enabled flag to true. There's also supabase.auth.site_url field, where you specify base URL of all links built by Supabase and used in emails. This is optional, but default value is http://localhost:3000/, so you might want to change it, at least for production.

Disable signups​

If needed, you can quickly disable signups by setting supabase.auth.disable_signup to true. That way, customers won't be able to create an account on their own, the only way would be through invitation.

Reference​

__env.tf
locals {
...
supabase = {
enabled = true
...
auth = {
// NOTE: if supabase.enabled=false this will be automatically disabled
enabled = false
// (optional) By setting this to 'true' you forbid users to sign-up to your platform, this might be a case when
// you'd want to have users created from Stripe flow, or users being invited
// default: false
disable_signup = false
// (optional) This is the Site URL that will be used as base URL for a Magic Link
// default: https://localhost:3000, no wildards (*) allowed
site_url = "https://runtyme.co"
}
}
...
}

Password​

__env.tf
locals {
...
supabase = {
enabled = true
...
auth = {
enabled = false

// (optional)
password = {
// (optional) Passwords shorter than this value will be rejected as weak.
// default: 8, Minimum 6, recommended 8 or more.
min_length = 8
// (optional) Passwords that do not have at least one of each will be rejected as weak.
// The value below is recommended
required_characters = "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~"
// (optional) Rejects the use of known or easy to guess passwords on sign up or password change. Powered by the HaveIBeenPwned.org Pwned Passwords API.
// ONLY ALLOWED FOR SUPABASE PRO TIER
// default: false
prevent_use_of_leaked_passwords = false
}
}
}
...
}
__env.tf
locals {
...
supabase = {
enabled = true
...
auth = {
enabled = false

// (optional)
otp = {
// (optional) Time after Magic Link will expire and will no longer be valid
// default: 3600 - 1h, Maximum: 86400
expire_in = 3600
// (optional) Number of generated characters for OTP auth
// default: 6, Minimum: 6, Maximum: 10
code_length = 6
}
}
}
...
}

Rate-limiting​

Supabase gives us an option to configure rate-limiting for things like sending emails, OTP verifications or Token refreshing.

You can set your custom rate-limits in infra/__env.tf file under supabase.rate_limit section. This is configured out of the box, so you don't have to look into that unless you really need to.

Make sure supabase.enabled and supabase.auth.enabled is set to true.

Reference:​

__env.tf
locals {
...
supabase = {
enabled = true
...
auth = {
enabled = true

// (optional)
rate_limit = {
// (optional) Limit of emails being sent from current project per hour
// Available only if `smtp.use_sendgrid=true` and `sendgrid.enabled=true`
// default: 10
email_sent = 10
// (optional) Limit of refresh token operations performed by IP per 5 minutes
// default: 10
token_refresh = 10
// (optional) Limit of Magic Link verification emails being sent by IP per 5 minutes
// default: 10
verify = 10
// (optional) Limit of OTP verification operations performed by IP per 5 minutes
// default: 10
otp = 10
}
}
}
...
}

Emailing​

Supabase comes with a feature which sends an email to users of the platform, when below actions are triggered:

  • Email Confirmation - Triggered when customer signs up and is required to confirm email address.
  • Invite - Triggered when customer is invited by another customer or the system itself.
  • Magic Link - Triggered when customer tries to sign in via OTP, email with Sign-In Token and Magic Link is sent.
  • Email Change - Triggered when customer requests an email address change.
  • Password Reset - Triggered when customer forgots their's password and requests an email to reset it.
  • Reauthentication - Triggered when platform action requires reauthenticated customer, i.e. customer changes their password in dashboard and system requires a reauthentication of this customer.

Templates​

Starter from runtyme-kit comes with built in Supabase templates that can be changed anyway you want.

You can find them under infra/_templates/emails/supabase directory.

To automatically attach them to your Supabase instance, make sure supabase.enabled and supabase.auth.enabled is set to true in your infra/__env.tf config file.

__env.tf
locals {
...
supabase = {
enabled = true
...
auth = {
enabled = true
...
}
}
...
}

Out of the box, templates are being automatically referenced in infra/__env.tf config file and you don't have to do anything about them.
All the values are optional, if left empty or undefined, no changes will be applies (only if it wasn't populated before).

Custom authentication hook​

In order to use permission scopes runtyme-kit uses Supabase Auth Hooks. It is essentially a PostgresQL function called whenever customer authenticates into your product.

This function can be found under infra/modules/supabase/sql/custom_auth_hook.sql. It essentially checks profiles table and adds proper scopes into JWT Token's user_metadata.scopes field. Then those values are validated on Backend side, everytime customer wants to access protected resource.

Reference:​

__env.tf
locals {
...
supabase = {
enabled = true
...
auth = {
enabled = true

// (optional) You can override default Supabase templates related to Auth operations
email_template = {
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Confirm signup
signup_subject = "[your_app] Confirm Your Signup"
signup_relative_path = "/_templates/emails/supabase/email-confirmation.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Invite user
invite_subject = "[your_app] You have been invited"
invite_relative_path = "/_templates/emails/supabase/invite-user.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Magic Link
magic_link_subject = "[your_app] Your Magic Link"
magic_link_template_relative_path = "/_templates/emails/supabase/magic-link.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Change Email Address
email_change_subject = "[your_app] Confirm Email Change"
email_change_template_relative_path = "/_templates/emails/supabase/change-email.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Reset Password
reset_password_subject = "[your_app] Reset Your Password"
reset_password_template_relative_path = "/_templates/emails/supabase/reset-password.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Reauthentication
re_authentication_subject = "[your_app] Confirm Reauthentication"
re_authentication_relative_path = "/_templates/emails/supabase/reauthenticate.html"
}
}
}
...
}

SMTP Server​

Default Supabase SMTP server only allows Auth emails to be sent to project owners, it is not suitable for production. Any user of email address that is not assigned to the organization, which actions triggers any Supabase email event, won't receive this email.

It is recommended if not required, to use your own SMTP server on production for Auth.

Important

To disable any custom SMTP server once it was enabled, you need to first disable it in your project's Supabase dashboard under Project Settings -> Authentication -> SMTP Settings, otherwise apply flow will fail. That's due to inconsistency of Supabase API and Terraform provider.

SendGrid​

Right now only SendGrid is supported, it can be enabled in infra/__env.tf by setting supabase.auth.smtp.use_sendgrid to true.

runtyme-kit creates and configures SendGrid instance for you and uses it's values to populate Supabase configuration automatically.

Important

It will work only if you're have sendgrid.enabled set to true in your infra/__env.tf file!

Full module reference​

__env.tf
locals {
supabase = {
enabled = false
// (required) Name of the Supabase project under your organization account
// IMMUTABLE, cannot be changed after initialization
// Can be updated only in Supabase dashboard, if updated in dashboard, you have to update it here as well
project_name = "runtyme-kit"
// (optional) World region where Supabase instance will be deployed, available values: https://supabase.com/docs/guides/platform/regions
// defaults to 'eu-central-1'
region = "eu-central-1"
// (optional) Instance size of Supabase database, available values: https://supabase.com/docs/guides/platform/compute-add-ons
// NOTE: can be specified only in organization isn't a Free tier
// size = "nano"

auth = {
// NOTE: if supabase.enabled=false this will be automatically disabled
enabled = false
// (optional) By setting this to 'true' you forbid users to sign-up to your platform, this might be a case when
// you'd want to have users created from Stripe flow, or users being invited
// default: false
disable_signup = false
// (optional) This is the Site URL that will be used as base URL for a Magic Link
// default: https://localhost:3000, no wildards (*) allowed
site_url = "https://runtyme.co"

// (optional)
otp = {
// (optional) Time after Magic Link will expire and will no longer be valid
// default: 3600 - 1h, Maximum: 86400
expire_in = 3600
// (optional) Number of generated characters for OTP auth
// default: 6, Minimum: 6, Maximum: 10
code_length = 6
}

// (optional)
password = {
// (optional) Passwords shorter than this value will be rejected as weak.
// default: 8, Minimum 6, recommended 8 or more.
min_length = 8
// (optional) Passwords that do not have at least one of each will be rejected as weak.
// The value below is recommended
required_characters = "abcdefghijklmnopqrstuvwxyz:ABCDEFGHIJKLMNOPQRSTUVWXYZ:0123456789:!@#$%^&*()_+-=[]{};'\\\\:\"|<>?,./`~"
// (optional) Rejects the use of known or easy to guess passwords on sign up or password change. Powered by the HaveIBeenPwned.org Pwned Passwords API.
// ONLY ALLOWED FOR SUPABASE PRO TIER
// default: false
prevent_use_of_leaked_passwords = false
}

// (optional)
rate_limit = {
// (optional) Limit of emails being sent from current project per hour
// Available only if `smtp.use_sendgrid=true` and `sendgrid.enabled=true`
// default: 10
email_sent = 10
// (optional) Limit of refresh token operations performed by IP per 5 minutes
// default: 10
token_refresh = 10
// (optional) Limit of Magic Link verification emails being sent by IP per 5 minutes
// default: 10
verify = 10
// (optional) Limit of OTP verification operations performed by IP per 5 minutes
// default: 10
otp = 10
}

// (optional) Specify custom SMTP server for Supabase auth emails
// NOTE: If empty, default shared Supabase server will be used, not recommended for production application
smtp = {
// (optional) If set to 'true' AND 'sendgrid.enabled=true', configured SendGrid SMTP server will be used
// default: false
use_sendgrid = true
}

// (optional) You can override default Supabase templates related to Auth operations
email_template = {
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Confirm signup
signup_subject = "[your_app] Confirm Your Signup"
signup_relative_path = "/_templates/emails/supabase/email-confirmation.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Invite user
invite_subject = "[your_app] You have been invited"
invite_relative_path = "/_templates/emails/supabase/invite-user.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Magic Link
magic_link_subject = "[your_app] Your Magic Link"
magic_link_template_relative_path = "/_templates/emails/supabase/magic-link.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Change Email Address
email_change_subject = "[your_app] Confirm Email Change"
email_change_template_relative_path = "/_templates/emails/supabase/change-email.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Reset Password
reset_password_subject = "[your_app] Reset Your Password"
reset_password_template_relative_path = "/_templates/emails/supabase/reset-password.html"
// (optional) Supabase -> Dashboard -> [project_name] -> Authentication -> Email Templates -> Reauthentication
re_authentication_subject = "[your_app] Confirm Reauthentication"
re_authentication_relative_path = "/_templates/emails/supabase/reauthenticate.html"
}
}
}
}