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/storage

45 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Connecting Auth data to custom tables

User data and Auth information stored in the Auth schema can be connected to custom tables using triggers and foreign key references.

Auth storage in Postgres database

Auth uses the project's Postgres database under the hood, storing user data and other Auth information in a special schema.

User session duration impact on SMTP load

Short-lived user sessions can problematically increase email volume by forcing active users to sign in frequently, increasing the number of messages needed to be sent. Consider increasing the maximum duration of user sessions. If seeing unnecessary increases in logins without a clear cause in SSR frameworks, check that the @supabase/ssr package is up to date and that middleware is correctly implemented to avoid early session termination.

Session storage in SSR: cookies instead of local storage

When using Supabase Auth with SSR, you must configure the Supabase client to store the user session in cookies instead of local storage.

Supabase client initialization for React Native requires platform-specific storage adapters

When initializing the Supabase client for React Native apps, you must use platform-specific storage adapters: Expo SecureStore for mobile to encrypt session information, and AsyncStorage for web. The tutorial demonstrates creating separate configuration files (lib/supabase.web.ts and lib/supabase.ts) for each platform.

Expo SecureStore encryption uses aes-js library with 256-bit keys

To encrypt user session information in Supabase Auth with React Native, use the `aes-js` library implementing AES encryption in CTR mode. A new 256-bit encryption key is generated using the `react-native-get-random-values` library. The encryption key is stored in Expo SecureStore while the encrypted value is placed in AsyncStorage. When implementing ExpoSecureStoreAdapter, keep the expo-secure-storage, aes-js, and react-native-get-random-values libraries up-to-date and choose the correct SecureStoreOptions (such as SecureStore.WHEN_UNLOCKED) for your app's security needs.

Custom storage adapter for PKCE flow

The client library can be configured to use a custom storage adapter when localStorage may not be available (such as server-side scenarios). The storage option accepts an object with three methods: getItem(key), setItem(key, value), and removeItem(key). Each method should handle fallback to alternate storage such as cookies when localStorage is not supported.

Custom storage adapter example

Example of implementing a SupportedStorage object with fallback logic: ```js import { type SupportedStorage } from '@supabase/supabase-js'; const supportsLocalStorage = () => true const customStorageAdapter: SupportedStorage = { getItem: (key) => { if (!supportsLocalStorage()) { // Configure alternate storage return null } return globalThis.localStorage.getItem(key) }, setItem: (key, value) => { if (!supportsLocalStorage()) { // Configure alternate storage here return } globalThis.localStorage.setItem(key, value) }, removeItem: (key) => { if (!supportsLocalStorage()) { // Configure alternate storage here return } globalThis.localStorage.removeItem(key) }, } ```

Customizable storage option for tokens

Supabase client libraries provide a customizable storage option when a client is initiated, allowing you to change where tokens are stored.

Cookie Max-Age parameter should not be set short

The Max-Age or Expires cookie parameters only control whether the browser sends the value to the server. Since a refresh token represents the long-lived authentication session, setting a short Max-Age or Expires parameter only results in degraded user experience.

SameSite cookie property recommendation

A good default for the SameSite property is to use Lax which sends cookies when users navigate to your site. Cookies typically require the Secure attribute which sends them over HTTPS only, but this can be problematic when developing on localhost.

Local storage vs secure cookie storage for tokens

The default behavior for non-SSR applications is to store access and refresh tokens in local storage. For server-side rendering, tokens must instead be stored in a secure cookie so they can be passed between client and server code.

HttpOnly cookies not necessary for Supabase tokens

Both access and refresh tokens are designed to be passed around to different components in the application. The browser-based side needs access to the refresh token to maintain a browser session, so HttpOnly cookies are not necessary.

Express environment variables and dotenv setup

For Express, set the following environment variables in .env: SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY. Install and initialize the dotenv package using npm install dotenv.

Astro environment variables for Supabase

For Astro, set the following environment variables in .env: PUBLIC_SUPABASE_URL and PUBLIC_SUPABASE_PUBLISHABLE_KEY.

TanStack Start environment variables for Supabase

For TanStack Start, set the following environment variables in .env.local: VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY.

CDN and ISR caching can leak sessions between users

If your app uses ISR (Incremental Static Regeneration) or is deployed behind a CDN, caching of HTTP responses can cause users to receive another user's session. When a session is refreshed, the new token is written to the response via Set-Cookie. If that response is cached and served to a different user, that user will be signed in as the wrong person. This must be handled carefully in SSR setups.

Astro server client with createServerClient

In Astro, create a server client using createServerClient with cookies configuration. The cookies.getAll method should parse the Cookie header using parseCookieHeader. The cookies.setAll method should set cookies via Astro.cookies.set and apply cache control headers to Astro.response.headers.

Remix server and browser client setup example

In Remix, create a server client in both loader and action functions using createServerClient. Use parseCookieHeader to read the Cookie header and serializeCookieHeader to set cookies in the responseHeaders. Return the SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY from the loader so the browser component can create a client with createBrowserClient.

SvelteKit server-side hooks for auth

In SvelteKit, set up server-side hooks in src/hooks.server.ts to create a request-specific Supabase client, check user authentication, and guard protected pages. Add type definitions for new event.locals properties in src/app.d.ts to prevent TypeScript errors. Create a Supabase client in the root +layout.ts and pass the session from event.locals via a +layout.server.ts file to access the Auth token on the server.

TanStack Start does not require a proxy for session refresh

Unlike Next.js, TanStack Start renders matched routes on the server by default, so beforeLoad and loader run server-side on the initial request. This means you don't need a proxy or middleware layer to keep sessions fresh — the server client reads and writes the session cookie directly on each request.

TanStack Start route protection with server functions

In TanStack Start, protect routes by writing a server function like fetchClaims that calls supabase.auth.getClaims() and returns the claims or null if the session isn't valid. Call fetchClaims from a layout route's beforeLoad hook before any nested route renders, and redirect to /login when it returns null. Every server function that returns or mutates private data needs this same check; don't rely on the route nesting alone.

Astro static vs SSR configuration

By default, Astro apps are static, with requests for data happening at build time rather than when the user requests a page. To use Supabase Auth with Astro, configure SSR by setting output: 'server' in astro.config.mjs.

Express server client creation example

In Express, create a server client by calling createServerClient with cookies configuration. Use parseCookieHeader to read from context.req.headers.cookie, and use serializeCookieHeader to set cookies via context.res.appendHeader('Set-Cookie', ...). Apply cache headers via context.res.setHeader().

Nuxt server route client example

In Nuxt server routes, create a Supabase client by calling createServerClient inside a defineEventHandler. Use parseCookieHeader to parse the Cookie header via getHeader(event, 'Cookie'). Use serializeCookieHeader and appendHeader to set cookies on the response.

Hono environment variables for Supabase

For Hono, set the following environment variables in .env: SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY.

Remix environment variables for Supabase

For Remix, set the following environment variables in .env: SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY.

Next.js environment variables for Supabase SSR

For Next.js SSR, set the following environment variables in .env.local: NEXT_PUBLIC_SUPABASE_URL (the Supabase project URL) and NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY (the publishable key).

@supabase/ssr package for SSR cookie handling

To use Server-Side Rendering (SSR) with Supabase, you need to install the @supabase/ssr helper package alongside @supabase/supabase-js. This package configures the Supabase client to use cookies for session management in SSR applications.

Auth token cookie name format

The default cookie name for Supabase Auth tokens is sb-<project_ref>-auth-token.

Next.js SSR auth setup requires two client types

Next.js applications need two types of Supabase clients: (1) Client Component client for code running in the browser, and (2) Server Component client for code running only on the server (Server Components, Server Actions, Route Handlers).

Next.js Proxy refreshes and stores auth tokens

Since Next.js Server Components cannot write cookies, a Proxy is required to refresh expired Auth tokens and store them. The Proxy is responsible for: (1) Refreshing the Auth token by calling supabase.auth.getClaims(), (2) Passing the refreshed Auth token to Server Components via request.cookies.set so they don't attempt to refresh the same token themselves, and (3) Passing the refreshed Auth token to the browser via response.cookies.set so it replaces the old token.

Supabase client setAll cookie headers must be applied to response

When the @supabase/ssr cookies.setAll method is called, it receives a headers object containing cache headers (Cache-Control, Expires, Pragma) that must be applied to the HTTP response to prevent CDNs from caching the response and leaking the session to other users. In Next.js, this is handled in the Proxy; in Server Components, the headers cannot be set, which is why the setAll call is wrapped in a try/catch and the error is ignored.

Use supabase.auth.getClaims() for server-side page protection

Always use supabase.auth.getClaims() to protect pages and user data on the server. Never trust supabase.auth.getSession() inside server code such as middleware or proxies, as it isn't guaranteed to revalidate the Auth token. getClaims() is safe to trust because it validates the JWT signature against the project's published public keys every time.

Supabase clients are lightweight and should be created per request

Creating a Supabase client is lightweight and should be done for every route/request. On the server, it configures a fetch call and needs to be reconfigured for every request to include the cookies from that request. On the client, createBrowserClient uses a singleton pattern, so only one instance is ever created regardless of how many times the createClient function is called.

SvelteKit environment variables for Supabase

For SvelteKit, set the following environment variables in .env.local: PUBLIC_SUPABASE_URL and PUBLIC_SUPABASE_PUBLISHABLE_KEY.

Nuxt environment variables and runtime config

For Nuxt, set NUXT_PUBLIC_SUPABASE_URL and NUXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY in .env. In nuxt.config.ts, map these public env vars into runtime config keys under runtimeConfig.public with keys supabaseUrl and supabasePublishableKey.

React Router environment variables for Supabase

For React Router, set the following environment variables in .env: SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY.

HTTP-only cookies for token storage limitations

Using HTTP-only cookies to store access and refresh tokens is only feasible for apps using the traditional server-only web app approach where all application logic is implemented on the server and it returns rendered HTML only. If your app uses any client-side JavaScript to build a rich user experience, using HTTP-only cookies is not feasible since only your server will be able to read and refresh the session while the browser will not have access to the tokens.

Custom storage implementation for tokens

You can override the storage option when creating the Supabase client on the server to store values in cookies or your preferred storage choice. The customStorageObject should implement the getItem, setItem, and removeItem methods from the Storage interface. Async versions of these methods are also supported.

Custom storage example for HTTP-only cookies

Example of overriding storage when creating Supabase client: import { createClient } from '@supabase/supabase-js' const supabase = createClient('SUPABASE_URL', 'SUPABASE_PUBLISHABLE_KEY', { auth: { storage: { getItem: () => { return Promise.resolve('FETCHED_COOKIE') }, setItem: () => {}, removeItem: () => {}, }, }, })

Cookie expiration for token storage

When using cookies to store access and refresh tokens, make sure that the Expires or Max-Age attributes of the cookies is set to a timestamp very far into the future. Browsers will clear the cookies, but the session will remain active in Supabase Auth. Therefore it's best to let Supabase Auth control the validity of these tokens and instruct the browser to always store the cookies indefinitely.

Deleting user does not automatically sign out user

Deleting a user from the auth.users table does not automatically sign out a user. Because Supabase uses JSON Web Tokens (JWT), a user's JWT will remain valid until it expires.

auth.admin.deleteUser removes row from auth.users

Using auth.admin.deleteUser() with the default shouldSoftDelete: false removes the row from auth.users, which cascades to auth.sessions and invalidates the user's refresh tokens, preventing the account from minting new access tokens.

Supabase auth.users table

A Supabase project includes an auth.users table in the database for storing user information. You can view the table using SQL SELECT * FROM auth.users.

Give your agent this brain