読者です 読者をやめる 読者になる 読者になる

nirasan's tech blog

趣味や仕事の覚え書きです。Linux, Perl, PHP, Ruby, Javascript, Android, Cocos2d-x, Unity などに興味があります。

RailsでOAuthをつかったGoogleアカウント認証を実装

概要

  • RailsでOAuth2.0を使ってGoogleアカウントでログインする仕組みを実装する
  • 後述の参考サイトではgoogle-api-clientとsinatraのサンプルコードがあるのでこれをRailsに移植する

Client ID の作成

プロジェクトの作成と準備

# プロジェクトの作成
rails new oauth-test
cd oauth-test

# 依存パッケージの追加
echo "gem 'google-api-client'" >> Gemfile
bundle install

# 動作確認
rails s

トークン保存用モデルの作成

rails g model TokenPair refresh_token:string access_token:string expires_in:integer issued_at:integer
rake db:migrate
  • app/model/token_pair.rb
class TokenPair < ActiveRecord::Base   
  attr_accessible :access_token, :expires_in, :issued_at, :refresh_token       
         
  def update_token!(object)  
    self.update_attributes(  
      :refresh_token => object.refresh_token,    
      :access_token  => object.access_token,     
      :expires_in    => object.expires_in,       
      :issued_at     => object.issued_at,        
    )    
  end    
         
  def to_hash      
    return {       
      :refresh_token => self.refresh_token,      
      :access_token  => self.access_token,       
      :expires_in    => self.expires_in,         
      :issued_at     => Time.at(self.issued_at)  
    }    
  end    
end
認証コントローラの作成
  • app/controllers/application_controller.rb
class ApplicationController < ActionController::Base       
  protect_from_forgery       
         
  before_filter :oauth2      
         
  require 'google/api_client'
  def oauth2       
    @client = Google::APIClient.new    
    @client.authorization.client_id = 'XXXXXXXXXXXXXXXXXXXXX'
    @client.authorization.client_secret = 'XXXXXXXXXXXXXXXXXXXXX' 
    @client.authorization.scope = 'https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email'        
    @client.authorization.redirect_uri = oauth2callback_url
    @client.authorization.code = params[:code] if params[:code]      
    if session[:token_id]    
      # Load the access token here if it's available       
      token_pair = TokenPair.find(session[:token_id])      
      @client.authorization.update_token!(token_pair.to_hash)        
    end  
    if @client.authorization.refresh_token && @client.authorization.expired?   
      @client.authorization.fetch_access_token!  
    end  
    unless @client.authorization.access_token || request.path_info =~ /^\/oauth2/        
      redirect_to oauth2authorize_url  
    end  
  end    
end
  • app/controllers/auth_controller.rb
class AuthController < ApplicationController     
         
  def oauth2authorize        
    redirect_to @client.authorization.authorization_uri.to_s         
  end    
         
  def oauth2callback         
    @client.authorization.fetch_access_token!    
    # Persist the token here 
    token_pair =   
      if session[:token_id]  
        TokenPair.find(session[:token_id])       
      else         
        TokenPair.new        
      end
    token_pair.update_token!(@client.authorization)        
    session[:token_id] = token_pair.id 
    redirect_to '/'
  end    
         
  def result       
    result = @client.execute(:uri => 'https://www.googleapis.com/oauth2/v1/userinfo')    
    response = result.response.to_s    
    render :json => {:token_id => session[:token_id], :response => response}   
  end    
end
  • config/routes.rb
  match 'oauth2authorize' => 'auth#oauth2authorize'        
  match 'oauth2callback'  => 'auth#oauth2callback'         
  root :to => 'auth#result'   

動作確認