Skip to content

feat(customers): revoke Sign in with Apple tokens when a customer deletes their account - #165

Open
roncodes wants to merge 1 commit into
mainfrom
feat/apple-sign-in-revocation
Open

roncodes wants to merge 1 commit into
mainfrom
feat/apple-sign-in-revocation

Conversation

@roncodes

Copy link
Copy Markdown
Member

Apple requires apps that offer Sign in with Apple and account deletion to revoke the user's Apple tokens when the account is deleted (App Review guideline 5.1.1(v)). The server used to ignore the authorizationCode the app sends at sign-in, and account closure never contacted Apple.

What changes

  • At Apple sign-in (loginWithApple): the authorization code is exchanged at https://appleid.apple.com/auth/token for a refresh token. It is stored encrypted in a new apple_sign_in_tokens table, one row per customer per app. The app (client_id) is the verified identity token's audience, and apple_user_id is its subject.
  • At account deletion (confirmAccountClosure): the customer's tokens are revoked at https://appleid.apple.com/auth/revoke before the account is deleted. When the user account is deleted too, tokens kept for that user's other storefront customers are revoked as well. The rows are removed either way.
  • Never blocking: a missing key, a refusal from Apple or a timeout doesn't stop sign-in or deletion. Each outcome is logged, and tokens are never logged.
  • Keys: the client secret is signed with core-api's AppleClientSecretFactory, which is already in ^1.6.74, so no core change is needed. Keys come from the organization's notification channels, matched by app_bundle_id = the token's audience:
    • the store's APN channel, when that key also has Sign in with Apple enabled. AppHelm's push guide already tells owners to tick both, so most stores configure nothing new.
    • a new Sign in with Apple channel type (apple_sign_in, same fields as APN) for a separate key. It's added to Settings → Notifications in the Console and is tried first.
    • if Apple answers invalid_client for one key, the next key is tried.
  • Store-owner guide: docs/sign-in-with-apple.md.

Upgrading

  • Run migrations: adds apple_sign_in_tokens on the storefront connection.
  • Customers who signed in with Apple before a key was configured have no token stored yet. Theirs is stored the next time they sign in with Apple.

Tests

AppleSignInRevocationTest has 7 tests with Apple's endpoints faked and a real EC key. They cover the token being stored encrypted and replaced on the next sign-in; key choice and fallback (the APN key, invalid_client falling through to the next key, other apps and other organizations ignored); no key configured; Apple refusing the code; sign-in still succeeding on a timeout; revocation on closure; and closure still succeeding when Apple refuses, times out, no key is configured or the token table can't be read. Full suite: 1169 tests pass.

Not in this PR

loginWithApple takes email and appleUserId from the request instead of the verified token, and core's AppleVerifier doesn't check the audience. That needs a core-api change plus a matching Storefront change.

…etes their account

Apple requires apps that offer Sign in with Apple and account deletion to revoke the
user's tokens on deletion (App Review 5.1.1(v)). At Apple sign-in the authorization
code is now exchanged for a refresh token, kept encrypted in apple_sign_in_tokens;
confirm-account-closure revokes it with Apple before deleting the account.

The client secret is minted with core-api's AppleClientSecretFactory from the store's
APN channel key when it also has Sign in with Apple enabled, or from a new
'apple_sign_in' notification channel, matched by bundle ID = the identity token's
audience. Missing keys and Apple failures are logged and never block sign-in or
deletion.
@codecov

codecov Bot commented Oct 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.43066% with 9 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.93%. Comparing base (af7d978) to head (4eaeef8).

Files with missing lines Patch % Lines
server/src/Support/AppleSignIn.php 93.23% 9 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##                main     #165      +/-   ##
=============================================
- Coverage     100.00%   99.93%   -0.07%     
- Complexity      4014     4058      +44     
=============================================
  Files            229      230       +1     
  Lines          14221    14357     +136     
=============================================
+ Hits           14221    14348     +127     
- Misses             0        9       +9     
Flag Coverage Δ
backend 99.93% <93.43%> (-0.07%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant