Authentication with Supabase GoTrue in Elixir
View SourceThis guide covers how to use Supabase's authentication service (GoTrue) with your Elixir applications. It provides examples for the most common authentication scenarios and explains how to integrate authentication with both traditional Phoenix applications and LiveView.
Authentication Methods
Supabase GoTrue supports multiple authentication methods:
Email and Password Authentication
The most common authentication method is email+password sign-in:
# Sign in with email and password
{:ok, session} = Supabase.GoTrue.sign_in_with_password(client, %{
email: "user@example.com",
password: "securepassword"
})
# Use the session to get the current user
{:ok, user} = Supabase.GoTrue.get_user(client, session)
Phone Authentication
Phone-based authentication using SMS verification:
# Sign in with phone and password
{:ok, session} = Supabase.GoTrue.sign_in_with_password(client, %{
phone: "+15555551234",
password: "securepassword"
})
One-Time Password (OTP)
OTP is a passwordless authentication method that sends a temporary code to the user's email or phone:
# Request an OTP to be sent
:ok = Supabase.GoTrue.sign_in_with_otp(client, %{
email: "user@example.com"
})
# Later, verify the OTP to get a session
{:ok, session} = Supabase.GoTrue.verify_otp(client, %{
email: "user@example.com",
token: "123456",
type: "email"
})
OAuth (Social Authentication)
Sign in with social providers like Google, GitHub, etc.:
# Get the OAuth URL to redirect the user to
{:ok, provider, redirect_url} = Supabase.GoTrue.sign_in_with_oauth(client, %{
provider: :github,
redirect_to: "https://myapp.com/auth/callback"
})
# After OAuth callback, exchange the code for a session
{:ok, session} = Supabase.GoTrue.exchange_code_for_session(client, auth_code, code_verifier)
Single Sign-On (SSO)
Enterprise single sign-on for organizations:
# Start SSO authentication
{:ok, redirect_url} = Supabase.GoTrue.sign_in_with_sso(client, %{
domain: "example.org",
redirect_to: "https://myapp.com/auth/callback"
})
Anonymous Authentication
Create a session without user credentials:
{:ok, session} = Supabase.GoTrue.sign_in_anonymously(client)
Session Management
A successful authentication returns a Session
struct containing tokens and user information:
%Supabase.GoTrue.Session{
access_token: "eyJhbGciOiJ...",
refresh_token: "kIvYW5...",
expires_in: 3600,
expires_at: 1650123456, # Unix timestamp when token expires
token_type: "bearer",
user: %Supabase.GoTrue.User{...}
}
Refreshing Sessions
To keep users logged in, refresh the session before the access token expires:
{:ok, new_session} = Supabase.GoTrue.refresh_session(client, session.refresh_token)
For automatic token refreshing, you can use the Supabase.GoTrue.AutoRefresh
GenServer in your supervision tree:
# In your application.ex:
children = [
{Supabase.GoTrue.AutoRefresh, {client, session, refresh_callback_fn}}
]
User Management
User Registration
Create a new user with email and password:
{:ok, user} = Supabase.GoTrue.sign_up(client, %{
email: "new_user@example.com",
password: "securepassword"
})
Getting User Information
Retrieve current user details:
{:ok, user} = Supabase.GoTrue.get_user(client, session)
Updating User Information
Update user profile details:
{:ok, updated_conn} = Supabase.GoTrue.update_user(client, conn, %{
data: %{
display_name: "Jane Doe",
avatar_url: "https://example.com/avatar.png"
}
})
Password Recovery
Send a password reset email:
:ok = Supabase.GoTrue.reset_password_for_email(client,
"user@example.com",
redirect_to: "https://myapp.com/reset-password"
)
Multi-factor Authentication (MFA)
GoTrue supports multi-factor authentication for additional security:
Managing MFA Factors
# Get user's MFA factors
{:ok, user} = Supabase.GoTrue.get_user(client, session)
factors = user.factors
# Check if user has MFA enabled
has_mfa = length(factors) > 0
Identity Management
GoTrue allows users to link multiple authentication methods to a single account:
Linking New Identity Providers
# Get a URL to link a new provider
{:ok, %{provider: :github, url: redirect_url}} = Supabase.GoTrue.link_identity(
client,
session,
%{provider: :github}
)
# Redirect user to this URL to link their GitHub account
Unlinking Providers
# Remove a linked identity
:ok = Supabase.GoTrue.unlink_identity(client, session, identity_id)
Listing Linked Identities
# Get all linked identities
{:ok, identities} = Supabase.GoTrue.get_user_identities(client, session)
Server Information
Get information about the GoTrue server:
# Get server settings
{:ok, settings} = Supabase.GoTrue.get_server_settings(client)
# Check server health
{:ok, health} = Supabase.GoTrue.get_server_health(client)
Integration with Phoenix
Traditional Phoenix Applications
For Phoenix applications with traditional views, use the Supabase.GoTrue.Plug
module:
# lib/my_app_web/auth.ex
defmodule MyAppWeb.Auth do
use Supabase.GoTrue.Plug,
client: MyApp.Supabase.Client,
endpoint: MyAppWeb.Endpoint,
signed_in_path: "/app",
not_authenticated_path: "/login",
session_cookie: "my_app_session"
end
# lib/my_app_web/router.ex
defmodule MyAppWeb.Router do
import MyAppWeb.Auth
pipeline :browser do
plug :fetch_current_user
end
# Public routes
scope "/", MyAppWeb do
pipe_through [:browser, :redirect_if_user_is_authenticated]
get "/login", SessionController, :new
post "/login", SessionController, :create
end
# Protected routes
scope "/app", MyAppWeb do
pipe_through [:browser, :require_authenticated_user]
get "/", DashboardController, :index
end
end
# lib/my_app_web/controllers/session_controller.ex
defmodule MyAppWeb.SessionController do
import MyAppWeb.Auth
def create(conn, %{"email" => email, "password" => password}) do
case log_in_with_password(conn, %{email: email, password: password}) do
{:ok, conn} ->
conn
|> put_flash(:info, "Welcome back!")
|> redirect(to: Routes.dashboard_path(conn, :index))
{:error, _reason} ->
conn
|> put_flash(:error, "Invalid email/password")
|> render("new.html")
end
end
end
Phoenix LiveView Applications
For LiveView applications, use the Supabase.GoTrue.LiveView
module:
# lib/my_app_web/auth.ex
defmodule MyAppWeb.Auth do
use Supabase.GoTrue.LiveView,
client: MyApp.Supabase.Client,
endpoint: MyAppWeb.Endpoint,
signed_in_path: "/app",
not_authenticated_path: "/login"
end
# In your LiveView
defmodule MyAppWeb.DashboardLive do
use MyAppWeb, :live_view
on_mount {MyAppWeb.Auth, :mount_current_user}
on_mount {MyAppWeb.Auth, :ensure_authenticated}
def mount(_params, _session, socket) do
# socket.assigns.current_user is available here
{:ok, assign(socket, page_title: "Dashboard")}
end
end
# In your router
live_session :authenticated,
on_mount: [
{MyAppWeb.Auth, :mount_current_user},
{MyAppWeb.Auth, :ensure_authenticated}
] do
live "/dashboard", DashboardLive
end
Best Practices
Secure Token Storage: Store tokens in HTTP-only cookies for web applications to prevent XSS attacks.
Token Refresh: Implement token refresh before expiration to maintain continuous authentication.
Error Handling: Properly handle authentication errors and provide feedback to users.
HTTPS: Always use HTTPS in production to protect authentication data.
Rate Limiting: Implement rate limiting for authentication endpoints to prevent brute force attacks.
Conclusion
This guide covered the essentials of using Supabase's GoTrue authentication service with Elixir applications. For more detailed information on specific functions, refer to the module documentation.