Sign in with apple

Sign in with Apple

2022.07.22

はじめに

ワンタップでサインアップ、サインインができるSign in with Apple。実装してみると情報が少なくて手こずったのでここにまとめておきます。


Sign in with Appleとは

Androidユーザーには馴染みがないかもしれませんが、アプリをインストールした際の新規登録やログインがパスワードなしで簡単にできる機能です。


準備

Sign in with Appleの機能を使うにはApple Developer Programの加入が必要です。年会費1万強で学生としては少し躊躇するお値段でした。


アプリ側の実装

アプリ側ではidentity tokenとauthorization codeを取得するところまでを目標とします。これらを用いたサーバー側の実装を行う際は参考サイトを参照してください。


ユーザー情報を扱うためのstructを定義します。initの引数であるAsAuthorizationAppleIDCredentialが名前とメールアドレスを含むのは新規登録の時のみです。よって2回目以降のログインではinit内のguard文によりこのstructは作られません。

Swift
import AuthenticationServices

struct AppleUser: Codable {
    let userId: String
    let firstName: String
    let lastName: String
    let email: String

    init?(credentials: ASAuthorizationAppleIDCredential) {
        guard let firstName = credentials.fullName?.givenName,
              let lastName = credentials.fullName?.familyName,
              let email = credentials.email
        else { return nil }

        self.userId = credentials.user
        self.firstName = firstName
        self.lastName = lastName
        self.email = email
    }
}

下がSign in with Appleのボタン配置とsign in後の処理です。 先ほども述べた通り、アプリをインストール後初めてサインインする場合にはメールアドレスと名前が取得できますが、2回目以降はそれができません。よって初めての処理を逃した場合に備えてuserDefaults(key-value形式のstorage)にユーザー情報を格納しています。
なお、identity tokenとauthorization codeを使えばメールアドレスを取得することができるのでこの処理が必ずしも必要というわけではないです。

Swift
    var body: some View {
        SignInWithAppleButton(.signIn, onRequest: configure, onCompletion: handle)
            .signInWithAppleButtonStyle(colorScheme == .dark ? .white : .black)
            .frame(width: 200, height: 45)
    }

    func configure(_ request: ASAuthorizationAppleIDRequest) {
        request.requestedScopes = [.fullName, .email]
    }

    func handle(_ authResult: Result<ASAuthorization, Error>) {
        switch authResult {
            case .success(let auth):
                switch auth.credential {
                case let appleIdCredentials as ASAuthorizationAppleIDCredential:
                    if let appleUser = AppleUser(credentials: appleIdCredentials),
                        let appleUserData = try? JSONEncoder().encode(appleUser) {
                        UserDefaults.standard.setValue(appleUserData, forKey:appleUser.userId)
                            print("saved apple user", appleUser)
                    } else {
//                   2回目以降の処理 
                    }

                default:
                    print(auth.credential)
                }

            case.failure(let error):
                print(error)
            }
    }
}

参考サイト

Face IDでログイン!Sign in with AppleをiOSアプリに組み込む
Sign in with AppleでのiOSアプリとサーバーとの連携
Sign In with Apple概要 iOSでの実装方法検討
Verifying a user: Apple Developer Documentation