【iOS】Sign In with Apple 実装してみた。

## Sign in with Appleの必須化
2019/6/3に更新されたレビューガイドラインに以下の記述がありました。

```Sign in with Apple will be available for beta testing this summer. It will be required as an option for users in apps that support third-party sign-in when it is commercially available later this year```

※ 公式：https://developer.apple.com/news/?id=06032019j

どうやらログイン連携にサードパーティを用いているアプリには、**Sign in with Apple** の実装が必須になるよう…。
これは早めに試してみようということで早速実装してみました！！

## 環境
- Xcode11 以上
- 対応端末iOS13 以上

今回は自社の **HiNative** を使ってお試し実装してみました。
（ちゃっかり宣伝: [WEB](https://hinative.com/ja)・[Apple Store](https://apps.apple.com/app/apple-store/id923920480)）

## 実装
ステップはたったの3つ！結論からいうと超簡単でした。

1. Xcodeの設定
2. Providerを生成してリクエスト
3. Delegateでその後の処理

#### 1. Xcodeの設定
**TARGET** > **Signing & Capabilities** に **Sign in with Apple** を追加します。
<img width="400" alt="スクリーンショット 2019-09-27 0.41.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/4a912b06-dd37-3677-a103-c29bcc8fdb88.png"> <img width="400" alt="スクリーンショット 2019-09-27 0.42.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/8e893452-d07c-502a-c0d2-a25b7f49900f.png">


これでXcodeの設定は完了です。

### 1.2. (ステップには記載なし) 適当にボタン作ってね
ボタンとActionを用意してください。
ボタンのレイアウトは公式から指定があるので、[こちら](https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/)の公式を参考に！

### 2. Providerを生成してリクエスト
```ViewController.swift
import AuthenticationServices

@objc
func authorizationAppleID() {
  if #available(iOS 13.0, *) {
    let appleIDProvider = ASAuthorizationAppleIDProvider()
    let request = appleIDProvider.createRequest()
    request.requestedScopes = [.fullName, .email]

    let authorizationController = ASAuthorizationController(authorizationRequests: [request])
    authorizationController.delegate = self
    authorizationController.performRequests()
  }
}
```
`if #available(iOS 13.0, *)` なので、ボタンの表示非表示も気をつけないといけないですね。

### 3. Delegateでその後の処理
```ViewController.swift
extension ViewController: ASAuthorizationControllerDelegate {
    @available(iOS 13.0, *)
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
            //　取得できる値
            let userIdentifier = appleIDCredential.user
            let fullName = appleIDCredential.fullName
            let email = appleIDCredential.email
        }
    }

    @available(iOS 13.0, *)
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        // エラー処理
    }
}
```
##### 取得できる値について
Sign in with Appleで取得できるApple IDのデータは、初回の認証時のみ取得できます。
そのため2回目以降の認証時に現在(2020/8/25)取得できません。そのデータを使ってユーザー登録する場合とか大変不便ですね。
どうしてもその値を使いたい場合は初回認証時のデータを永続保持しておくしか無さそうです。

##### 補足
`ASAuthorizationAppleIDCredential` は 2 で生成した `ASAuthorizationAppleIDProvider` のリクエストが成功した際に呼ばれます。
今回はこの実装のみですが、他にも **iCloud Keychainのクレデンシャル情報** を用いた実装もあるようです。
（詳しく知りたい方は下記の参考記事を見てみてください！）


### 動かすとこんな画面が出てきます

<img width="200" alt="スクリーンショット 2019-09-27 1.20.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/bad561ad-f118-7f75-25f2-c9b9b82ab3e7.png"> <img width="200" alt="スクリーンショット 2019-09-27 1.20.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/86ca528d-22c8-b923-8e68-75f50f7a512f.png"> <img width="200" alt="スクリーンショット 2019-09-27 1.21.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305854/8b7d7b9f-f106-6ad3-f90a-c47863f1b8f0.png">

FaceIDでログインできるので本当に楽…！！

##### 参考にさせて頂いた記事
[【iOS】対応必須かも？Sign In with Appleまとめ（第一報)](https://qiita.com/shiz/items/5e094910f742c2ad72a4)