Face IDでログイン!Sign in with AppleをiOSアプリに組み込む

Sign In with Appleは、Apple IDを認証プロバイダとして利用できる機能です。iOS 13から利用できます。本記事では、Sign In with Appleを使ってIdentity Tokenを取得する実装方法を解説しています。非常に簡単に実装できますのでぜひ試してみてください。
2019.10.16

Sign in with AppleをiOSアプリに組み込もう

Sign in with Appleは、Apple IDを認証プロバイダとして利用できる機能です。iOS 13から利用できます。

つまりこれによって iPhoneユーザーであれば誰もが所有・使用しているであろうApple IDのログイン機能をアプリに組み込める と言うわけです。

またSign in with Appleの提供に伴いApp Store Review Guidelineがアップデートされ、サードパーティのソーシャルログインを実装している場合は対応が必須 となりました。新規のアプリは既に必須化されており、既存のアプリは2020年4月に必須化される予定です。

本記事では、Sign in with Appleを使ってIdentity Tokenを取得する実装方法を解説します。非常に簡単に実装できますのでぜひ試してみてください。

App IDの登録

まずはApple Developerでの作業です。App IDを登録します。既に存在しているAppに対して追加で設定する場合は、登録部分を読み替えてください。

「Certificates, Identifiers & Profiles」の「Identifiers」を開きます。「+」ボタンでApp IDを新規作成します。

設定の「Capabilities」をスクロールすると「Sign In with Apple」がありますので、チェックを付けます。

サンプルプロジェクトの作成

次にサンプルプロジェクトを作成しましょう。テンプレートは「Single View App」を選びます。

「Bundle Identifier」が先ほど登録したApp IDと同一になるように「Product Name」と「Organization Identifier」を設定します。プロジェクト作成後に調整が可能なので、一旦設定して後から調整する形でも問題ありません。

プロジェクトを作成後、プロジェクトの設定の「Signing & Capabilities」タブを開き「+ Capability」をクリックします。

「Sign in with Apple」をダブルクリックで選択します。

「Sign in with Apple」が有効になりました。

次にView ControllerにSign in with Appleを実行するコードを実装します。

まずはコード全体をご覧ください。

import UIKit
// 1. インポート
import AuthenticationServices

class ViewController: UIViewController {

    @IBOutlet weak var stackView: UIStackView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupProviderLoginView()
    }

    // 2. ログインボタンの配置
    func setupProviderLoginView() {
      let authorizationButton = ASAuthorizationAppleIDButton()
      authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
      self.stackView.addArrangedSubview(authorizationButton)
    }
    
    // 3. 認証リクエスト
    @objc
    func handleAuthorizationAppleIDButtonPress() {
        // ASAuthorizationAppleIDRequestの作成
        let request = ASAuthorizationAppleIDProvider().createRequest()
        // Scopeの設定
        request.requestedScopes = [.email, .fullName]
        // ASAuthorizationControllerの作成
        let controller = ASAuthorizationController(authorizationRequests: [request])
        // Delegateの設定
        controller.delegate = self
        controller.presentationContextProvider = self
        // 認証リクエストを実行
        controller.performRequests()
    }

}

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

// 4. ハンドリング
extension ViewController: ASAuthorizationControllerDelegate {
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {

        if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
            guard
                let authCodeData = appleIDCredential.authorizationCode,
                let authCode = String(data: authCodeData, encoding: .utf8),
                let idTokenData = appleIDCredential.identityToken,
                let idToken = String(data: idTokenData, encoding: .utf8),
                let fullName = appleIDCredential.fullName else {
                print("Problem with the authorizationCode")
                return
            }
            print("authorization code : \(authCode)")
            print("identity token : \(idToken)")
            print("full name : \(fullName)")

        }
    }

    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        print("Authorization Failed: \(error)")
    }
}

1. インポート

Sign in with Appleには AuthenticationServicesフレームワーク を使うので、まずはインポートします。

2. ログインボタンの配置

ログインボタンは ASAuthorizationAppleIDButtonクラス を使います。View ControllerにUIStackViewを配置している前提となっているので、あらかじめStoryboardにUIStackView配置するようにしてください。

.touchUpInside イベントを handleAuthorizationAppleIDButtonPress() メソッドでハンドリングしています。

3. 認証リクエスト

handleAuthorizationAppleIDButtonPress() メソッドでは認証のリクエストを行なっています。

認証リクエストは ASAuthorizationAppleIDRequestクラスASAuthorizationControllerクラス を使います。

// ASAuthorizationAppleIDRequestの作成
let request = ASAuthorizationAppleIDProvider().createRequest()
// Scopeの設定
request.requestedScopes = [.email, .fullName]
// ASAuthorizationControllerの作成
let controller = ASAuthorizationController(authorizationRequests: [request])
// Delegateの設定
controller.delegate = self
controller.presentationContextProvider = self
// 認証リクエストを実行
controller.performRequests()

ASAuthorizationAppleIDRequestには requestedScopes に、認証時にどのような個人データを取得するか指定できます。このコードでは .email.fullName を指定してますので、メールアドレスと本名(フルネーム)が取得可能です(現時点ではこの2種類のみ指定可能)。なおユーザー側では認証時に匿名型のメールアドレスを渡すことが設定可能ですので、必ずしも正式なメールアドレスが取得できるわけでは無い点に留意してください。

作成したASAuthorizationAppleIDRequestはASAuthorizationControllerに渡します。

ASAuthorizationControllerには2種類のDelegateを設定します。

メンバー プロトコル 説明
delegate ASAuthorizationControllerDelegate 認証リクエストの結果をハンドリングする
presentationContextProvider ASAuthorizationControllerPresentationContextProviding ASAuthorizationControllerを表示する画面を指定する

最後に performRequests() を呼ぶことで認証画面を表示します。

4. ハンドリング

ASAuthorizationControllerDelegateの authorizationController(:didCompleteWithAuthorization) に成功時の処理を、 authorizationController(:didCompleteWithError) に失敗時の処理を記述します。

authorizationController(:didCompleteWithAuthorization) では、引数の ASAuthorizationcredential にIdentity Tokenなどのデータが渡されます。

以下の情報が取得できます。

メンバー 説明
user 一意なユーザーID
state 状態
authorizedScopes 認証されたScope
authorizationCode 認証コード
identityToken Identity Token (JWT形式)
email メールアドレス
fullName フルネーム
realUserStatus ユーザーのステータス

サンプルコードでは identityTokenaccessToken を取得しています。

以上で実装完了です!

試してみよう

実機で試してみましょう。起動するとログインボタンが表示されます。

ログインボタンをタップするとApple IDを使ったログインが行えます。iPhone X以降ではFace IDで、それ以前ではTouch IDでログインできます。Face IDおよびTouch IDをサポートしていない場合、または設定されていない場合はパスワードでログインできます。

ログインが完了した後にコンソールを見てみると、Identity Tokenなどが取得できていることが確認できます。

Identity Tokenの内容をチェックしてみましょう。JWTを簡単にデコードできる jwt.io を使うと簡単です。

Payloadでは次のような情報が取得できました。

{
  "iss": "https://appleid.apple.com",
  "aud": "jp.classmethod.siwa",
  "exp": 1571152178,
  "iat": 1571151578,
  "sub": "000856.7b04d71ac07a425ab7dfa0972216efd8.1358",
  "c_hash": "7JcWQaa6H4EtW202BB_f-w",
  "email": "fxn4uvrw9g@privaterelay.appleid.com",
  "email_verified": "true",
  "is_private_email": "true",
  "auth_time": 1571151578
}

iOSアプリでの認証を簡単にしよう!

以上、Identity Tokenを取得するところまでご紹介しました。簡単に言うと、ボタンを配置し、Delegateを設定し、リクエストを作成するだけです。いわゆる伝統的な方法で実装できます。

Apple IDを使ったログインは、アプリをダウンロードする際など、iPhoneユーザーにとっては頻繁に行なっている操作です。その操作感でアプリにログイン機能を実装できる「Sign in with Apple」は、ログインについて快適なUXを提供できる非常に重要な機能です。

Identity Tokenを検証する方法はまた別途ご紹介したいと思います。