Deviseなしで、Twitterログインを実装する(OAuth認証)
現在作成しているアプリケーションにdeviseなしでtwitteログインを実装したので、アウトプットします。
OAuth認証という認証により、twitter,facebook等のユーザー情報でログインできるよにしま。
OAuth認証については以下の記事が分かりやすかったので、一度読んでみてください。
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be
ruby 2.5.7
rails 5.2.3
やること
・twitterAPIを取得する。
・gemのインストール
・ルーティングの設定、APIキーの設定、OAuth認証の設定
・twitterログインを実装
●twitterAPIを取得する。
twitterAPIの取得は以下の記事を参考させて頂き取得できました。
https://digitalnavi.net/internet/3072/
●gemのインストール
Gemfile
#twitter認証の為のgem
gem 'omniauth' gem 'omniauth-twitter'
#APIキーをGitHubに上げな為に環境変数に入れます。このgemは.envファイルから環境変数をロードする為のgemです。 gem 'dotenv-rails'
※APIキーをGitHub上に上げない方法は以前ブログに書いたので参考にしてみてください。
https://golikyua.hatenablog.com/entry/2019/12/02/135230
$bundle install
ルーティングの設定
routes.rb
Rails.application.routes.draw do ・・・ get 'auth/:provider/callback', to: 'sessions#create' ・・・ end
今回はログイン機能をsessionsコントローラーのcreateアクションで実装したので、上のようにルーティングを設定しました。
環境変数の設定
.env
TWITTER_KEY="取得したAPI key" TWITTER_SECRET="取得したAPI secret key"
これでローカル環境で、APIキーを使用することができますが、本番環境ではまだ使用できません。
自分の場合、アプリケーションをherokuにデプロイしていたので、heroku側でも環境変数を設定します。
コンソールで以下の設定を行います。
$ heroku config:set TWITTER_SECRET="取得したAPI key" $ heroku config:set TWITTER_SECRET="取得したAPI secret key"
以下のコマンドで設定されている環境変数一覧が確認できるので、設定されているか確認してみましょう。
$ heroku config
OAuth認証の設定
config/initializers/omniauth.rbを作成し、以下を記入する。
Rails.application.config.middleware.use OmniAuth::Builder do provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'] end
●twitterログインを実装
userモデルに以下のカラムを追加します。
class AddColumnsToUsers < ActiveRecord::Migration[5.0] def change add_column :users, :uid, :string add_column :users, :provider, :string add_column :users, :image_url, :string end end
$ rails db:migrate
user.rb内に以下のメソッドを追加します。
class User < ApplicationRecord ・・・ def self.find_or_create_form_auth(auth) provider = auth[:provider] uid = auth[:uid] name = auth[:info][:name] image = auth[:info][:image] self.find_or_create_by(provider: provider, uid: uid) do |user| user.name = name user.image_url = image end end end
自分の場合これだけでログインしようとしたら、バリデーションに引っかかってログイン出来なかったので、バリデーションを変更します。
class User < ApplicationRecord validates :name, presence: true, unless: :uid?, length: { maximum: 30 } validates :email, presence: true, unless: :uid?, uniqueness: true, length: { maximum:255 }, format: { with: /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i.freeze } validates :password, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]{8,30}+\z/i }, length: { in: 8..30 }, unless: :uid? has_secure_password validations: false has_one_attached :image, dependent: :destroy has_many :posts, dependent: :destroy has_many :favorites, dependent: :destroy has_many :favorite_posts, through: :favorites, source: 'post' has_many :reviews, dependent: :destroy ・・・ end
自分の場合nameカラム、emailカラム、passwordカラムにunless: :uid?を追加したら、バリデーションに引っかからなくなりました。
もしバリデーションに引っかかってログイン出来ない状態だったら、コメントアウトを使ってどこで引っかかっているか確認してみるといいと思います。
続いてsessionsコントローラーの設定を行います。
app/contorllers/sessions_controller.rb
class SessionsController < ApplicationController ・・・ def create auth = request.env['omniauth.auth'] if auth.present? user = User.find_or_create_form_auth(request.env['omniauth.auth']) session[:user_id] = user.id flash[:success] = "ユーザー認証が完了しました。" redirect_to user else @user = User.find_by(email: params[:session][:email]) if @user && @user.authenticate(params[:session][:password]) log_in @user flash[:success] = "ログインしました" redirect_to @user else flash.now[:danger] = "ログインに失敗しました" render 'new' end end end ・・・ end
ポイントは if文で、twitterログインと通常のログインを分けることです。これをやらないとエラーが発生します。(だいぶ苦労しました。)
最後に、ログインする為のビューを設定します。
app/views/sessions/new.html.erb
<%= link_to "Twitterアカウントでログイン", "/auth/twitter" %>
これで上手く行くと思います。