iosswiftkeychainwwdcsign-in-with-apple

How to figure out "Sign in with Apple" in user with multiple devices with same apple id?


Here is my scenario.

Someone has iPhone and iPad (iOS 13.0 or later), and he signed up with same appleID.
And he `sign in with apple` in his iPhone and try to `sign in with apple` again in his iPad.

I don't want him to "sign in with apple" twice by editing his name or checking share or hide his email twice when he touch signIn Button.

I found out some codes from sample code that can help my scenario above

func performExistingAccountSetupFlows() {
    // Prepare requests for both Apple ID and password providers.
    let requests = [ASAuthorizationAppleIDProvider().createRequest(),
                    ASAuthorizationPasswordProvider().createRequest()]

    // Create an authorization controller with the given requests.
    let authorizationController = ASAuthorizationController(authorizationRequests: requests)
    authorizationController.delegate = self
    authorizationController.presentationContextProvider = self
    authorizationController.performRequests()
}

And I found out ASPasswordCredential will help me define credential user

  1. First, should I implement saving userIdentifier in iCloud Keychain? Then should I need to add Keychain group Capability?
  2. First, I don't really know where to put that performExistingAccountSetupFlows function in. I would like to present AuthorizationController when user touch button. So I tried this approach.
@available(iOS 13.0, *)
@objc private func handleAuthorizationAppleIDButtonPress() {
    let appleIDProvider = ASAuthorizationAppleIDProvider()
    appleIDProvider.getCredentialState(
        forUserID: KeychainItem.currentUserIdentifier ?? "") { [weak self] (credentialState, error) in
        guard let `self` = self else { return }
        log.debugPrint(KeychainItem.currentUserIdentifier ?? "nil")

        switch credentialState {
            case .authorized:
                // The Apple ID credential is valid. Show Home UI Here

                // MARK: Existing iCloud keychain 
                self.performExistingAccountSetupFlows() 
                break

            case .revoked, .notFound:
                let request = appleIDProvider.createRequest()
                request.requestedScopes = [
                    .fullName,
                    .email
                ]

                let controller = ASAuthorizationController(authorizationRequests: [request])
                controller.delegate = self
                controller.presentationContextProvider = self
                controller.performRequests()
                break
            default:
                break
            }
        }

}

And this doesn't work which I intended.

Is there any kind teacher who can answer my question?
Thank you.


Solution

  • You don't need to do anything. Apple handles it all for you by associating your app bundle with the identity in the user's iCloud.

    If they run your app on another device that has the same iCloud account then they are not given an opportunity to create a new account when they use "Sign in with Apple" - They will simply be prompted to sign in with their existing account.

    You can optionally use the code in performExistingAccountSetupFlows() to prompt the user to log in without needing to tap the "Sign in with Apple" button;

    When this code runs, if an existing account association is found they will be prompted to authenticate. If no account is found then nothing happens.