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:
| Platform | Flow | Credential |
|---|---|---|
| iOS, macOS | Native sheet | An App ID, your bundle identifier |
| Android, Web, Windows, Linux | Browser | A 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 createalready set it: formy_app --org com.acmeit iscom.acme.myAppon both iOS and macOS. To read it out of the project instead, open theios(ormacos) folder in Xcode (right click on the folder →Open in Xcode) →Runner(sidebar) →General(tab bar) →Runner(TARGETSsidebar) →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/callbacke.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 Applefrom the list →Configure- Primary App ID > choose the App ID you previously created in the step before →
Save
- Primary App ID > choose the App ID you previously created in the step before →
→ Continue → Register → Download
Make sure you safely store the
AuthKey_XXXXXXXXXX.p8file. 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 Signingturned on in Xcode, you will need to recreate and download the updated Provisioning Profiles for your app, so they include the newSign in with Applecapability. 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 Applecapability 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
iosormacosfolder in Xcode (right click on the folder →Open in Xcode) - Go to
Runner(underTARGETS) →Signing & Capabilities - Click
+ Capabilityand addSign in with Apple - That is all: Floot uses Swift Package Manager, so there is no
pod installstep
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| Key | Ships as | What to do |
|---|---|---|
enabled | false | Flip it to true |
client_id | env(OAUTH_APPLE_CLIENT_ID) | Leave it; fill the variable |
secret | env(OAUTH_APPLE_SECRET) | Leave it; only the browser flow uses it |
redirect_uri | env(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:
| Setting | Value |
|---|---|
| Client IDs | The Services ID first, then each bundle identifier: com.acme.myapp.web,com.acme.myApp |
| Secret | The generated secret (Generate Secret Key); only the browser flow uses it |
| Redirect | The 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_SECRETandGOTRUE_EXTERNAL_APPLE_REDIRECT_URI(https://api.myapp.com/auth/v1/callback) to theauthservice in your own compose file, then recreate theauthcontainer. 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.