15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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を実装して、より良いログイン体験を目指したいです!

15
9
0

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
  3. You can use dark theme
What you can do with signing up
15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?