2019年12月17日火曜日

JavaScript で Facebook の OAuth 認証を試してみた

概要

Facebook の OAuth を JavaScript で試してみました
Facebook の JavaScript SDK があるのでそれを使っています

環境

  • macOS 10.15.2
  • Chrome 78.0.3904.108
  • Facebook OAuth API v5.1

Facebook アプリの作成

ここから作成します
まだデベロッパー登録していない場合はページにアクセスしてログインすれば登録しアプリが作成できるようになります

新規アプリを作成しましょう
適当なアプリの名前を設定します

キャプチャが表示されるので入力しましょう

アプリが作成されてダッシュボードに移動します

アプリにプロダクトを追加する

今回は Facebook ログインを使うので Facebook ログインの「設定」を選択します

今回は Web アプリなので「ウェブ」を選択します

あとはアプリを動作させる予定の URL を設定します
localhost だけでテストするのであれば適当な URL を入力すれば OK です
アクセスできない URL でも大丈夫でした

サンプルアプリの作成

今回は Ruby で作成します
HTML + JavaScript だけなのでサーバサイドアプリじゃなくても OK です

  • bundle init
  • vim Gemfile
gem "sinatra"
  • bundle install --path vendor
  • mkdir views
  • vim app.rb
require 'sinatra/base'

class App < Sinatra::Base
  get '/' do
    erb :index
  end
end
  • vim config.ru
require './app'
run App
  • touch views/index.erb

OAuth の実装

JavaScript SDK を使ってログインを実装します
基本は Facebook アプリの設定に出てくるクイックスタートを実装した内容になります

  • vim views/index.erb
<html>
<head>
  <title></title>
</head>
<body>
  <script>
    window.fbAsyncInit = function() {
      FB.init({
        appId      : '2613442028942274',
        cookie     : true,
        xfbml      : true,
        version    : 'v5.0'
      });
      FB.AppEvents.logPageView();   
      FB.getLoginStatus(function(response) {
        console.log(response);
        if (response.status === 'connected') {
          console.log(response.authResponse.accessToken);
        }
      });
    };
    (function(d, s, id){
      var js, fjs = d.getElementsByTagName(s)[0];
      if (d.getElementById(id)) {return;}
      js = d.createElement(s); js.id = id;
      js.src = "https://connect.facebook.net/en_US/sdk.js";
      fjs.parentNode.insertBefore(js, fjs);
    }(document, 'script', 'facebook-jssdk'));
    function checkLoginState() {
      FB.getLoginStatus(function(response) {
        console.log(response);
        if (response.status === 'connected') {
          console.log(response.authResponse.accessToken);
        }
      });
    }
  </script>
  <fb:login-button 
    scope="public_profile,email"
    onlogin="checkLoginState();">
  </fb:login-button>
</body>
</html>

FB.init で Facebook アプリの初期化を行います
作成した Facebook アプリの ID が必要になります
ID はアプリのダッシュボード上部で確認できます
また appId の部分は各自で作成した Facebook アプリの ID に変更してください

その下の function は Facebook JavaScript SDK の動的な読み込みを行っています
ページがロードされたあとで確認するとちゃんと SDK の読み込みやボタンの生成に必要なスタイルのタグが定義されていると思います

ボタンを押したときとページがロードされたときに FB.getLoginStatus が呼ばれます
これはログインの状態を確認する関数です
connected の場合はすでにログインの状態になります
その場合は他の API をコールするためのアクセストークンが取得できます

動作確認

  • bundle exec rackup config.ru

localhost:9292 にアクセスしてみましょう
Facebook のログインボタンが表示されるので押して見ると別ウィンドウが表示され認証画面になることが確認できると思います
今回のサンプルアプリでは認証後に取得できるアクセストークンをコンソールに表示して終了です

ただページを再度読み込むとなぜかログアウトした状態になってしまいます
理由は不明なのですが localhost でテストしているのが原因かもしれないので https 付きの Heroku 上でも動作確認してみました

Heroku で試してみる

本来は https が動作しているサーバ上でホスティングし動作させる必要があります
試しに Heroku にデプロイして試してみました

Heroku Container で動作させています

  • vim Dockerfile
FROM ruby

RUN gem install bundler

ADD . /app
WORKDIR /app

RUN bundle install
CMD bundle exec rackup config.ru -o 0.0.0.0 -p $PORT
  • docker build -t registry.heroku.com/randomgram/web .
  • heroku create -a randomgram
  • heroku container:login
  • docker push registry.heroku.com/randomgram/web
  • heroku container:release web -a randomgram

これで Heroku 上で動作確認するとページをリロードしてもちゃんとログイン状態になっていました
やはり http 上 (もしくは localhost) だとログイン状態は毎回解除されるようです
おそらく開発中のテストなのでそのような挙動になっているのだと思います

Tips

The method FB.getLoginStatus can no longer be called from http pages というエラーがコンソールで表示されますが localhost でテストした場合でも出るようです
localhost でのテストの場合は問題ないですがドメインありのサイトで http の場合は動作しないので注意しましょう

The Login Button plugin no longer works on http pages. Please update your site to use https for Facebook Login. このエラーも同様に http 上での動作だと出るので注意しましょう

最後に

Facebook JavaScript SDK を使って HTML + JavaScript で Facebook の OAuth を試してみました
このあとは取得できたセッショントークンを使って各種 API をコールする感じになります
そのあたりも別途紹介できたらなと思います

また今回は JavaScript ですべて完結しました
トークン情報をサーバサイドで使いたい場合もあるかなと思いますがその場合はトークン情報をサーバサイドに渡す工夫が必要になります

参考サイト

0 件のコメント:

コメントを投稿