new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Supabase · Auth · all subjects

authentication/methods

414 notes in this subject, read out of this brain and free to use. This is page 5 of 7.

Passkey sign-in error codes

In addition to passkey-specific errors, signInWithPasskey() returns the usual sign-in failure modes: email_not_confirmed, phone_not_confirmed, and user_banned.

Passkey authentication overview

Passkeys are passwordless credentials built on the WebAuthn standard. The user proves possession of a private key stored on their device or password manager using biometrics, a PIN, or a hardware security key. The matching public key is registered with Supabase Auth and used to verify future sign-ins. Passkeys are phishing-resistant and remove the need to manage shared secrets.

Passkey support is experimental

Passkey support is experimental and the API may change without notice. Developers must explicitly opt-in when creating the Supabase client.

Passkey authentication client library requirements

Passkey authentication requires @supabase/supabase-js v2.105.0 or later, supabase_flutter v2.15.0 or later, or supabase-swift v2.48.0 or later.

WebAuthn ceremony three steps

Each passkey sign-in or registration is a WebAuthn ceremony with three steps. First, the client requests a challenge from Supabase Auth. Second, the platform's passkey API prompts the user for biometrics or a security key. Third, the signed response is sent back to Supabase Auth, which validates the challenge and either stores the new credential or issues a session.

Passkey uses discoverable credentials

Supabase Auth uses discoverable credentials for sign-in. The user does not need to provide an email, phone, or username — the authenticator resolves the account from the credential it stores.

Passkey registration prerequisites

Registering a passkey requires an existing, confirmed, non-anonymous user.

Passkey sign-in prerequisites

Sign-in with a passkey works for any user that has previously registered a passkey, provided their email or phone is confirmed and the account is not banned.

Enable passkey authentication on dashboard

To enable passkey authentication, open the Passkeys settings from the Authentication → Passkeys section of the Supabase Dashboard and turn on Enable Passkey authentication. Fill in the WebAuthn relying party details: Relying Party Display Name (a human-readable name for your application shown during the passkey prompt, for example "My App"), Relying Party ID (the bare domain name for your application, for example "example.com", without scheme, port, or path), and Relying Party Origins (comma-separated list of allowed origins, up to 5 origins).

Relying Party Origins requirements

For Relying Party Origins: HTTPS is required except for loopback addresses ("localhost", "127.0.0.1", "[::1]"). Each origin's hostname must match or be a subdomain of the Relying Party ID. Android native apps can use an app origin of the form android:apk-key-hash:<base64url SHA-256 of the signing certificate>.

Changing Relying Party ID invalidates existing passkeys

Passkeys are cryptographically bound to the Relying Party (RP) ID they were registered against. Changing the RP ID makes every existing passkey unusable for sign-in, and users will need to register a new one. Pick the RP ID carefully before users start enrolling, and keep it stable once they do.

Enable passkey in Supabase config.toml

To enable passkey authentication via CLI, add the following to supabase/config.toml: [auth.passkey] enabled = true [auth.webauthn] rp_display_name = "My App" rp_id = "example.com" rp_origins = ["https://example.com", "https://app.example.com"] The [auth.webauthn] section is required when auth.passkey.enabled is true.

Enable passkey via Management API

Passkeys can be configured via the Management API at https://api.supabase.com/v1/projects/{PROJECT_REF}/config/auth. Use a GET request to read the current passkey configuration, which returns passkey_enabled, webauthn_rp_id, webauthn_rp_display_name, and webauthn_rp_origins. Use a PATCH request to enable passkeys and set WebAuthn relying party details with JSON body containing passkey_enabled (boolean), webauthn_rp_display_name (string), webauthn_rp_id (string), and webauthn_rp_origins (comma-separated string).

Enable passkey in JavaScript client

To enable passkey support in JavaScript, pass the experimental flag when creating the Supabase client: const supabase = createClient(supabaseUrl, supabaseKey, { auth: { experimental: { passkey: true }, }, })

Passkey support in Dart SDK

The Dart SDK does not require an opt-in flag — the methods are annotated @experimental so the analyzer surfaces them as preview API. The server independently rejects calls with passkey_disabled when the dashboard toggle is off. supabase_flutter performs the server side of the WebAuthn ceremony and delegates the platform prompt (FaceID/TouchID/security key) to an authenticator you supply. Add a passkey plugin to your app and pass its authenticator to registerPasskey() and signInWithPasskey().

Passkey support in Swift SDK

The Swift SDK gates passkey support behind @_spi(Experimental). Add this import to every file that uses passkey APIs: @_spi(Experimental) import Supabase The SupabaseClient itself needs no extra configuration — the experimental SPI is enabled at the import site, not at client initialization. Platform setup (Associated Domains entitlement and a relying-party server with HTTPS) must be configured in your Xcode project.

Register passkey JavaScript example

To register a passkey in JavaScript, call auth.registerPasskey() which runs the full WebAuthn ceremony: const { data, error } = await supabase.auth.registerPasskey() if (error) { // User cancelled, browser doesn't support WebAuthn, or verification failed console.error(error) } else { console.log('Registered passkey', data.id) }

Register passkey Dart example

To register a passkey in Dart, call auth.registerPasskey() with an authenticator: try { final Passkey passkey = await supabase.auth.registerPasskey(authenticator); print('Registered passkey ${passkey.id}'); } on AuthException catch (e) { // The Supabase server rejected the credential. print(e); } catch (e) { // User cancelled or the platform ceremony failed. print(e); }

Register passkey Swift example

To register a passkey in Swift (iOS 16+, macOS 13+, visionOS 1+), call registerPasskey() with a presentation anchor: do { let passkey = try await supabase.auth.registerPasskey( presentationAnchor: view.window! ) print("Registered passkey \(passkey.id)") } catch { // AuthError from the server, or user cancelled the native UI. print(error) }

Passkey registration response structure

The registerPasskey() method returns a passkey object with the following properties: id (UUID — use this to update or delete the passkey), friendly_name (optional string derived from the authenticator's AAGUID, for example "iCloud Keychain", "Google Password Manager", "1Password"), and created_at (timestamp string).

Sign in with passkey JavaScript example

To sign in with a passkey in JavaScript, call auth.signInWithPasskey() which runs the full discoverable-credential authentication ceremony: const { data, error } = await supabase.auth.signInWithPasskey() if (error) { console.error(error) } else { // data.session and data.user are set; the client also dispatches a SIGNED_IN event console.log('Signed in as', data.user?.email) }

Sign in with passkey Dart example

To sign in with a passkey in Dart, call auth.signInWithPasskey() with an authenticator: try { final AuthResponse res = await supabase.auth.signInWithPasskey(authenticator); // res.session and res.user are set; the client also fires AuthChangeEvent.signedIn print('Signed in as ${res.user?.email}'); } on AuthException catch (e) { print(e); }

Sign in with passkey Swift example

To sign in with a passkey in Swift (iOS 16+, macOS 13+, visionOS 1+), call signInWithPasskey() with a presentation anchor: do { let response = try await supabase.auth.signInWithPasskey( presentationAnchor: view.window! ) // response.session and response.user are set; the client also fires a signedIn event. print("Signed in as \(response.user?.email ?? \"\")") } catch { print(error) }

Two-step passkey API for authentication JavaScript

For custom UI or full control over the WebAuthn ceremony in JavaScript, use the lower-level auth.passkey namespace for authentication: const { data: options } = await supabase.auth.passkey.startAuthentication() // Run the WebAuthn ceremony yourself (e.g.: using a native WebAuthn library) const credential = await runAuthenticationCeremony(options.options) const { data } = await supabase.auth.passkey.verifyAuthentication({ challengeId: options.challenge_id, credential, })

Two-step passkey API for authentication Dart

For custom UI or full control over the WebAuthn ceremony in Dart, use the two-step API for authentication: final authentication = await supabase.auth.passkey.startAuthentication(); // Run the platform ceremony yourself (e.g. using a passkey plugin). final Map<String, dynamic> credential = await runAuthenticationCeremony( authentication.options, ); final AuthResponse res = await supabase.auth.passkey.verifyAuthentication( challengeId: authentication.challengeId, credential: credential, );

Passkey limitation: SSO users cannot register

SSO users cannot register passkeys.

Two-step passkey API for authentication Swift

For custom UI or full control over the WebAuthn ceremony in Swift (all Apple platforms), use getPasskeyAuthenticationOptions() and verifyPasskeyAuthentication(): let options = try await supabase.auth.getPasskeyAuthenticationOptions() // Run the platform authenticator yourself (e.g. via ASAuthorizationController). let credential: AnyJSON = try await runAuthenticationCeremony(options.options) let response = try await supabase.auth.verifyPasskeyAuthentication( challengeId: options.challengeId, credentialResponse: credential )

WhatsApp channel support

WhatsApp is only supported as a channel for the Twilio and Twilio Verify SMS providers.

Verify phone OTP - Swift

To verify a phone OTP in Swift, use auth.verifyOTP() with phone, token, and type parameters: try await supabase.auth.verifyOTP( phone: "+13334445555", token: "123456", type: .sms )

Verify phone OTP - HTTP

To verify a phone OTP via HTTP, POST to /auth/v1/verify endpoint with type, phone, and token: curl -X POST 'https://<PROJECT_REF>.supabase.co/auth/v1/verify' \ -H "apikey: <SUPABASE_KEY>" \ -H "Content-Type: application/json" \ -d '{ "type": "sms", "phone": "+13334445555", "token": "123456" }'

Sign in with phone OTP - C#

To sign in with phone OTP in C#, use Auth.SignIn(): await supabase.Auth.SignIn(SignInType.Phone, "+13334445555");

Sign in with phone OTP - Kotlin

To sign in with phone OTP in Kotlin, use auth.signInWith(OTP) with phone parameter: supabase.auth.signInWith(OTP) { phone = "+13334445555" } To send via WhatsApp instead (requires Twilio or Twilio Verify provider): supabase.auth.signInWith(OTP) { phone = "+13334445555" channel = Phone.Channel.WHATSAPP }

Sign in with phone OTP - Swift

To sign in with phone OTP in Swift, use auth.signInWithOTP() with phone parameter: try await supabase.auth.signInWithOTP( phone: "+13334445555" )

Sign in with phone OTP - Python

To sign in with phone OTP in Python, use auth.sign_in_with_otp() with phone parameter: response = supabase.auth.sign_in_with_otp({ 'phone': '+13334445555', })

Sign in with phone OTP - HTTP

To sign in with phone OTP via HTTP, POST to /auth/v1/otp endpoint with phone number: curl -X POST 'https://<PROJECT_REF>.supabase.co/auth/v1/otp' \ -H "apikey: SUPABASE_KEY" \ -H "Content-Type: application/json" \ -d '{ "phone": "+13334445555" }'

Sign in with phone OTP - JavaScript

To sign in with phone OTP in JavaScript, use supabase.auth.signInWithOtp() with the phone parameter: const { data, error } = await supabase.auth.signInWithOtp({ phone: '+13334445555', })

Phone OTP rate limits and expiry

By default, a user can only request an OTP once every configured period and OTPs expire after a configured validity duration.

Enabling phone login configuration

For hosted Supabase projects, enable phone authentication on the Auth Providers page. For self-hosted projects or local development, use the configuration file with variables namespaced under auth.sms. Supported SMS providers include MessageBird, Twilio, Vonage, and TextLocal (community-supported).

Verify phone OTP - Python

To verify a phone OTP in Python, use auth.verify_otp() with phone, token, and type parameters: response = supabase.auth.verify_otp({ 'phone': '13334445555', 'token': '123456', 'type': 'sms', })

Phone Login benefits

Phone OTP login improves user experience by not requiring users to create and remember a password, increases security by reducing the risk of password-related security breaches, and reduces support burden of dealing with password resets and other password-related flows.

Phone Login overview

Phone Login is a method of authentication that allows users to log in without using a password. Users authenticate through a one-time password (OTP) sent via SMS or WhatsApp.

Update phone number - JavaScript

To update a user's phone number in JavaScript, use supabase.auth.updateUser() with phone parameter: const { data, error } = await supabase.auth.updateUser({ phone: '123456789', })

Update phone number - HTTP

To update a phone number via HTTP, POST to /auth/v1/verify endpoint with type 'phone_change', phone, and token after user receives SMS.

Update phone number - Python

To update a user's phone number in Python, use auth.update_user() with phone parameter: response = supabase.auth.update_user({ 'phone': '123456789', })

Phone OTP verification response

On successful phone OTP verification, the response includes access_token (Bearer token type), token_type (bearer), expires_in (3600 seconds), and refresh_token. The access token can be sent in the Authorization header for CRUD operations.

Update phone number - Swift

To update a user's phone number in Swift, use auth.updateUser() with phone parameter: try await supabase.auth.updateUser( user: UserAttributes( phone: "123456789" ) )

Update phone number - Kotlin

To update a user's phone number in Kotlin, use auth.updateUser(): supabase.auth.updateUser { phone = "123456789" }

Update phone number - C#

To update a user's phone number in C#, use Auth.Update(): var response = await supabase.Auth.Update(new UserAttributes { Phone = "123456789" });

Phone number update verification process

When updating a phone number, the user receives an SMS with a 6-digit pin that must be verified within 60 seconds. Use the 'phone_change' type when calling verifyOTP to complete the phone number update.

SSR frameworks and Supabase Auth compatibility

Supabase Auth is fully compatible with server-side rendering (SSR) frameworks. SSR frameworks move rendering and data fetches to the server to reduce client bundle size and execution time.

@supabase/ssr package for SSR setup

Supabase provides an @supabase/ssr package (available on npm) for setting up the Supabase client in SSR environments. This package is currently in beta, and adoption is recommended, but the API is still unstable and may have breaking changes in the future.

PKCE flow for SSR authentication

When using Supabase Auth with SSR, use the PKCE flow instructions where they differ from implicit flow instructions. If no difference is mentioned in the documentation, the implicit flow instructions can be followed.

Framework quickstarts for SSR

Supabase provides framework-specific quickstarts for SSR, including Next.js and SvelteKit. These quickstarts automatically configure Supabase to use cookies, making the user and their session available on both the client and server.

Expo React Native social auth tutorial uses Apple and Google providers

This tutorial demonstrates building a React Native app with Expo that implements social authentication using Supabase Auth. The app showcases a complete authentication flow with protected navigation using Supabase Database (Postgres with Row Level Security) and Supabase Auth with social authentication providers (Apple and Google).

Email verification requirement for Supabase Auth sessions in React Native

By default, Supabase Auth requires email verification before a session is created for the user. To support email verification in React Native apps, you need to implement deep link handling. For testing purposes, you can disable email confirmation in your project's email auth provider settings in the Supabase dashboard.

Redirect URLs configuration purpose

Supabase Auth allows you to control how user sessions are handled by your application using redirect URLs. The redirectTo parameter in the Supabase client library specifies where to redirect the user after authentication. The URL in redirectTo must match the Redirect URLs list configuration in the URL Configuration page.

Site URL as default redirect

The Site URL in URL Configuration defines the default redirect URL when no redirectTo is specified in the code. It should be changed from http://localhost:3000 to your production URL (for example, https://example.com). This setting is critical for email confirmations and password resets.

Wildcard patterns for redirect URLs

Supabase allows wildcard match patterns in redirect URLs. The wildcard patterns are: '*' matches any sequence of non-separator characters; '**' matches any sequence of characters; '?' matches any single non-separator character; 'c' matches character c (where c is not a special character); '\c' matches character c literally; '[!{character-range}]' matches any sequence of characters not in the range (for example, '[!a-z]' will not match any characters ranging from a-z). Separator characters in a URL are defined as '.' and '/'.

Redirect URL wildcard examples

Examples of redirect URLs with wildcards: 'http://localhost:3000/*' matches http://localhost:3000/foo and http://localhost:3000/bar but not http://localhost:3000/foo/bar or http://localhost:3000/foo/ (with trailing slash). 'http://localhost:3000/**' matches http://localhost:3000/foo, http://localhost:3000/bar, and http://localhost:3000/foo/bar. 'http://localhost:3000/?' matches http://localhost:3000/a but not http://localhost:3000/foo. 'http://localhost:3000/[!a-z]' matches http://localhost:3000/1 but not http://localhost:3000/a.

Netlify preview URL configuration

For deployments with Netlify, set SITE_URL to your official site URL. Add the following additional redirect URLs for local development and deployment previews: 'http://localhost:3000/**' and 'https://**--my_org.netlify.app/**'.

Give your agent this brain