Sinatraでつくる、FacebookのOAuth認証サンプル

Facebook Graph APIの実験の為に、いろいろなサンプルアプリを作ったりしています。

本番用のアプリを作るときはRailsを採用したりするのですが、簡単にAPIを試すだけのサンプルの場合は、Sinatraを使ったほうがサクっと作れて便利ですよね。

そんなときは、Ruby OAuth2 gemとSinatraを使うと、「Facebookアカウントでのログインの仕組み」を簡単に実装することが出来たりします。

今回は、ボクが普段使っているサンプルコードを紹介したいと思います。

本当は Rack::Session::Pool を使いたいのですが、shotgunと併用するとうまくセッションが効いてくれなかったりすることもあり、Rack::Session::Cookieで我慢しています。

https://gist.github.com/998545

require 'rubygems'
require 'sinatra'
require 'oauth2'

use Rack::Session::Cookie,
  :expire_after => 86400,
  :secret => "secret" # 文字列を変更すること

APP_ID='1111111111111' # FacebookアプリのアプリケーションID
APP_SECRET='aaaaaaaaaaaaaaaaaa' # Facebookアプリのsecret
REDIRECT_URI='http://[ドメイン名]/callback' # リダイレクト用URIを指定する
SCOPE='offline_access' # 呼び出すAPIに応じて変える 

@@client = OAuth2::Client.new(APP_ID, APP_SECRET,
  {:site => 'https://graph.facebook.com',
   :ssl => {:verify => false},
   :parse_json => true})

get '/' do
  if session[:access_token]
    access_token = OAuth2::AccessToken.new(@@client, session[:access_token])
    @me = access_token.get("/me")
  end
  erb :index
end

get '/login' do
  redirect @@client.web_server.authorize_url(
    :redirect_uri => REDIRECT_URI, :scope => SCOPE)
end

get '/logout' do
  session[:access_token] = nil
  redirect '/'
end

get '/callback' do
  if params[:code]
    access_token = @@client.web_server.get_access_token(
      params[:code], :redirect_uri => REDIRECT_URI)
    session[:access_token] = access_token.token
    redirect '/'
  end
end

helpers do
  # ログアウト状態のときはログインリンク、
  # ログイン状態のときはログアウトリンク
  def link_to_login_or_logout
    if session[:access_token]
      %Q(<a href="/logout">ログアウト</a>)
    else
      %Q(<a href="/login">ログイン</a>)
    end
  end

  # Hashをhtml table形式で出力する
  def to_html_table(hash)
    result = ""
    if hash
      result << "<table>"
      hash.each do |key, value|
        result << "<tr>"
        result << "<th>#{key}</th>"
        result << "<td>"
        if value.is_a?(Hash)
          result << to_html_table(value)
        elsif value.is_a?(Array)
          value.each do |v|
            result << to_html_table(v)
          end
        else
          result << "#{value}"
        end
        result << "</td>"
        result << "</tr>"
      end
      result << "</table>"
    end
    result
  end
end

__END__
__DATA__

@@ index
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<%= link_to_login_or_logout %>
<%= to_html_table(@me) %>
</body>
</html>