Sign in with
Apple
Sign in with Apple stops working roughly every six months. The secret expires, Apple never warns you — your users tell you instead. This Action rotates it on a schedule: set it up once and forget it.
How it breaks
The official advice for this is to set a calendar reminder every six months.
Five, not six — on purpose. Apple's ceiling is about six months, so the spare month is your margin if a run ever fails.
Your Supabase project is updated through its own API. No dashboard visit required — not now, not in six months.
Not on Supabase? Drop two inputs and the Action simply hands you the fresh secret as an output. Pipe it wherever your stack needs it.
The whole setup
One file in your repo and four secrets in your settings. Run it manually once — and never think about it again.
on: schedule: - cron: "0 6 1 */5 *" # every 5 months, with margin workflow_dispatch: {} # first run — manually jobs: rotate: runs-on: ubuntu-latest steps: - uses: oskar-makarov/apple-client-secret-rotator@v1 with: apple_team_id: ${{ secrets.APPLE_TEAM_ID }} apple_key_id: ${{ secrets.APPLE_KEY_ID }} apple_services_id: com.example.app.web apple_p8: ${{ secrets.APPLE_P8 }} supabase_project_ref: your-project-ref supabase_access_token: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
Why you can trust it with your key
You hand this Action your Apple private key — so being verifiable matters more here than any promise.
It lives in your own GitHub Secrets and is used inside your own run. It isn't sent to me, and there's nowhere to send it — this Action has no server.
Not a single third-party library — only what Node already ships. Nothing can update itself and swap the contents behind your back.
rotate.js reads end to end in a few minutes. Don't trust the description — open it and see what it does before you install.
Take it, change it, use it commercially. Fork it and run from your own copy if that feels safer.
FAQ
Why every 5 months and not 6?
Apple's hard ceiling is around six months. Running every five leaves a month of margin: if one run fails, sign-in doesn't break.
Is my .p8 key safe?
It stays in your repository's secrets and never leaves your own workflow run. The Action has no server and no dependencies — the entire logic is one file you can read before installing.
Does this affect sign-in inside my iPhone app?
No. Native in-app sign-in doesn't use the client secret — expiry only affects sign-in through the web.
What if I'm not on Supabase?
Then the Action just hands you the fresh secret and you pass it to your own service. Works with Firebase, Auth0, self-hosted — anything.
Author
Oskar Makarov. This isn't theory: I hit this failure myself and wrote the rotation so I'd never hit it again. You don't have to take my word for it — the code is fully open and the Marketplace listing is one click away.
Free, forever. If it helps, take a look at Pipeline.md — it's about the same kind of trap, the kind that only shows up after launch.