【Swift】Sign in with Appleの実装方法!Apple IDを使ったログイン機能

この記事からわかること

  • Sign in with Appleとは?
  • Apple IDを使ったログイン認証機能の実装方法
  • AuthenticationServicesフレームワーク使い方
  • インターフェースStoryboardで構築している場合の実装方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

iOSやAndroidなどさまざまなアプリにApple IDを使用してログインできる「Sign in with Apple」とはどのようなものなのか、またSwiftでの実装方法をまとめていきます。

Sign in with Appleとは?

参考文献:Apple:Sign in with Apple

Sign in with AppleとはAppleが公式に提供しているログイン認証機能のことです。自分のApple IDを使用してWebサイトやモバイルアプリにサインインするための機能を提供してくれます。

Apple IDをそのまま使用できることにより指紋認証(Touch ID)や顔認証(Face ID)などを使った認証が行えたり、Apple IDに紐づいているメールアドレスをアプリに対して非公開に設定することができるようになっています。

アプリにログイン機能を組み込むなら必須

アプリに対してサードパーティ製(外部サービス)のログイン機能やSNSサービス(GoogleやTwitterなど)を使用する場合はApple IDでのサインインを実装することが必須であるとガイドラインに明記されるようになりました。

”4.8 Sign in with Apple
Apps that use a third-party or social login service (such as Facebook Login, Google Sign-In, Sign in with Twitter, Sign In with LinkedIn, Login with Amazon, or WeChat Login) to set up or authenticate the user’s primary account with the app must also offer Sign in with Apple as an equivalent option. A user’s primary account is the account they establish with your app for the purposes of identifying themselves, signing in, and accessing your features and associated services.”

引用文献:Apple GuideLine:4.8 Sign in with Apple

私も知らずにGoogleアカウントのログインのみを実装したアプリを申請を出したところ以下のような内容でリジェクトされてしまいました。

”Guideline 4.8 - Design - Sign in with Apple

Your app uses a third-party login service, but does not offer Sign in with Apple. Apps that use a third-party login service for account authentication need to offer Sign in with Apple to users as an equivalent option.

Next Steps

Please revise your app to offer Sign in with Apple as an equivalent option for account authentication.”

Swiftでログインボタンを実装する方法

ここからはインターフェースをStoryboardで構築している場合の実装方法を解説していきます。

  1. Developer siteでSign in with Appleを有効にする
  2. Xcode側でSign in with Appleを追加
  3. AuthenticationServicesフレームワークを使って実装

Developer siteでSign in with Appleを有効にする

まずは「Apple Developer site」にアクセスして使用したいApp IDでSign in with Appleを有効にして作成しておきます。既に生成済みであれば「Certificates, IDs & Profiles」から対象のApp IDを編集していきます。

Apple Developerホーム画面

有効にするにはチェックを入れるだけです。

【Swift/Firebase】AuthenticationでApple ID(Sign in with Apple)でログインを実装する方法

Xcode側でSign in with Appleを追加

続いてXcode側で「Signing & Capability」タブの 「 + 」ボタンをクリックして「Sign in with Apple」を追加します。

【Swift/Firebase】AuthenticationでApple ID(Sign in with Apple)でログインを実装する方法

これでXcode側の作業も完了です。

AuthenticationServicesフレームワーク

Sign in with Appleの実装はAuthenticationServicesフレームワークとして提供されています。Xcodeの中にはすでに組み込まれているのでimport文を記述することで使用することができます。

import AuthenticationServices

UIKit(Storyboard)での実装方法

実装手順は公式の方法に倣いつつ、すぐにテストできるようにところどころ改変しながら記述していきます。

参考文献:Implementing User Authentication with Sign in with Apple

  1. ASAuthorizationAppleIDButtonクラスでボタンを実装
  2. ASAuthorizationAppleIDProviderクラスで承認リクエストの構築
  3. ログイン承認状態の識別

Sign in with AppleではログインボタンのUIがあらかじめ用意されています。見た目を変更することも可能ですが他のアプリと共通の見た目になるのでそのまま使うことが推奨されています。

【Swift】Sign in with Appleの実装方法!Apple IDを使ったログイン機能

ASAuthorizationAppleIDButtonクラスでボタンを実装

ボタンを実装するためにStoryboardにビューを追加しておきます。ここで追加するのはUIButtonではなくUIViewです。

import UIKit
import AuthenticationServices

final class AuthViewController: UIViewController {
    
    @IBOutlet  private weak var buttonView: UIView!
}

追加したUIViewをViewControllerクラスのプロパティに紐付けておきます。続いてコードを記述していきます。

基礎となるボタンビューはASAuthorizationAppleIDButtonクラスとして定義されています。インスタンス化してメソッドを紐づけるのは通常のボタン(UIButton)と同じ流れです。

// SetUp
func setupProviderLoginView() {
  // ボタンを定義
    let authorizationButton = ASAuthorizationAppleIDButton()
    //  アクションを定義
    authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
    authorizationButton.bounds = CGRect(x: 100, y: 1000, width: 200, height: 40)
    //  プロパティに紐付け
    buttonView.addSubview(authorizationButton)
}

定義したメソッドをviewDidLoad内で呼び出すようにしておきます。

override func viewDidLoad() {
    super.viewDidLoad()
    setupProviderLoginView()
}

ボタンのデザインを変更する

参考文献:ASAuthorizationAppleIDButton

ASAuthorizationAppleIDButtonクラスではインスタンス化時に用意されたデザイン(スタイルとタイプ)を指定できます。

ASAuthorizationAppleIDButton(authorizationButtonType: .default, authorizationButtonStyle: .white)

ASAuthorizationAppleIDButton.ButtonType

ボタンのタイプはASAuthorizationAppleIDButton.ButtonTypeの値で指定します。

enum ButtonType : Int, @unchecked  Sendable {
    case `continue` // 継続
    static var `default`: ASAuthorizationAppleIDButton.ButtonType // デフォルト
    case signUp // サインアップ
    case signIn // サインイン
}

ASAuthorizationAppleIDButton.Style

ボタンのスタイルはASAuthorizationAppleIDButton.Styleの値で指定します。

 enum Style : Int, @unchecked  Sendable {
    case black // 黒いボタン
    case white // 白いボタン
    case whiteOutline // 白い輪郭のボタン
}

ASAuthorizationAppleIDProviderクラスで承認リクエストの構築

ボタンに紐づけるアクションはAppleに対して承認をリクエストする処理です。ASAuthorizationAppleIDProviderクラスでリクエストを構築しASAuthorizationControllerクラスを使って認証フローを実行します。

@objc  func handleAuthorizationAppleIDButtonPress() {
    let appleIDProvider = ASAuthorizationAppleIDProvider()
    let request = appleIDProvider.createRequest()
    request.requestedScopes = [.fullName, .email]
    
    let authorizationController = ASAuthorizationController(authorizationRequests: [request])
    authorizationController.delegate = self
    authorizationController.presentationContextProvider = self
    authorizationController.performRequests()
}

このアクションメソッドを定義した段階ではエラーが出ますが次のコードを記述して解決できます。

presentationAnchorメソッド

参考文献:ASAuthorizationControllerPresentationContextProvidingプロトコルpresentationAnchorメソッド

認証フローはそのためにViewControllerクラスを拡張して ASAuthorizationControllerPresentationContextProvidingのpresentationAnchorを使ってモーダルでユーザーに提示します。

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

ログイン承認状態の識別

ログイン状態を識別するためにはAuthViewControllerクラスをさらに拡張させASAuthorizationControllerDelegateに準拠させます。用意されているデリゲードメソッドから承認状態やエラーなどを操作することができます。

// MARK: - ASAuthorizationControllerDelegate
extension AuthViewController: ASAuthorizationControllerDelegate {
    
    func authorizationController(controller: ASAuthorizationController,didCompleteWithAuthorization authorization: ASAuthorization ) {
        // ログイン後に実行したい処理
    }
    
    func authorizationController(controller: ASAuthorizationController,didCompleteWithError error: Error) {
       // エラー操作
    }
}

これでApple IDでサインインすることができるようになりました。Xcodeのバージョンが古いから(?)なのかシミュレーターではサインインできずにずっとぐるぐるしていたので実機へビルドするとテストすることができるようになります。

【Swift】Sign in with Appleの実装方法!Apple IDを使ったログイン機能

また最新のXcodeのバージョンに更新した後ならシミュレーターでも正常に動作を確認することができました。

おすすめ記事:エラー:Sign in with Appleで「登録が完了しませんでした」の解決方法!

全体のコード

import UIKit
import AuthenticationServices

final class AuthViewController: UIViewController {
    
    @IBOutlet  private weak var buttonView: UIView!
  
    // SetUp
    func setupProviderLoginView() {
        let authorizationButton = ASAuthorizationAppleIDButton()
        authorizationButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
        authorizationButton.bounds = CGRect(x: 100, y: 1000, width: 200, height: 40)
        buttonView.addSubview(authorizationButton)
    }
    
    // Action
    @objc    func handleAuthorizationAppleIDButtonPress() {
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        let request = appleIDProvider.createRequest()
        request.requestedScopes = [.fullName, .email]
        
        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.presentationContextProvider = self
        authorizationController.performRequests()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupProviderLoginView()
    }
}

// MARK: - ASAuthorizationControllerDelegate
extension AuthViewController: ASAuthorizationControllerDelegate {
    
    func authorizationController(controller: ASAuthorizationController,didCompleteWithAuthorization authorization: ASAuthorization ) {
        // ログイン後に実行したい処理
    }
    
    func authorizationController(controller: ASAuthorizationController,didCompleteWithError error: Error) {
       // エラー操作
    }
}

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

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index