はじめに
現在開発している子育て情報サービス『コノタメ』にて、twitterのAPIを利用してログインする機能を実装しました。
手順を忘れないように記録しておきたいと思います。
環境
- Ruby 3.1.2
- Ruby on Rails 7.0.3
- 【gem】 sorcery 0.16.4
- 【gem】 turbo-rails 1.1.1
- omniauth-twitter 1.4.0
※ sorceryは利用しておりますが、sorceryのexternalモジュールは使用していません。
前提
Simple Password Authenticationにて、メールアドレス認証機能は実装済み
手順
1. Twitter APIの登録
Developer Platformで、API申請をします。
これはたくさんの記事がありますので、割愛。
こちらの記事とか、とても参考になります。
注意点は、Callback URIをきちんと入力しておくこと、アクセスレベルを"Essential"ではなく、"Elevated"にしておくこと。
2. Gemのインストール
ここから先は、
こちらの記事をコピペ参考に。
# Gemfile
gem 'omniauth'
gem 'omniauth-twitter'
gem "omniauth-rails_csrf_protection"
gem 'dotenv-rails'
そしてbundle install
。
gem "omniauth-rails_csrf_protection"
を入れるのは、下の記事を読みまして。
3. APIキーの登録
Consumer KeysのAPI Key and Secretを.envファイルに登録します。(.envファイルは.gitignoreに入れておく。)
# .env
TWITTER_KEY = 自分のAPI Key
TWITTER_SECRET = 自分のSecret
今回は、herokuにデプロイしていますので、herokuのSettings > Config VarsにもこちらのKeyやSecretを登録しておきます。
4. Userモデル追記
# migrationファイル
class SorceryCore < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
t.string :email, null: false
t.string :name, null: false
t.string :crypted_password
t.string :salt
t.timestamps null: false
end
end
end
既にこのような形でUserモデルが作成されているので、以下をモデルファイルに追記。
# user.rb
class User < ApplicationRecord
def self.find_or_create_from_auth(auth)
uid = auth[:uid]
name = auth[:info][:name]
if auth[:info][:email].present?
email = auth[:info][:email]
else
email = uid + '(好きなようにダミーを作る)' #入力しないとvalidationのため、user登録されないので、適当に作成。
end
self.find_or_create_by(email: email) do |user|
user.name = name
user.email = email
user.password = (好きなように式などでダミーを作る) #入力しないとvalidationのため、user登録されないので、適当に作成。
user.password_confirmation = user.password
end
end
end
5. Sessionコントローラー作成
# app/controllers/session_controller.rb
class SessionsController < ApplicationController
skip_before_action :require_login
def create
@user = User.find_or_create_from_auth(request.env['omniauth.auth'])
reset_session
auto_login(@user)
redirect_to root_path, notice: 'ログインしました'
end
def failure
redirect_to root_url, notice: 'ログインに失敗しました'
end
end
application_controller.rbに、before_action :require_login
を設定しているので、skip_before_action :require_login
を入れておかないと、ログインボタンを押しても、「ログインしてください」とだけメッセージがでてきて、一向にログインできません。
auto_login(user)
はsorceryのメソッドです。
# config/routes.rb
Rails.application.routes.draw do
get '/auth/:provider/callback', to: 'sessions#create'
get '/auth/failure', to: 'sessions#failure'
end
ログアウトはsorceryで実装済みですので、今回は省いております。
6. ログインリンク作成
<%= button_to '/auth/twitter', method: :post, data: { turbo: false } do %><%= image_tag "/assets/sign-in-with-twitter-gray.png.twimg.1920.png" %><% end %>
実はここが一番苦労したところです。
ボタンを押しても押しても、画面遷移しないわけです。
何日も悩んでいたところに出会った記事が、こちら!!
ふむふむ、、、rails7では、link_to
のときに、method: :post
が効かないことは知っていたので、button_to
を使ってはいました。
しかし、さらに、data: { turbo: false }
が必要だったようです!!
turbo-railsを利用されている方はご注意ください。
おわりに
最初、sorceryのexternalモジュールを試してみたのですが、そうしたらAuthenticationデータがログインごとに作成されて困ってしまい、結局諦めることになりました。続いて、今回のomniauthを使うことにしたのですが、401エラーが出たり、302で終了したりして、何日も悩み、諦めかけていたのですが、たくさんの記事に救われ、今回ログイン機能を実装することができました!
この記事がどなたかのお役に立てればうれしいです。
また、何かご指摘がございましたら、コメントいただけるとうれしいです。