Laravel SocialiteのgetEmailでTwitterのメールアドレスが取得できなかったので調べてみた

こんにちは、エンジニアの @akase244 です。

当社で開発・運営している「chirami(Webデザイナー向けのHTMLプレビューツール)」では、Twitter、GitHub、Facebookアカウントを利用しログインができます。 (chiramiの使い方についてはこちらをご覧ください)

f:id:akase244:20170807102032p:plain

おかしい。。。前回書いた記事とまったく同じ導入になっている気がするが。。。気にしない。

chiramiのログイン部分はLaravel Socialiteを利用しています。
以前の記事では、Laravel Socialiteの「getName()」で日本語名が返ってくるカスタマイズについて触れましたが、今回は「getEmail()」についてちょっと調べてみました。

認証後にメールアドレスを取得してみると。。。

繰り返しになりますが、chiramiではTwitter、GitHub、Facebookアカウントを利用しログインができます。
ということで、各SNSプロバイダで認証後に以下のように getEmail() を実行すると、Twitterの場合のみメールアドレスが取得できませんでした。

(現状、chiramiでは新規ログイン時にメールアドレスの取得フローは設けておりませんが、今後利用者の方との連絡手段としてメールアドレスの取得を検討中です)

Facebookの場合

Facebookの開発者向けドキュメント「アクセス許可のリファレンス」を見ると、以下の記述のとおり、メールアドレスを取得するには「email」という権限が必要なことが分かります。

userオブジェクトのemailプロパティを介して、利用者のプライマリメールアドレスにアクセスできるようにします。

また、「ログインレビューとは」のページを見ると、以下のように記載されています。

次の3つの基本的なアクセス許可をリクエストする場合は、レビューは不要です。

public_profile、user_friends、email。

利用者がアプリにログインする際にそれ以外の許可をリクエストする場合は、レビューが必要です。

つまり、メールアドレスを取得する場合、以下のようなOAuthアプリ設定画面で「アイテムを審査に送信」といった特別な操作は不要であることが分かります。

f:id:akase244:20170806134538p:plain:w500

さらに、Laravel SocialiteのFacebookプロバイダに実装を見てみると、スコープとして email が指定されているため、 getEmail() でメールアドレスが取得できそうだということが分かります。

socialite/FacebookProvider.php at v3.0.7 · laravel/socialite · GitHub gist.github.com

GitHubの場合

次にGitHubですが、「About scopes for OAuth Apps」を見ると、「user:email」の権限でメールアドレスが取得できることが分かります。

Name Description
user:email Grants read access to a user’s email addresses.

Laravel SocialiteのGitHubプロバイダもFacebookプロバイダと同じような作りになっており、スコープとして user:email が指定されているため、 getEmail() でメールアドレスが取得できそうだということが分かります。

socialite/GithubProvider.php at v3.0.7 · laravel/socialite · GitHub gist.github.com

Twitterの場合

さて、いよいよTwitterです。
Twitter Developer Documentationの「GET account/verify_credentials」の「Parameters」を見ると、「include_email」というパラメータに「true」を渡すと、メールアドレス取得できることが分かります。

Name Required Description Default Value Example
include_email optional When set to true email will be returned in the user objects as a string. If the user does not have an email address on their account, or if the email address is not verified, null will be returned. true

Laravel SocialiteのTwitterプロバイダは、FacebookやGitHubとは若干プログラムの書き方が異なっていますが、プログラムを追いかけてみると、「oauth1-client/src/Client/Server/Twitter.php」に該当箇所を見つけることができました。

oauth1-client/Twitter.php at 1.7.0 · thephpleague/oauth1-client · GitHub gist.github.com

これを見ると「include_email=true」の指定があるので、プログラム側は特に問題なくメールアドレスが取得できそうです。

しかし、実際にはメールアドレスが取得できません。

Twitterでメールアドレスを取得するための設定

プログラムの問題ではなさそうなのは分かりました。
そこで、先程のリファレンスのページをよく読んでみると、「Request a User’s Email Address」の部分に答えが書いてありました。

The “Request email addresses from users” checkbox is available under the app permissions on apps.twitter.com.

ということらしいです。

早速、書いてあるとおりに「Twitter Application Management」にアクセスしてみましょう。

次に、メールアドレスを取得したいTwitterのOAuthアプリケーションを選択します。

f:id:akase244:20170805212909p:plain:w500

「Permissions」のタブを開きます。

f:id:akase244:20170805213147p:plain:w500

「Additional Permissions」に「Request email addresses from users」というチェックボックスがあるので、これにチェックして、「Update Settings」ボタンをクリックすると設定完了です。

f:id:akase244:20170805213200p:plain:w500

メールアドレス取得のチェックボックスをオンにする場合、「Settings」タブのプライバシーポリシーと利用規約のURL欄が必須入力となるので注意してください。

f:id:akase244:20170805213519p:plain:w500

入力していない場合はこのように怒られてしまいます。

f:id:akase244:20170805213432p:plain:w500

まとめ

前述の設定が完了すると、ようやくメールアドレスが取得できました。

ということで、結局調べてみるとLaravel Socialiteが犯人ではなく、TwitterのOAuthアプリケーションの設定漏れだったということに行き着き、恥ずかしい限りです。

もし私と同じようにTwitterのOAuth認証でメールアドレスが取得できないといった場合は、ぜひ設定見直してみてください。