新規登録やログインをgoogleやgithubのアカウントでできるようにする
OmniAuthとは
OmniAuthは、OAuth認証をシンプルに扱うためのRubyライブラリで、RailsアプリケーションにSNSログイン機能を実装する際に広く利用されています。OmniAuthを使うと、GitHub、Google、Facebookなど、さまざまなプロバイダーを通じての認証が容易になります。
OAuth認証とは
OAuth認証(OAuth 2.0)は、ユーザーが自分のパスワードを第三者に渡さずに、他のサービスにアクセス許可を与えるための認証プロトコルです。OAuthは、特にWebアプリケーションやモバイルアプリケーションにおいて、ユーザーが他のアプリケーションやサービスと安全にデータを共有できるようにするために使われます。
①googleのOAuthアプリケーションを作成する
googleのAPIを作成するにはGoogle Cloud Consoleにアクセスし、OAuthアプリケーションを作成します.
作成のやり方は下の記事を参考にしてください.
OAuthアプリケーションが作成できたら,クライアントIDとクライアントシークレットをメモしておく.
②githubのOAuthアプリケーションを作成する.
GitHub Developer Settingsにアクセスし,OAuthアプリケーションを作成します.
-
New OAuth App
をクリックして新しいアプリケーションを作成する. -
Application name
には好きなアプリ名を入れる. -
Homepage URL
にはホームページのURLを入れる.
例 {
開発環境: http://localhost:3000
本番環境: https://your-app-name.herokuapp.com
}
4. Application description
にはアプリの説明を入力する.
5.Authorization callback URL
はコールバックURLといい,github側で認証が完了したあと,アプリ側に行くとき使われるurlということである.(これはGETリクエストで処理される(ここ重要))
(例)http://localhost:3000/auth/github/callback
6.Enable Device Flow
はチェックしなくていい
これでOAuthアプリケーションを作ることができた.
7.Client secrets
を発行する.
そのあとClient IDとClient secretsメモしておく.
③ENVにAPIキーを書き込む
envというファイルをつくる.
GOOGLE_CLIENT_ID=googleのクライアント ID
GOOGLE_CLIENT_SECRET=googleのクライアント シークレット
GITHUB_CLIENT_ID=githubのClient ID
GITHUB_CLIENT_SECRET=githubのClient secret
env
はgithubにあげないようにする.
④認証に必要なパッケージをインストールする.
gem 'omniauth'
gem 'omniauth-google-oauth2'
gem 'omniauth-github'
gem 'omniauth-rails_csrf_protection'
gem 'omniauth-rails_csrf_protection'
これはCSRF(クロスサイトリクエストフォージェリ)対策を強化するための Gemです.(なくてもいい)
⑤Userモデルにproviderとuidのカラムを追加する
Userモデルにprovider
とuid
のカラムを追加する.
rails generate migration AddProviderAndUidToUsers provider:string uid:string
rails db:migrate
provider
にはGoogleやGitHubのどのサービスを使って認証されたかを保存しておくカラムである.
uid
はGoogleやGitHubで認証された際、それぞれのサービスがユーザーを一意に識別するためのIDを保存するカラムである.
⑥omniauth.rbにOmniAuthの設定を記述する
config/initializers/omniauth.rb
のファイルにOmniAuthを利用した認証プロバイダ(GoogleやGitHub)の設定を行う.
まずOmniAuthはPOSTリクエストしか受け付けないため,GETリクエストも受け付けるように設定する.
そしてGETリクエストのときは警告がでるため出ないように設定する.
OmniAuth.config.allowed_request_methods = [:post, :get] #getリクエストもできるようにする
OmniAuth.config.silence_get_warning = true #getリクエストの時の警告をなくす
Rails.application.config.middleware.use OmniAuth::Builder do
provider :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], {
scope: 'email,profile', #OAuthのemailやアイコンのアクセスが求められる
prompt: 'select_account', #アカウントを選択する
image_aspect_ratio: 'square', #Googleアカウントのプロフィール画像の比率を「正方形」に設定する
image_size: 50, #Googleのプロフィール画像のサイズを50ピクセルに設定する
access_type: 'offline' #リフレッシュトークンを取得する
}
provider :github, ENV['GITHUB_CLIENT_ID'], ENV['GITHUB_CLIENT_SECRET'], {
scope: 'user:email' #OAuthのemailのアクセスが求められる
}
end
⑥sessions_controller.rbで認証の処理を書く.
sessions_controller.rb
には,認証を受け付けて,認証してきたユーザーがデータベースに存在しなかったらそのユーザーを新規登録して,データベースに存在したらログインさせる処理を書く.
(しかし,この処理はUserモデル(user.rb)に書いているのでそのメソットであるfrom_omniauth
を使うだけ)
class SessionsController < ApplicationController
def create
auth = request.env["omniauth.auth"] #OmniAuthによって取得された認証情報が格納されたオブジェクトである.
user = User.from_omniauth(auth) #from_omniauthメソットに取得したauthを入れる
if user.persisted? #そのユーザーがもし存在するならsessionにuser.idを入れる
session[:user_id] = user.id
flash[:notice] = "ログインしました"
redirect_to items_path
else
flash[:alert] = "ログインに失敗しました: #{user.errors.full_messages.join(", ")}"
redirect_to login_path
end
end
end
userモデルに処理を書く.パスワードにはランダムに生成された値を入れる.
(パスワードがないと登録できないため)
def self.from_omniauth(auth)
user = find_or_initialize_by(provider: auth.provider, uid: auth.uid) #providerとuidからユーザーを検索して存在すればそのデータを取得して,存在しなければ初期化してuserに代入する.
if user.new_record? #ユーザーが存在しないならば,trueを返す.
existing_user = find_by(email: auth.info.email) #emailが同じアカウントがないか調べる
if existing_user #同じアカウントがあったら
user = existing_user
user.update(provider: auth.provider, uid: auth.uid)
else
user.email = auth.info.email
user.name = auth.info.name
user.password = SecureRandom.hex(10)
user.save
end
end
user
end
⑦session_store.rbにセッションの処理を書く.
if Rails.env.production?
Rails.application.config.session_store :cookie_store, key: '_my_session', expire_after: 1.weeks, domain: 'mydomain.com'
else
Rails.application.config.session_store :cookie_store, key: '_my_session', domain: 'localhost'
end
⑧URLを設定する
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
⑨アクセスできるようにする
<%= link_to "Login with Google", "/auth/google_oauth2", method: :post %>
<%= link_to "Login with GitHub", "/auth/github", method: :post %>