らっちゃいブログ

日々の学びと気づきを発信するブログ

iOS ChromeではFacebook JavaScript SDKによる認証が動作しない

スポンサーリンク

連日の iOS ネタです。

現象

開発中のサービスにて、iOS Chrome でのみFacebookアカウントでの会員登録をしようとすると以下のエラーとなりました。Safari を使えと。

f:id:racchai:20160518105140j:plain:w250

Facebook JavaScript SDKを使ってクライアントサイドで認証しているのですが、FB.login を実行したタイミングで発生するため、使い方がおかしいわけではなさそうです。別な環境では動きますしね。

専用のエラーメッセージがあるくらいなので何か事情があるのでしょう。iOS でブラウザを作るのは制約多そうですしね。グーグルさんホントお疲れ様っす。

回避方法

調べてみたところ、みなさん同じような現象に遭遇していました。

javascript - Facebook OAuth "Unsupported" in Chrome on iOS - Stack Overflow

回避するには、iOS Chrome の場合は自前で window.open して認証画面を開くようにすればよいそうです。ただ、個人的にブラウザ検出って好きじゃないというか、もはややるべきでないと思っているのでそこは不満ではありますが、こうなっては仕方がありません。

ブラウザ検出するために iOS Chrome の User-Agent を以下のサイトで調べてみました。

User Agent Strings - Google Chrome

User-Agent が判明。

Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en) AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60 Mobile/9B206 Safari/7534.48.3

stackoverflow でも言っていたように、CriOS が含まれているかで判定できそうです。

navigator.userAgent.match('CriOS')

次は肝心の window.open ですが、以下のように実行すればよさそうです。

var url = 'https://www.facebook.com/dialog/oauth?client_id=' + appId + '&redirect_uri='+ document.location.href +'&scope=email&response_type=token';
window.open(url, '', null);

というわけで、最終形はこちら。

if (navigator.userAgent.match('CriOS')) {
    var url = 'https://www.facebook.com/dialog/oauth?client_id=' + appId + '&redirect_uri='+ document.location.href +'&scope=email&response_type=token';
    window.open(url, '', null);
} else {
    FB.login(function(response) {
        ....
    });
}

redirect_uri を設定しておくことで、認証が成功したらリダイレクト先でアクセストークンを取得できるようになります。アクセストークンはURL内にハッシュパラメータとして付与されていますので、以下のようにして抽出すればOKです。

window.location.hash.match('access_token=([^&]+)')[1]

アクセストークンさえ取得できてしまえば、あとは通常通りAPIを叩くだけですね。

まとめ

ブラウザ検出はしてしまっていますが、まともな回避方法があってよかったです。

それにしても iOS むずい。