Introduction to the

At WWDC 2019, Apple introduced Sign In with Apple, a new feature In iOS 13 that allows users to log into apps using their Apple ID without having to enter their email, password and verify their login email. At the same time, Sign In with Apple offers cross-platform features and improved security.

On the other hand, it also puts forward new audit requirements. In the new requirements, it mentions that any application that includes third-party login also needs to adapt Sign In with Apple, otherwise there will be audit risks:

Sign In with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year.

In addition, to use Sign In with Apple, users need to enable two-step authentication. If it is not enabled, users will be prompted to enable it when using it for the first time. Otherwise, users will not be able to use it.

How to access Sign In with Apple

1. Project configuration

Add Sign in with Apple capability:

And join in the project AuthenticationServices. The framework can be. When you need to use, need to added in the file < AuthenticationServices/AuthenticationServices. H > references.

2. Add a built-in login button

Login button button can use apple recommend ASAuthorizationAppleIDButton, specific design style can see here, the style of roughly as follows:

Note:

  • The built-in login button needs to be in a prominent position. There’s no emphasis on it being in the first place, but it doesn’t need users to scroll to see it.
  • The size and rounded corners of the built-in login button can be adjusted, but there are maximum and minimum size limits.
  • There is no emphasis on using the built-in login button, but the design guide states that it is best to use a similar design.

Handling login Events

3.1 Creating a Request

3.1.1 New User Login

In the new login user clicks on the built-in buttons, expect to use apple ID to register and login, we need to use to create a ASAuthorizationAppleIDRequest ASAuthorizationAppleIDProvider request, in this request, We can configure an array of ASAuthorizationScope to specify what kind of information the user needs to provide. Currently, ASAuthorizationScope only contains two:

  • ASAuthorizationScopeEmail: requires the user to provide an E-mail address
  • ASAuthorizationScopeFullName: requires the user to provide name

It should be noted that the user can choose to hide the real email address when providing the email, so that the email address can be obtained like this:

[email protected]

Emails received from the mailbox are forwarded to the user’s real mailbox. When a name is required, the user can change the name at will.

After filling in your name and choosing whether to hide your email, you can enter your Apple ID password and automatically complete the registration process. If there is no network, you can’t continue and stay on this page.

Example code:

// Create the request

ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
[request setRequestedScopes:@[ASAuthorizationScopeFullName,ASAuthorizationScopeEmail]];
    
Copy the code

3.1.2 Logging In as an old User

If our APP users have landed before, and on the keyChain preserved the user name and password, you can also use ASAuthorizationAppleIDProvider and ASAuthorizationPasswordProvider to create request

This method is aimed at the situation that users have logged in to the app with their account and password and have saved them into the keyChain. Since it is not meaningful for the current status of my project, I will not discuss it in this paper.

3.2 Initiating a Request

The initiating needed ASAuthorizationController, it can also make multiple Provider’s request.

Example code:

// Initiate a request

ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
controller.delegate = self;
controller.presentationContextProvider = self;
[controller performRequests];

Copy the code

After the request is initiated, the UI of Sign In with Apple will appear. After the user completes login and other operations, the request result will be returned and processed by our APP.

3.3 Processing the Request Result

ASAuthorizationController in which provides ASAuthorizationControllerDelegate agent, used to request the results of the callback, agency provides two methods:

Successful callback:

    • (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization

Failure callback

    • (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error

In a successful callback, we can get an ASAuthorization object with provider and Credential attributes, where the Provider attribute tells us what kind of provider initiated the request. Credential is an authentication of the result of an Apple account login.

In the case of the “new user login”, return the credential for ASAuthorizationAppleIDCredential, and under the condition of “old user login”, it returns ASPasswordCredential.

We focus on the ASAuthorizationAppleIDCredential properties of resolution:

  • User ID: Apple user unique identifier, it is the same under the same developer account under all apps, we can use it to bind with the background account system (similar to wechat)OpenID).
  • Verification DataIncluding:identityToken.authorizationCode. It is passed to the developer backend server, which then verifies the validity and authenticity of the authorized login request data to Apple’s authentication server.
  • Account Information: Name, Verified Email, and Apple user Information, including full Name, verified email address, etc.
  • Real User Indicator: Determines whether the current apple account is a real user. The value can be:unsupported,unknown,likelyReal.

Example code:

- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization {
		//Sign with Apple
		if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
    		// Use Sign With Apple
  			
			ASAuthorizationAppleIDCredential *credential = authorization.credential;
  			NSString *userID = credential.user;
  			NSString *fullname = credential.fullName;
  			NSData *token = credential.identityToken
  			
  			// Continue the client login authentication}}Copy the code

3.4 Verifying Data with the server

Sequence diagram

The overall process is similar to a common third-party login. You also need to obtain the user ID and token and submit them to the background to verify the validity of the login.

Validation process correlation

  1. Step 1 and step 2 are completed on the clientASAuthorizationAppleIDProviderIf the login is successful, Apple will return the following data:
  • User ID: Apple user unique identifier, it is the same under the same developer account under all apps, we can use it to bind with the background account system (similar to wechat)OpenID).
  • Verification DataIncluding:identityToken.authorizationCode. It is passed to the developer backend server, which then verifies the validity and authenticity of the authorized login request data to Apple’s authentication server.
  • Account Information: Apple user Information, including full name and email address. Users can choose to hide their real email address or change their name when logging in.
  • Real User Indicator: Determines whether the current apple account is a real user. The value can be:unsupported,unknown,likelyReal.
  1. In steps 3 and 4, the client willidentityToken.authorizationCode.userIDThese three parameters are passed to the server to verify the validity of the login.

Where identityToken is a signed JSON Web Token(JWT), it contains:

It is divided into three parts:

  • Header: contains the key ID and encryption algorithm
  • payload:
    • Iss: Issuing agency, Apple
    • Aud: receiver and target app
    • Exp: indicates the expiration time
    • Iat: issue time
    • Sub: user id
    • C_hash: a hash sequence whose function is unknown
    • Auth_time: indicates the signature time
  • Signature: The signature used to verify JWT

After obtaining the identityToken sent by the client, the server needs to perform the following steps:

  1. You need to reverse engineer the process and decode out the three parts of the JWT
  2. fromappleid.apple.com/auth/keysTo obtain the public key and convert the public keyconversionforpemVerify the JWT
  3. Such asidentityTokenAfter verification, you can perform operations such as verification based on the payload

Token authentication principle:

Because idnetityToken uses asymmetric encryption RSASSA [RSA signature Algorithm] and ECDSA [Elliptic Curve data Signature Algorithm], when verifying the signature, it uses the public key to decrypt the Singature. If the decrypted content is the same as the base64UrlEncode(header) + “.” + base64UrlEncode(Payload), the authentication succeeds.

Mechanism of preventing man-in-the-middle attack:

The token is a JWT generated by Apple using the private key, and the public key is given. We verify the token. Since the middle man does not have apple’s private key, the token generated by it cannot be verified using the public key given by Apple to ensure the security of the token.

4. Handle the Apple ID login status change

Users log in using their Apple ID, so you should handle things like ID logging out. In addition, after logging in with Apple ID, the user can delete the previously logged application on the Settings page, similar to unbinding. In this case, the application also needs to do corresponding processing.

Apple provides a quick API that lets us query a user’s Apple ID status:

- [ASAuthorizationAppleIDProvider getCredentialStateForUserID:completion:]
Copy the code

This interface uses the userID obtained at login to quickly return account status:

  • Authorized: certified
  • NotFound: The user may not have tied an account to an Apple ID
  • Revoked: The account is revoked

This method should be called when the application is returned to the foreground at startup to ensure that the account status is up to date.

conclusion

  • As a login method similar to three-party login, the background needs to pay attention to the login status verification and the binding logic between the account and the Apple userID.
  • Apple account switching and logout will be handled on the client and the account will be logged out when the status changes.

In addition, Apple in and background verification of a document is too vague, the web and app side of the verification process is also very big difference, let head big.

Follow my blog for more content

Reference documentation

  • Fetch Apple’s public key for verifying token signature
  • What the Heck is Sign In with Apple?
  • So They’ve Signed in with Apple, Now What?
  • OS13 Sign In With Apple adaptation
  • JWT.io
  • JSON Web Token – Securely transfers information between Web applications