This article is a summary of Apple's new technology called 'Sign in with Apple'. If you plan to integrate it into your application or if you are simply interested in how it works compared to other third party services, read on!

During WWDC19, one of Apple's main focus was Privacy. Ever since the popularity of the phone market, Apple was always proud of their transparent data handling. It's worth to note that we will never know how much data companies actually collect, but that shouldn't shadow Apple's newly introduced feature, Sign in with Apple.

Introduction to Sign in with Apple

The feature was revealed by Craig Federighi as a part of iOS 13 among other privacy focused features, like the smarter Location Services, during the Keynote event (Sign in with Apple starts at 40:18)

Craig Federighi announces Sign in with Apple

Apple's own login system, in contrast to already existing third-party services like Facebook Login or Sina Weibo Login, approaches the problem from a different perspective. Instead of sharing all kinds of personal information from your social network account with the developer, it only shares the absolutely necessary ones. While other services give developers the chance to request even more data than they need, Apple is very strict with the amount of required data in their guidelines. Furthermore, with Apple's email relay service, it's not just another, maybe more transparent service, but something developers have to prepare for.
In this article I will explain the most important differences from other services, and give a brief tutorial on how to integrate Sign in with Apple into your already existing app.

Differences from other services

You can choose what you share with the developer

Apple is very vocal about asking only the basics from the user. They can deny applications from App Store if developers try to ignore this guideline. As of right now with Apple's login, you can request a maximum of 2 scopes.
request.requestedScopes = [.fullName, .email]
If we don't request any scope, only a unique identifier will authenticate the user.
In case we request the email address, the user can choose to share only a private, "throwable" address, but more on that below.

Email relay service

No one likes getting spam, and even less people like getting spam and not knowing where it came from. If we use the same address on every site, there is no way to tell which website was the one who leaked it. Of course, there are already tricks to overcome this problem, like on Gmail, putting a . character to our address, or using the + character followed by a string that identifies the site, but all of these are not only service-specific, but also easily detectable. Not even throwable addresses are perfect, since in some cases you can actually get important emails after registration.
Apple addressed this issue and came up with their own feature integrated into Sign in with Apple.

Announcing the relay service

Upon registration, users now have different options on how to share their email addresses. (Obviously, only if it's required)
They can choose from emails that are connected to their Apple ID (mostly a main address and the @me.com or @icloud.com addresses)

Phone screen

Introduced with Sign in with Apple, users now also have the option to choose 'Hide My Email', a relay service by Apple. Upon choosing Hide My Email, the application will get a unique address, that is not only different among users, but also applications. The said address looks like this: 47ce76g3b4@privaterelay.appleid.com
Even if the address gets shared publicly, no one can use it other than the application's developers. Every application that uses Sign in with Apple, is required to be in Apple's Developer Program, and enable the function through the Developer Portal.

Apple Developer Portal

Each of the application's email addresses that it uses for communicating with users has to be registered on the Developer Portal, (or the server that has the application's MX server) thus preventing address sharing between different applications.
If a user doesn't want to get emails from a specific application anymore, they can easily disable it (at least it was mentioned during the WWDC Keynote, but we have yet to see it in practice).
Furthermore, Apple promises that the addresses are working (or at least they were connected to the Apple ID once) so there's no need to verify them with other methods either.

Antifraud system

In many cases application would like to know if the end user is in fact a user or just a bot. Almost every service needs an information like that, but most of the time, the authenticating process is most uncomfortable for the real users. Be it a photo verification or even sending pictures of blurred out ID cards in some more serious cases, the goal would be to get rid of them, while maintaining security. Sign in with Apple offers a solution for this problem as well. While it's not public how Apple determines real users (obviously), they promise if they say the user is real, they probably is. Apple says the devices use machine learning and various parameters (like the age of the account) to guess if someone is real or not.
This might all sound even too good, and since there aren't many real world cases for the functionality yet, we can't be sure how much companies will use the feature in the first place. But more on that later.

Policies regarding Sign in with Apple

Mandatory policies

  • Every app that has third-party login needs to have “Sign in with Apple” as well
    • Every new app has to implement it and every already existing app has to implement it until April, 2020
    • Overall there's good intention behind the idea, but requires extra work from all of the development teams (including frontend and backend too)

Exceptions from usage

  • It isn't required to use Sign in with Apple in a few cases, like

    • if your app only uses your company's login system
    • if "is an education, enterprise, or business app that requires the user to sign in with an existing education or enterprise account." (from Apple)
    • if the third-party system is to identify the user via government citizen identification system
    • if the app requires a certain third-party service (like an app based on Google Drive and it's functionalities)
  • There are some cases too, when Apple straight up prohibits the usage of Sign in with Apple but these aren't anything different from the industry standards (like it's not eligible in application promoting tobacco, guns, etc.)

Design guidelines

  • Apple provided an exact design guideline for the button that fits iOS features, like the newly introduced Dark Mode or various locales for the button label.

Implementing Sign in with Apple with your application

Requirements:

  • Xcode 11.0+
  • iOS 13+

After creating a new Project, go to Target -> Your App -> Signing & Capabilities

With the + Capability button in the top left corner, you can add the Sign in with Apple capability to your app.

Sign in with Apple

The code

import AuthenticationServices

After importing the new class, create a view and add the button to it

let authorizationButton = ASAuthorizationAppleIDButton()
buttonView.addSubview(authorizationButton)

As you can see the button appeared according to your system settings.

English locale with Light Mode

Now it's time to handle when the user wants to sign in. For that, first add an action to your newly created button.

authorizationButton.addTarget(self, action: #selector(handleClick), for: .touchUpInside)

At end of the file (for better readability), add two protocols as extensions for our class.

extension ViewController: ASAuthorizationControllerDelegate {
  // MARK: - ASAuthorizationControllerDelegate
}

extension ViewController: ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return self.view.window!
    }
}

And then finally write the touch handler function.

@objc
func handleClick() {
    let appleIDProvider = ASAuthorizationAppleIDProvider()
    let request = appleIDProvider.createRequest()
    request.requestedScopes = [.fullName, .email]

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

After running our app, upon clicking the button, the phone will ask us to log in, in case we haven't so far.

Not logged in screen

In order to use Sign in with Apple, you need to have 2FA enabled on your account.

2FA prompt

After a successful login, you can choose if you want to share your real e-mail address, or use Apple's new service that hides it from third-party sites.

Login prompt

Now it's time to write the code that handles the result from Apple's sever. Upon completing the registration, we can handle the data in our ASAuthorizationControllerDelegate delegate.

extension ViewController: ASAuthorizationControllerDelegate {
  // MARK: - ASAuthorizationControllerDelegate
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
            let userIdentifier = appleIDCredential.user
            let fullName = appleIDCredential.fullName
            let email = appleIDCredential.email
            let realPerson = appleIDCredential.realUserStatus

            print("\nData to save\n")
            print("Identifier: \(userIdentifier)")
            print("Full name: \(fullName)")
            print("Email: \(email)")
            switch(realPerson){
            case .likelyReal:
                print("The user is most likely real.")
            case .unknown, .unsupported:
                print("Not sure if the user is real or not.")
            }
        }
    }

    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        // Handle error.
    }
}

Obviously in a real use, the data we get should be handled in a more sophisticated way, but for this demo, this method is acceptable to showcase the new feature's capabilities.

The result is an ASAuthorizationAppleIDCredential object, which contains the following fields (those that important in order to identify the user) :

var user: String { get }

A String that can identify the logged in user and for that reason, it always has a value.

var fullName: PersonNameComponents? { get }

The PersonNameComponents class has been part of iOS since iOS 9, if you want to read more about it's fields, you can read about it on Apple's website here

Normally, for most accounts, you'd get familyName, givenName and sometimes middleName, but every value is optional, and for some cases, you'll get phoneticRepresentation for example, for Japanese users.

To keep the demo code simple, I just print out the whole object, without any further data handling.

var email: String? { get }

The user's email address. There is no further data whenever it's a hidden address, or the user's own.

var realUserStatus: ASUserDetectionStatus { get }

Apple's help in detecting fraud. While the exact method is unknown (for a reason), Apple promises if the given ASUserDetectionStatus enum has a value of likelyReal (2), then it's very likely a real person who logged in. In other cases, the recommended path is to handle registration how we did before.

Result after logging in

As you can see, after logging in we get all required data, including the hidden email, after using Apple's Hide My Email service.

Since we used the demo code from a simulator, it can't determine if the user was real or not.

Conclusion

Sign in with Apple seems good on paper, but we have yet to see how it can be implemented in real life.
The system seems polished and easy, after all it was made by Apple. But it was only released a few months ago and while this new system seems promising, there are obvious drawbacks as well, like multi-platform compatibility, exiting together with earlier versions of iOS' logins, etc.
The IT ecosystem doesn't only have Apple devices (let alone, devices that run iOS 13+) so it's up to the developers how they will approach this problem. One thing is sure, Apple pushes the technology really hard, so even with a little headache, it's expected that most applications will have this feature, therefore it's good to know the basics of it.

Author: Hina Kormoczi
autsoft.net