Face IDでログイン!Sign in with AppleをiOSアプリに組み込む
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を検証する方法はまた別途ご紹介したいと思います。