Set up Sign in with Apple

Apple is the fiddly one: the client id isn’t what you’d guess, the client secret isn’t a secret, and the return URL has to be on a domain Apple has verified. Each step below says which value goes where. The same walkthrough in prose is at docs/setup/apple.
  1. 1

    Create an App ID

    In the Apple Developer portal, go to Identifiers → + → App IDs → App. Give it a description — that’s what users see during sign-in — set a bundle ID, tick Sign In with Apple, and register.
    Bundle ID (example)
    com.aussieauth.app
    Reverse-domain form. Keep it; step 6 needs it.
  2. 2

    Create a Services ID — this is your client id

    Back on Identifiers, + → Services IDs. Description is your app’s name; the identifier is again reverse-domain.
    Services ID (example)
    com.aussieauth.app.si

    This identifier is APPLE_CLIENT_ID, not the App ID from step 1. It is the single most common thing to get wrong here, and the resulting error says nothing useful.

  3. 3

    Configure the Services ID

    Open it, enable Sign In with Apple, click Configure, and set the App ID from step 1 as the primary.
    Domain
    aussieauth.com
    Return URL
    https://aussieauth.com/api/auth/callback/apple
    Your own domain — not the .convex.site deployment. Apple verifies the domain before accepting a return URL and won’t take localhost or anything without TLS, so this one path is proxied through the site by vercel.json. Every other provider calls the deployment directly.
  4. 4

    Create the signing key

    Keys → +, name it, tick Sign In with Apple, choose your primary App ID, and download the .p8 file. Apple gives it to you exactly once.
    Services ID from step 2
    bunx convex env set APPLE_CLIENT_ID "com.aussieauth.app.si"
    Team ID — top right of the developer portal
    bunx convex env set APPLE_TEAM_ID "<team id>"
    Key ID — shown with the key you just made
    bunx convex env set APPLE_KEY_ID "<key id>"
    Private key — the whole file, BEGIN/END lines included
    bunx convex env set APPLE_PRIVATE_KEY "$(cat AuthKey_XXXXXXXXXX.p8)"
    Escaped \n are fine; they're unescaped before parsing.
    There is no client secret to set. Apple’s is a JWT you sign yourself, and it rejects one dated more than six months out — so AussieAuth stores the key material and mints a fresh token per request. Nothing here expires and nothing needs rotating.
  5. 5

    Verify the domain

    Apple hands you a verification file when you add the domain in step 3. Paste its contents into an environment variable rather than committing it — convex/http.ts serves it at the path Apple looks for, and vercel.json proxies that path from your domain.
    Domain association
    bunx convex env set APPLE_DOMAIN_ASSOCIATION "<file contents>"
    Where Apple will fetch it
    https://aussieauth.com/.well-known/apple-developer-domain-association.txt
    Load it in a browser first, then press Verify in the portal.
  6. 6

    Native iOS, if you have one

    For native sign-in Apple issues the id token against the bundle id, not the Services ID, so without this the JWT validation fails. Skip this step if there’s no iOS app.
    Bundle identifier from step 1
    bunx convex env set APPLE_APP_BUNDLE_IDENTIFIER "com.aussieauth.app"
    APPLE_APP_SITE_ASSOCIATION serves the file iOS fetches to let a native app use this domain’s passkeys and links. It 404s while unset, which is the honest answer — iOS caches what it fetches, so a malformed file is worse than no file.
  7. 7

    Check Apple is live

    This checks all four of APPLE_CLIENT_ID, APPLE_TEAM_ID, APPLE_KEY_ID and APPLE_PRIVATE_KEY — the provider only registers when every one is present.Environment variables take a moment to propagate after convex env set. This asks the deployment directly.
Your apps talk to this server directly — no AussieAuth consent screen, ever.