この記事は公開されてから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を検証する方法はまた別途ご紹介したいと思います。