こんにちは。 コロナウイルス対策で引きこもり属性が高まっているサーバエンジニアyukimuraです。
突然ですが、アプリのソーシャルログインといえば何が思い浮かびますか?
Facebook?
Google?
Apple?
・
・
・
あれ、Appleのサインインボタンってあんまり見たことないな〜と思った方はいないでしょうか?
それもその筈、Appleのソーシャルログインは、2019年6月3日にAppleが発表した新機能なんです。
このAppleによるソーシャルログイン、「Sign In with Apple
」ですが、既にApple以外のソーシャルログインを実装しているIOSアプリは、2020年6月30日までに実装する必要があります。(2020/3/30現在)
※ 改定の可能性があるため、最新の情報はAppleのガイドラインを確認してくださいね。
ですので今後、Sign In with Appleを実装したアプリが増えていくことと思います!
弊社のアプリaudiobook.jp
もただいまSign In with Appleを絶賛実装中です😁
audiobook.jpにはIOSアプリ・androidアプリ・webアプリがありますので、それぞれに実装を行なっています。
私はサーバサイドエンジニアとして認証api・webアプリのサインイン機能の実装に携わっております。
これから実装する方もいらっしゃるのではと思いますので、私が実装時に悩んだ内容を残しておこうと思います!
名前・メールアドレスが取得できず困る
まず、webアプリケーションにsiwaを実装する場合、認証用のURLを用意する必要があります。 (Sign In with Apple JSを利用する場合はパラメータをセットするだけで自動的にURLが生成されますが、利用しない想定です。)
URLに必要なクエリパラメータについては公式ページに記載があります。 https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/incorporating_sign_in_with_apple_into_other_platforms
さて、URLを組み立ててAppleの認証画面で認証すると、認証したユーザの名前とメールアドレスが取得できるはず・・。
ということで以下のようなURLを作成して試してみました。
https://appleid.apple.com/auth/authorize クエリパラメータ client_id = xxx (アプリ毎に異なるid) redirect_uri = xxx response_type = code id_token response_mode = form_post
認証の結果、以下認可codeとIDトークンを取得できました。
code: xxxxxxx id_token:yyyyyy
取得したIDトークンをデコードすると・・(値はサンプルです)
{ "iss": "https://appleid.apple.com", "aud": "xxx", "exp": 1234567890, "iat": 1234567890, "sub": "xxx", "c_hash": "123456", "auth_time": 1234567890, "nonce_supported": true }
email・名前は含まれていませんね。 よくURLを見てみると、scopeを設定していなかったためscopeを指定して再試行します・・
https://appleid.apple.com/auth/authorize クエリパラメータ client_id = xxx (アプリ毎に異なるid) redirect_uri = xxx response_type = code id_token response_mode = form_post scope = email name
しかしレスポンスされるデータ構造には変化がなく、email・名前が取得できません・・!
原因
Appleとの初回認証時にscopeを設定しておく必要がありました。 2回目以降の認証だと、scopeを設定しても効果はありません。
初回認証時にscopeを設定している場合は以下のような結果が取得できます。
code: xxxxxxx id_token:yyyyyy user: { "name":{"firstName":"太郎","lastName":"音羽"}, "email":"otohatarou@example.com" }
userというフィールドが追加され、名前とemailが取得できました!
取得したIDトークンをデコードすると・・(値はサンプルです)
{ "iss": "https://appleid.apple.com", "aud": "xxx", "exp": 1234567890, "iat": 1234567890, "sub": "xxx", "c_hash": "123456", "email": "otohatarou@example.com", "email_verified": "true", "auth_time": 1234567890, "nonce_supported": true }
IDトークンにもemailが含まれています。
なお、Appleで初回認証時にメールの共有・非公開を選択できますが、共有を選択した場合にはemail_verified
がtrue
、非公開を選択した場合にはfalse
になります。
注意点として、このscopeを設定していた場合でも2回目以降の認証の場合user
フィールドは取得できません・・。
2回目以降でもemailはIDトークンに含まれているため、2回目以降で取得可能なのはemailのみとなります。
ユーザが初回認証後操作をキャンセルして再認証した場合、名前は取得できなくなりますので、名前を取得できないことも考慮して実装を行う必要があります。
Facebookのようにユーザ情報を取得するUserInfo Endpointがあれば良いのですが、今のところ残念ながらそのようなapiは用意されていないんですよね・・。
再度初回認証を試したい場合
AppleIDのアカウントページから自分のアプリの紐付け情報を削除すれば、再度初回認証の確認ができます。 https://appleid.apple.com/#!&page=signin
ログイン後、以下手順で紐付け情報を削除できます。
> 「セキュリティ」を選択 > 「Apple IDを使用しているAppとWebサイトの管理… 」を選択 > ご自分のアプリを選択 > 「Apple Idの使用を停止」をクリック
終わりに
ソーシャルログインの実装に慣れている方であればすぐに原因が分かる内容かもしれませんが、認証系の実装は初めてだったため原因が分からず苦労しました・・!
この内容がお役に立てたようでしたら嬉しいです😊