Flootdocs
AuthSocial

Apple

Set up Sign in with Apple for your Floot application.

The Apple button is already on the sign-in and sign-up screens, beside email and password. It becomes functional the moment Supabase has Apple credentials.

There is no ENABLE_ flag for Apple

Unlike Google Sign-In, Sign in with Apple is not behind a feature flag. Nothing to flip in .env.local; what gates it is [auth.external.apple].enabled in supabase/config.toml, which ships false.

Sign in with Apple requires a paid membership to the Apple Developer Program. Sign in with Apple is one of the restricted services which is not available for free with just an Apple ID (source).

Which credential you need depends on the platform, because the flow differs:

PlatformFlowCredential
iOS, macOSNative sheetAn App ID, your bundle identifier
Android, Web, Windows, LinuxBrowserA Services ID plus a signing key

Ship both and you need both, in one comma-separated OAUTH_APPLE_CLIENT_ID. Every example below uses the project from floot create my_app --org com.acme.

Apple Developer Console Setup

Create App ID

Go to identifiers section of the console → filter by App IDs (upper right menu) → click the + button (upper left, next to "Identifiers") → App IDs → App

  • Description > give a meaningful description
  • Bundle ID > floot create already set it: for my_app --org com.acme it is com.acme.myApp on both iOS and macOS. To read it out of the project instead, open the ios (or macos) folder in Xcode (right click on the folder → Open in Xcode) → Runner (sidebar) → General (tab bar) → Runner (TARGETS sidebar) → Identity → Bundle Identifier
  • Capabilities (tab bar) > select Sign in with Apple

→ Continue → Register

One character apart, and not interchangeable

The bundle identifier camel-cases your project name; the deep-link scheme flattens it. They differ by one character and are not interchangeable: OAUTH_APPLE_CLIENT_ID wants the camel-cased one. See The Apple client id.

Your deployed backend lists every App ID that signs in through it among its Apple provider's Client IDs; see In production.

Service ID & Keys (Android, Web, Windows, Linux)

Skip this whole section if you only ship iOS and macOS: the native sheet needs no Services ID, no key and no return URL.

Create Service ID

Go to identifiers section of the console → filter by Services IDs (upper right menu) → click the + button (upper left, next to "Identifiers") → Services IDs

  • Description > give a meaningful description
  • Identifier > use a unique reverse-domain that is not your bundle id (e.g. com.acme.myapp.web)

→ Continue → Register

Configure Service ID

Open the newly created service ID → enable Sign in with Apple → Configure

  • Primary App ID > choose the App ID you previously created in the step before
  • Domains and Subdomains > options:

Apple does not accept http protocol, but there is a solution using Local Port Forwarding with VS Code-based editors.

Know that the forward URL generated by this method is temporary. Meaning you'll have to repeat this process every-time you quit the editor (mainly the visibility which tends to go back in private state). To have have a static URL, you can use Zrok (open source) or Ngrok.

  • From your code editor, open the terminal.
  • PORTS (tab bar) → Forward a Port → 54321
  • Right click on created port → Port Visibility → Public
  • Use the generated endpoint (without the https protocol) to redirect Apple events to your Supabase local instance.

Example generated endpoint with https: https://3k5jk495-54321.abc1.devtunnels.ms/

<generated.forward.address.without.https>

Generated endpoint without the https: 3k5jk495-54321.abc1.devtunnels.ms

  • Return URLs > options:

Use the FULL HTTPS endpoint generated above.

<generated.forward.address>/auth/v1/callback

e.g. https://3k5jk495-54321.abc1.devtunnels.ms/auth/v1/callback

Whatever you enter here for your local stack becomes OAUTH_APPLE_REDIRECT_URI later on; your deployed backend's goes to its own Apple provider (see In production). Apple is the one provider that does not share SB_AUTH_EXTERNAL_REDIRECT_URI with the others, precisely because it will not accept the plain-http localhost URL that Google and GitHub are happy with.

Create & Download Key

Go to keys section of the console → click the + button (upper left, next to "Keys")

  • Key Name > give meaningful name
  • Key Usage Description (optional) > give a meaningful description
  • Select Sign in with Apple from the list → Configure
    • Primary App ID > choose the App ID you previously created in the step before → Save

→ Continue → Register → Download

Make sure you safely store the AuthKey_XXXXXXXXXX.p8 file. If you ever lose access to it, or make it public accidentally, revoke it from the Apple Developer Console and create a new one immediately. You will also have to generate a new secret key using this file every 6 months, so make sure you schedule a recurring reminder in your calendar!

Generate Secret Key

Important

Keep in mind that you will have to renew your secret key every 6 month! So make sure to keep track of it.

Go to Supabase's Apple Docs page → scroll until you find a tool (Ctrl/Cmd + F to search "tool" keyword can also help)

  • Account ID > it corresponds to your team id in your developer account
  • Service ID > refers to the Service ID created above
  • Choose File > refers to the downloaded key from the previous step

→ Generate Secret Key

Your deployed backend's Apple provider takes this secret too; see In production.

Floot App Setup

Which env file

supabase/.env.local and supabase/config.toml configure your local stack. Your deployed backend takes the Apple provider from its own settings; see In production.

Xcode configuration

At this point you should have added the Sign in with Apple capability to your own app.

In case you don't have Automatically manage Signing turned on in Xcode, you will need to recreate and download the updated Provisioning Profiles for your app, so they include the new Sign in with Apple capability. Then you can download the new certificates and select them in Xcode.

In case Xcode manages your signing, this step will be done automatically for you. Just make sure the Sign in with Apple capability is active as described below.

Additionally this assumes that you have at least one iOS device registered in your developer account for local testing, so you can run the example on a device.

  • Open your ios or macos folder in Xcode (right click on the folder → Open in Xcode)
  • Go to Runner (under TARGETS) → Signing & Capabilities
  • Click + Capability and add Sign in with Apple
  • That is all: Floot uses Swift Package Manager, so there is no pod install step

The Supabase environment

On iOS and macOS the sign-in sheet is native: the app gets an identity token from Apple and passes it straight to Supabase, which validates its audience against OAUTH_APPLE_CLIENT_ID. That value is therefore your bundle identifier, not a Services ID.

OAUTH_APPLE_CLIENT_ID="com.acme.myApp"

The capital letter is not a typo

floot create my_app --org com.acme camel-cases the project name for the iOS and macOS bundle identifiers, com.acme.myApp, while the deep-link scheme flattens it to com.acme.myapp. The two look almost identical and are not interchangeable. See The Apple client id.

The variable takes a comma-separated list, and only the first entry is used for the browser flow. So when one project serves both the native platforms and the others, put the Services ID first:

OAUTH_APPLE_CLIENT_ID="com.acme.myapp.web,com.acme.myApp"

The Supabase config

supabase/config.toml already points every key at a variable. Only enabled needs editing:

[auth.external.apple]
enabled = true
KeyShips asWhat to do
enabledfalseFlip it to true
client_idenv(OAUTH_APPLE_CLIENT_ID)Leave it; fill the variable
secretenv(OAUTH_APPLE_SECRET)Leave it; only the browser flow uses it
redirect_urienv(OAUTH_APPLE_REDIRECT_URI)Leave it; only the browser flow uses it

config.toml and supabase/.env.local configure your local stack. Your deployed backend needs the same bundle identifiers, and any Services ID, on its own Apple provider; see In production.

In production

Your deployed backend needs its own Apple provider, filled from the values you made above:

SettingValue
Client IDsThe Services ID first, then each bundle identifier: com.acme.myapp.web,com.acme.myApp
SecretThe generated secret (Generate Secret Key); only the browser flow uses it
RedirectThe production Return URL you registered on the Services ID (Configure Service ID)
  • Supabase Cloud: turn Apple on under Authentication → Sign In / Providers → Apple in the dashboard, and enter the Client IDs and the secret. The callback is the project's own, https://<project-id>.supabase.co/auth/v1/callback. See Providers.
  • Self-hosted: the stock compose file has no Apple block. Add GOTRUE_EXTERNAL_APPLE_ENABLED: "true", GOTRUE_EXTERNAL_APPLE_CLIENT_ID, GOTRUE_EXTERNAL_APPLE_SECRET and GOTRUE_EXTERNAL_APPLE_REDIRECT_URI (https://api.myapp.com/auth/v1/callback) to the auth service in your own compose file, then recreate the auth container. See Auth defaults that differ.

supabase config push could send [auth.external.apple] from config.toml to a linked Cloud project instead, but it fills each env() from your local supabase/.env.local, so it would push your tunnel as the redirect. Set the provider in the dashboard, or read Alternative: settings from config.toml first.

The secret expires 6 months after you generate it, on every host: generate a new one before then and replace it wherever you entered it.

On this page