
Face IDでログイン!Sign in with AppleをiOSアプリに組み込む
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
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) では、引数の ASAuthorization の credential にIdentity Tokenなどのデータが渡されます。
以下の情報が取得できます。
| メンバー | 説明 | 
|---|---|
user | 
一意なユーザーID | 
state | 
状態 | 
authorizedScopes | 
認証されたScope | 
authorizationCode | 
認証コード | 
identityToken | 
Identity Token (JWT形式) | 
email | 
メールアドレス | 
fullName | 
フルネーム | 
realUserStatus | 
ユーザーのステータス | 
サンプルコードでは identityToken と accessToken を取得しています。
以上で実装完了です!
試してみよう
実機で試してみましょう。起動するとログインボタンが表示されます。
ログインボタンをタップすると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を検証する方法はまた別途ご紹介したいと思います。























