LoginSignup
9

More than 3 years have passed since last update.

Sign in with AppleをCordovaアプリで実装してみた際の記録です。

Sign In with Appleとは

  • Apple IDでアカウント作成・ログインができる
  • Touch ID/Face IDで認証できる
  • 登録するメールアドレスをランダムにできる

実装手段は2つ

  • Sign In with Apple JS
  • AuthenticationServices (ネイティブ SDK)

とりあえずJS版をCordovaに埋め込むと・・

CordovaはWebView上で動作するので、Sign In with Apple JSで事足りるのでは?と思い、JS版をCordovaに埋め込んでみました。
とりあえず、UIWebVeiw上で動作させてみたところ、SignInボタンをタップすると、ブラウザに飛びました。
※ちなみに、生のUIWebViewだと無反応なので、そもそもUIWebViewは対応していないようです。

WkWebViewの場合は認証のモーダルが開きました。
ただ、CordovaのWebView内だとredirect先にページ遷移してしまうので、SPAで実装するCordovaアプリだとUX的にはネイティブSDK(AuthenticationServices)の方が良さそうです。
※redirect先がディープリンクならページ遷移せずにハンドリングできるかもしれませんが。

AuthenticationServices

AuthenticationServicesはiOS12から追加された認証サービスのフレームワークです。Sign in with Apple関連のAPIも含まれています。

AuthenticationServicesを使用してログインのリクエストすると、認証モーダルが表示されます(Face ID/Touch ID/パスワードの何れかで認証)
取得できる情報はID Token、認可コード、メールアドレス、ユーザーID、ユーザー名などです。

Cordovaプラグイン化

CordovaアプリにおいてJSからネイティブのSDKにアクセスするには、Cordovaプラグインを作成する必要があります。
そこで、作ってみました。
https://github.com/pscsrv/cordova-plugin-apple-login

以下サンプルコードです。
一通りのパラメーターは渡せるようにしています。(各パラメーターの詳細は、Githubに書いてあるAppleのドキュメントを参照してください)

SignInWithApple.request({
 requestedScopes: [ SignInWithApple.Scope.Email ],
 state: '...',
 nonce: '...',
}).then((credential) => {
 // ...
}).catch(error => {
 console.error(error)
})

認証に成功すると、以下のようなオブジェクトが返ってきます。ほぼネイティブSDKのママです。

{
 "authorizedScopes": [],
 "identityToken": "eyJr.....K9NQ", // ID Token
 "authorizationCode": "c5704....eV6sg", // 認可コード
 "realUserStatus": 1,
 "fullName": { // ユーザー名(最初の1回のみ取得可)
   "namePrefix": null,
   "givenName": "Daisuke",
   "nameSuffix": null,
   "middleName": null,
   "familyName": "Kishino",
   "nickname": null
 },
 "email": "XXX@privaterelay.appleid.com", // メールアドレス(最初の1回のみ取得可)
 "state": null,
 "user": "XXX" // ユーザーID
}

サーバー側

サーバー側はCordova特有のことはないですが、一応解説します。以下のような流れになります。

  • 認可コードサーバー側に送る
    • ID Tokenでも良いが、リプライ攻撃やID Tokenの検証を考えると、認可コードの方が安全
  • Appleのtokenエンドポイントに投げて、ID Tokenを取得
  • ID Tokenの署名や内容を検証して、OKなら会員登録/ログイン

以下フローです。オレンジ枠がAuthenticationServicesの担当箇所です。
スクリーンショット 2019-12-07 23.33.46.png

ID TokenのPayloadは以下のようになっています。

{
 "iss": "https://appleid.apple.com", // 発行者(Apple)
 "aud": "jp.co.pscsrv.baassampleapp", // 発行先(App)
 "exp": 1569548110, // 有効期限(10分)
 "iat": 1569547510, // 発行時間
 "sub": "XXX", // ユーザーID
 "at_hash": "dP9t…OBDPA", // 認可コードのHash
 "email": "XXX@privaterelay.appleid.com", // メールアドレス
 "email_verified": "true", // ↑が検証済みか?
 "is_private_email": "true", // ↑がPrivateか?
 "auth_time": 1569547508, // ユーザー認証の時刻
 "nonce": "XXX" // リプライ攻撃対策用のランダム値
}

注意点

  • メールアドレスは初回だけ取得可能です(ユーザーがRevokeすると、再取得可能)
  • ユーザー名はtokenエンドポイントから返ってこない(AuthenticationServices経由でのみ取得可能)
  • client_secretはJWT(有効期限最大6ヶ月)
  • PrivateメールアドレスはTeam ID単位に作成される
  • ユーザーIDはRevokeされても変わらない。(メアドも変わらな い。過去の記事など見ると変わるという記述もあるが・・)

サンプル

Cordovaプラグインの使用サンプルと、サーバー側実装のサンプルです。

Cordovaプラグインの使用サンプル
https://github.com/kishino/cordova-plugin-apple-login-sample

サーバー側実装
https://gist.github.com/kishino/281f13461e975c819161298d35b6de54

さいごに

実際にサンプルを使った感じ、iPhoneでのログインのUXはとても良いです。
CordovaでもSign in with Appleを実装して、より良いログイン体験を目指したいです!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
9