Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2020 Safari & WebSystem ServicesPrivacy & Security

WWDC20 · 31 min · Safari & Web / System Services / Privacy & Security

Get the most out of Sign in with Apple

Sign in with Apple makes it easy for people to sign in to your apps and websites with the Apple ID they already have. Fully integrate Sign in with Apple into your app using secure requests, and by handling state changes and server notifications. We’ll also introduce new APIs that allow you to let existing users switch to Sign in with Apple quickly and easily.

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 6 snippets

Create an Authorization Request swift · at 2:02 ↗
// Configure request, setup delegates and perform authorization request

    @objc func handleAuthorizationButtonPress() {
        let request = ASAuthorizationAppleIDProvider().createRequest()
        request.requestedScopes = [.fullName, .email]
        
        request.nonce = myNonceString()
        request.state = myStateString()
            
        let controller = ASAuthorizationController(authorizationRequests: [request])
            
        controller.delegate = self
        controller.presentationContextProvider = self
            
        controller.performRequests()
    }
Get a credential from an Authorization swift · at 5:37 ↗
// ASAuthorizationControllerDelegate

func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let credential = authorization.credential as? ASAuthorizationAppleIDCredential {
            let userIdentifier = credential.user
            let fullName = credential.fullName
            let email = credential.email
            let realUserStatus = credential.realUserStatus
            
            let state = credential.state
            let identityToken = credential.identityToken
            let authorizationCode = credential.authorizationCode
            
            // Securely store the userIdentifier locally
            self.saveUserIdentifier(userIdentifier)
            
            // Create a session with your server and verify the information
            self.createSession(identityToken: identityToken, authorizationCode: authorizationCode)
    }
}
Verify the state of a credential swift · at 8:51 ↗
// Getting a credential state
        
        let provider = ASAuthorizationAppleIDProvider()
        
        provider.getCredentialState(forUserID: getStoredUserIdentifier()) { 
                                                        (credentialState, error) in
            switch(credentialState) {
            case .authorized:
                // Sign in with Apple credential Valid
            case .revoked:
                // Sign in with Apple credential Revoked, Sign out
            case .notFound:
                // Credential was not found, fallback to login screen
            case .transferred:
                // Application was recently transferred, refresh User Identifier
            @unknown default:
                break
            }
        }
Migrate a user identifier swift · at 11:00 ↗
// Migrating a user identifier

        let request = ASAuthorizationAppleIDProvider().createRequest()
        request.requestedScopes = [.fullName, .email]
            
        request.user = getStoredUserIdentifier()
        
        request.nonce = myNonceString()
        request.state = myStateString()
            
        let controller = ASAuthorizationController(authorizationRequests: [request])
            
        controller.delegate = self
        controller.presentationContextProvider = self
            
        controller.performRequests()
Create a Sign in with Apple button swift · at 13:54 ↗
// SwiftUI example:

SignInWithAppleButton(.signIn) {
    onRequest: { (request) in
        request.requestedScopes = [.fullName, .email]
        request.nonce = myNonceString()
        request.state = myStateString()
    }
    onCompletion: { (result) in
        switch result {
        case .success(let authorization):
            // Handle Authorization
        case .failure(let error)
            // Handle Failure
        }
    }
}.signInWithAppleButtonStyle(.black)
convertAccountToSignInWithAppleWithoutUserInteraction swift · at 25:15 ↗
enum VerificationResult : Int { case success; case failure; case twoFactorAuthRequired;

override func convertAccountToSignInWithAppleWithoutUserInteraction(
    for serviceIdentifier: ASCredentialServiceIdentifier, 
    existingCredential: ASPasswordCredential
) {
    verifyCredential(existingCredential) { (result: VerificationResult) in
        switch result {
        case .failure:
            self.extensionContext.cancelRequest(withError: 
                ASExtensionError(.failed))
        case .success:
          self.extensionContext.getSignInWithAppleAuthorizationWithState(state: myStateString(),
                                                                         nonce: myNonceString(),      
                                                                         {}        
        case .twoFactorAuthRequired:
            self.extensionContext.cancelRequest(withError: 
                ASExtensionError(.userInteractionRequired))
    }
}

Resources