RailsでGoogle AppsのOAuthを試す

Google Apps Premier EditionではOAuthが使えます。
Railsで試してみました。

基本的に以下の記事を参考にさせてもらっています。
RailsでTwitterのOAuthを試す | おいぬま日報
この記事のソースに対する修正点しか書いていないので、まずこの記事のサンプルを動かしてください。

これをGoogle Appsで動くように修正しました。
Google Calendarからカレンダー一覧を取得するだけです。

Google Appsドメインの管理画面からConsumer keyを取得します

ドメインの管理画面から「高度なツール(Advanced tools)」をクリックして、以下の画面を表示します。

「Manage OAuth domain key」をクリックします。
※Premier EditionまたはEducation Editionではないとこのメニューは表示されません。

この画面からConsumer keyとConsumer secretを取得します。
「Allow access to all APIs」にチェックを入れると、Consumer secretが取得できた気がします。

app/controllers/index_controller.rbの修正

index_controller.rbを修正します。
コード中のConsumer keyとConsumer sercretとDomain nameを適切に設定します。
Domain nameはGoogle Appsに登録しているドメインです。
Google Appsでは、Consumer keyとDomain nameは同じです。

require 'oauth'
require "rexml/document" 
 
class IndexController < ApplicationController
  def self.consumer
    OAuth::Consumer.new(
       "Consumer key",
       "Consumer secret",
       {
         :site => "https://www.google.com",
         :scheme => :header,
         :http_method => :post,
         :request_token_path => "/accounts/OAuthGetRequestToken",
         :access_token_path  => "/accounts/OAuthGetAccessToken",
         :authorize_path     => "/accounts/OAuthAuthorizeToken"
       }
    )
  end
 
  def index
  end
 
  def oauth
    request_token = IndexController.consumer.get_request_token(
      {:oauth_callback => "http://#{request.host_with_port}/oauth_callback"},
      :scope => "https://www.google.com/calendar/feeds/"
    )
    session[:request_token] = request_token.token
    session[:request_token_secret] = request_token.secret
    
    redirect_to request_token.authorize_url(:hd => 'Domain name')
    return
  end
 
  def oauth_callback
    consumer = IndexController.consumer
    request_token = OAuth::RequestToken.new(
      consumer,
      session[:request_token],
      session[:request_token_secret]
    )

    access_token = request_token.get_access_token(
      {},
      :oauth_token => params[:oauth_token],
      :oauth_verifier => params[:oauth_verifier]
    )
 
    response = consumer.request(
      :get,
      'https://www.google.com/calendar/feeds/default/allcalendars/full',
      access_token, { :scheme => :header }
    )
    case response
    when Net::HTTPSuccess
      @calendar_info = get_calendar_info(response.body)
    when Net::HTTPRedirection
      response = consumer.request(
        :get,
        response['Location'],
        access_token, { :scheme => :header }
      )
      @calendar_info = get_calendar_info(response.body)
    else
      RAILS_DEFAULT_LOGGER.error "Failed to get user info via OAuth"
      flash[:notice] = "Authentication failed"
      redirect_to :action => :index
      return
    end
  end
  
  private
  def get_calendar_info(xml)
    doc = REXML::Document.new xml
    doc.elements.to_a('//entry/title')
  end
end

app/views/index/oauth_callback.html.erbを修正

Twitterとはレスポンスが異なるので、修正します。

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>GoogleからOAuthで認証完了</title>
</head>
<body>
<h3>カレンダー一覧</h3>
<ul>
<%
  @calendar_info.each{|cal|
%>
    <li><%=cal.text%></li>
<%
  }
%>
</ul>
</body>
</html>

修正ポイント

    request_token = IndexController.consumer.get_request_token(
      {:oauth_callback => "http://#{request.host_with_port}/oauth_callback"},
      :scope => "https://www.google.com/calendar/feeds/"
    )

で、scopeを指定します。どのAPIを使うかを明示する必要があります。

redirect_to request_token.authorize_url(:hd => 'Domain name')

ドメイン名を指定します。これをしないと、Google Appsのログイン画面ではなく、普通のGoogleのログイン画面に飛んでしまいます。

    when Net::HTTPRedirection
      response = consumer.request(
        :get,
        response['Location'],
        access_token, { :scheme => :header }
      )
      @calendar_info = get_calendar_info(response.body)

最初のアクセスでは302が返ってきたので、もう一回リクエストを投げてあげる必要があります。この際も認証情報を渡す必要があるので、OAuthのライブラリでリクエストを投げます。

動かしてみる

ruby script\server

で起動して、http://localhost:3000/にアクセスしてみます。


「OAuthで認証」をクリック

そのドメインGoogle Appsへのログイン画面が表示されますので、ログインします。

Calendarへのアクセスの許可を求める画面が表示されます。「許可」をクリックします。

カレンダー一覧が表示されました。