RailsでTwitterのユーザー情報と連携して認証を行う
はじめに
Ruby on RailsでTwitterのユーザー情報を使用して認証を行う方法についてまとめます。
前回の記事でネタにした自作の練習アプリ「えもったー」で使った方法です。
よくあるアプリごとのユーザー登録・管理機能は用意せず、Twitterのユーザー情報でログイン・ログアウトを行う実装となります。
Twitter登録してないとログインできないし、Twitter登録していれば、何も追加の情報(パスワード等)は無しでログインできる。シンプル。
基本的な処理の流れとしては、gem「omniauth-twitter」でtwitter APIにアクセスして、返ってきたユーザー情報をsession変数に格納するというものです。
・・・omniauth-twitterのドキュメントに従ってるだけといえばそれまでなのですが。
環境
「えもったー」と同じ環境です。
下準備
Twitter APIのアプリケーション登録をする
下記サイト(Twitter Developers)で、Twitter APIを使用したアプリを作るための登録を行います。
画面下部の「Manage my apps」から自分のTwitter IDでログインして、促されるままにCreate New Appすれば問題ないと思います。
API KEYを確認する
登録したら、Keys and Access Tokensタブを開き、API KeyとAPI Secretの値を確認します。
この値が、アプリがTwitter APIを利用する際の認証情報となります。他人にばれないように気をつけないとだめ。
API KEYをアプリに記述する
上記で確認した情報をアプリに記述します。
このような秘密にしたい情報はconfig/secrets.ymlにまとめておくのが習わしらしいです。
というわけで、config/secrets.ymlに以下を書きます。
twitter: &twitter twitter_api_key: <%= ENV["TWITTER_API_KEY"] %> twitter_api_secret: <%= ENV["TWITTER_API_SECRET"] %> development: secret_key_base: (ひみつ) <<: *twitter test: secret_key_base: (ひみつ) <<: *twitter production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> <<: *twitter
ここでは、API KEYとAPI SECRETは環境変数で定義するようにしています。
実際にアプリを動かす際は、環境変数を代入しておくのを忘れないようにしないといけません。
# export TWITTER_API_KEY=(ひみつ) # export TWITTER_API_SECRET=(ひみつ)
OmniAuth設定ファイルの準備
今回はユーザー認証機能としてOmniAuthを利用するので、OmniAuthの設定ファイルを作成し、前述のAPI KEYとSECRETを記述します。
OmniAuthの設定ファイルはconfig/initializers/omniauth.rbです。
Rails.application.config.middleware.use OmniAuth::Builder do provider :twitter,Rails.application.secrets.twitter_api_key,Rails.application.secrets.twitter_api_secret end
作っていく
gemの準備
Gemfileに以下を追記します
gem 'omniauth' gem 'omniauth-twitter'
「はじめに」にも少し書いていますが、omniauth-twitterはTwitter APIを利用したユーザー認証機能を提供してくれるgemです。
(取得したユーザー情報を元に、ツイートしたりフォローしたりといった操作を行いたい場合は、twitterというgemを別途使用するのが良さそう)
認証用のコントローラとルーティングを設定する
まず、大まかな認証の経路としては以下の通りです。
- /auth/twitterへのリクエストが、twitterAPIに飛んでいく
- twitter側で認証に成功したら、Callbackに設定したURLにリクエストが返ってくる
- このリクエストにIDなどのパラメータが含まれている
- CallbackのURLに適切なルーティングを設定し、そのアクションでパラメータを取り出す
今回は、コールバック先はhttp:(railsのルートURL)/auth/twitter/callbackとします。
また、コントローラはsessionsという名前にします。
以下では、そんな感じで色々と作っていきます。
ルーティング
以下の内容をroutes.rbに追記します。
get '/auth/twitter/callback', to: 'sessions#create' get '/logout', to: 'sessions#destroy'
/auth/twitterについてはroutes.rbに書かなくてもomniauth-twitterの機能で自動的にルーティングしてくれる模様です。
そのためコントローラとアクションも書かなくて大丈夫です。
コントローラ作る
# rails generate controller Sessions create destroy
ここまでで試しにブラウザからhttp://(railsのルート)/auth/twitterにアクセスしてみます。
たぶん、tiwtterのアプリ認証画面が表示され、認証するとsessions#callbackのデフォルトのビューが表示されるはずです。
あとはtwitterのユーザー情報をuserモデルやsessionに持たせてあげればオッケーです。
コントローラの中身は後で書くことにして、まずはモデルから作ります。
userモデルを作る
コールバックしてきたリクエストにはtwitterのユーザー情報(twitter idやプロフ画像など)が含まれているので、適宜必要な情報を取り出して、保存したいものはモデルにカラムを用意して保存します。
コールバックで渡されるユーザー情報はrequest.env[‘omniauth.auth’]というハッシュに格納されています。
どんなパラメータがあるかはGithubでomniauth-twitterのREADMEに書かれています。
今回、モデルには以下のカラムを設定することにします。
- provider
- uid
- nickname
- name
- image_url
- description
request.env[‘omniauth.auth’]の中での値もほぼ同名です。image_urlだけimageだけど。
# rails generate model User provider:string uid:string nickname:string name:string image_url:string description:string # rails db:migrate
セッションとモデルに情報を保管する
以下のリンク先を参考にさせて頂きました。
Userモデル
モデル側には、コントローラが受け取ったrequest.env[‘omniauth.auth’]から情報を取り出してモデルに保存する処理を用意します。
class User < ApplicationRecord def self.find_or_create_from_auth(auth) provider = auth[:provider] uid = auth[:uid] nickname = auth[:info][:nickname] name = auth[:info][:name] image_url = auth[:info][:image] description = auth[:info][:description] self.find_or_create_by(provider: provider, uid: uid) do |user| user.nickname = nickname user.name = name user.image_url = image_url user.description = description end end
元記事から流用しているself.find_or_create_byでは既存ユーザーか否かの判定にproviderとuidを使っていますが、今回のように「twitter認証だけ使う!」場合はuidだけで充分一意になります(providerの値はtwitterしかありえない)。
そのためproviderというカラム自体不要ということになりますが、将来的な拡張のしやすさなどからカラムに含めておくことにしています。
コントローラ
コールバックのアクションから先ほどのメソッドを呼び出し、sessionに情報を格納してあげるだけです。
class SessionsController < ApplicationController def create user = User.find_or_create_from_auth(request.env['omniauth.auth']) session[:user_id] = user.id redirect_to root_path end def destroy reset_session redirect_to root_path end end
これで準備はおしまいです。
あとはビューで適当なところに/auth/twitterへのリンクを書けば、そのリンクを踏むだけでTwitterで認証が行われ、Twitterのユーザー情報がUserモデルとsessionに取得されるようになります。うれしい。
まとめ
RailsでTwitterの情報を用いたユーザー認証の方法をまとめました。
今回のモデルやコントローラの作りはめちゃくちゃシンプルですが、モデルが独自の情報を格納するようになったとしても、Twitterが絡む部分は変わりません。
TwitterAPIからユーザー情報(request.env[‘omniauth.auth’])を取得する部分が要点だと思います。