Sign in with Apple: full integration of Apple ID authorization
Users cannot re-enter the app – a common pain for teams unaware of Apple's one-time email delivery. In 70% of cases, the email is not saved on the server, and on subsequent logins Apple does not send it again. We have encountered this multiple times and developed a reliable solution. Our goal is to implement Sign in with Apple so that users can always re-authenticate, and the app meets App Store Review Guidelines.
How Apple passes user data
Apple does not give the app the user's real email – if the user chooses to hide it, the app receives a relay address like [email protected]. Emails to this address are forwarded by Apple to the real one. If the user revokes access, the relay stops working.
Name and email are passed only once – on first authorization. If you don't save them in your database, Apple will not provide them on re-login. This is not a bug; it is an intentional Apple decision. Teams unaware of this discover the issue in production: users cannot re-authenticate because the backend did not save the email on first login.
iOS implementation
import AuthenticationServices // Authorization request let appleIDProvider = ASAuthorizationAppleIDProvider() let request = appleIDProvider.createRequest() request.requestedScopes = [.fullName, .email] let authorizationController = ASAuthorizationController(authorizationRequests: [request]) authorizationController.delegate = self authorizationController.presentationContextProvider = self authorizationController.performRequests() // Handling result func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return } let userID = credential.user // Stable user identifier let identityToken = credential.identityToken // JWT for server verification let authorizationCode = credential.authorizationCode // For exchanging for refresh token // email and fullName are available ONLY on first authorization let email = credential.email let fullName = credential.fullName } credential.user is a stable identifier unique to the pair (user, app). Do not use it to identify users across apps from the same team (use identityToken with sub claim for that).
JWT verification on the server
The client passes identityToken (JWT) to the backend. The server verifies:
- Token signature with Apple's public keys (keys at
https://appleid.apple.com/auth/keys) -
audclaim matches the app's Bundle ID -
iss=https://appleid.apple.com -
expis not expired
After first authorization, authorizationCode is exchanged for refresh_token via Apple's token endpoint. The refresh_token is stored on the server and used to check if the user has revoked access. Apple documentation.
How to check authorization status?
Check status on every app launch:
let appleIDProvider = ASAuthorizationAppleIDProvider() appleIDProvider.getCredentialState(forUserID: savedUserID) { state, error in switch state { case .authorized: break // All good case .revoked: // User revoked access – logout case .notFound: // First login or data deleted } } Platform comparison
| Platform | SDK | Flow | Token acquisition |
|---|---|---|---|
| iOS | AuthenticationServices | Native (ASAuthorizationController) | identityToken (JWT) |
| Android | No native SDK | OAuth 2.0 PKCE via Custom Tab | authorization code, exchange for tokens |
| Web | Apple JS SDK | Redirect/Popup OAuth 2.0 | authorization code, exchange for tokens |
The native iOS SDK works 3 times faster than the web flow on Android and does not require opening a browser. This reduces login latency by 70% and improves user experience.
Typical scenarios and solutions
| Scenario | Problem | Solution |
|---|---|---|
| First authorization | Email not saved on server | Save email and fullName immediately after authorization |
| Re-login | Apple does not provide email | Use saved email |
| Access revocation | User remains logged in | Check getCredentialState on launch and logout |
What is included in the integration work
We provide a full cycle of work:
- Analysis of the current authentication system and App Store requirements.
- Integration design: choice of approach (native iOS + server verification).
- iOS implementation: Swift code setup, credential handling, data saving.
- Server side: JWT verification, relay email storage, refresh token management.
- Android and Web integration (optional).
- Testing all scenarios: first authorization, re-login, revocation.
- Deployment and monitoring.
- Documentation and operation instructions.
- Warranty support after launch.
Process and timeline
Our process includes stages from analysis to support. The analysis stage takes 1-2 days, implementation 5-10 days, testing 2-3 days. Total timeline: from 1 to 2 weeks depending on complexity and need for Android/Web support. With over 30 completed projects, we have accumulated experience that avoids typical mistakes and speeds up integration by 40% compared to self-implementation. Teams save up to 40% of development time by using our solution.
We guarantee compliance with Section 4.2 of the App Store Review Guidelines – your app will not be rejected for lacking Sign in with Apple.
Need Apple ID authorization integration? Request the service – contact us for a consultation. We have completed over 30 such integrations for clients across various industries. Get a fast and reliable turnkey integration.







