くじけそうになったが何とか認証まで成功したのでメモ
結論
いろんなサイトのコードをマネして何度も失敗しましたが、ソースコードが間違っているのではなくcallbackの記述が間違っているかと思われます。
成功した流れとコードをメモしておきます。
※ローカルでもHerokuでも動作確認できました。
callbackにローカルアドレス入れたら出来ました。
環境
Rails 5.2.1
Ruby 2.5.1
heroku
ubuntu16
IntelliJ IDEA
重要:困ったら
API keysを作成と確認
Twitter から Consumer API keys を作成する
- API key
- API secret key
これが無いと作れません。
キーを間違わない様にコピペしておきましょう。
Consumer API keysの方で良いです。
苦戦する Callback URL の確認
Callback URL は色々なところで書かれているが、
APIの仕様が結構変わるらしく最新の記述方法じゃないとエラーで弾かれます。
結局 2018/11/30 時点で成功した方法は
https://ドメイン名 + auth/twitter/callback が正解でした。
Heroku例:https:// ドメイン名.herokuapp.com/auth/twitter/callback
ローカル例:http:// 192.168.xx.yy:3000/auth/twitter/callback
たぶんどこのサイトの例やサンプルコードをマネしてもエラーが出るのはこの記述が違うから弾かれるんだと思います。
アプリ作成:ここからはじまり
$ rails new twitterauthapp -d postgresql
$ cd twitterauthapp
$ bundle
gem の追加
gem 'omniauth'
gem 'omniauth-twitter'
env ファイルを作成
APP_ID = "API key を入れます"
APP_SECRET = "API secret key を入れます"
空ファイルを作成して上記の内容を記載します。
Twitter から Consumer API keys コピペースとします。
env を公開しない設定
/.env
.gitignore へ 上記を追加することでConsumer API keysがアップロードされなくなります。
omniauth.rb を作成
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['APP_ID'], ENV['APP_SECRET']
end
ファイルを新しく手動で作成します。
空ファイル作成してコピペでOK。
user モデルを作成
$ rails g model user provider:string uid:string user_name:string image_url:string
devise を使ってないバージョンです。
既に使っている場合は書き方が違いました。
作成した user モデルに記述
class User < ApplicationRecord
def self.find_or_create_from_auth(auth)
provider = auth[:provider]
uid = auth[:uid]
user_name = auth[:info][:user_name]
image_url = auth[:info][:image]
self.find_or_create_by(provider: provider, uid: uid) do |user|
user.user_name = user_name
user.image_url = image_url
end
end
end
新規登録用のコントローラーを作成
$ rails g controller sessions
class SessionsController < ApplicationController
def create
user = User.find_or_create_from_auth(request.env['omniauth.auth'])
session[:user_id] = user.id
flash[:notice] = "ユーザー認証が完了しました。"
redirect_to root_path
end
def destroy
reset_session
flash[:notice] = "ログアウトしました。"
redirect_to root_path
end
end
ヘルパーメソッドを追加
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user, :logged_in?
private
def current_user
return unless session[:user_id]
@current_user ||= User.find(session[:user_id])
end
def logged_in?
!!session[:user_id]
end
def authenticate
return if logged_in?
redirect_to root_path, alert: "ログインしてください"
end
end
ログイン画面を作成
$ rails g controller home index
とりあえず、ログイン出来るリンクを追加するので作成します。
Twiiterログインリンクを作成
<% if session[:user_id]==nil %>
<%= link_to "Twitterログイン", "/auth/twitter"%>
<% else %>
<%= link_to "Twitterログアウト", "/logout"%>
<% end %>
ログイン用のリンク。
ルーティングを設定する
Rails.application.routes.draw do
get 'home/index'
get '/auth/:provider/callback', to: 'sessions#create'
get '/logout', to: 'sessions#destroy'
root 'home#index'
end
ログイン用のリンクをTOPにしておきます。
ローカルで画面の確認
$ rails db:create
$ rails db:migrate
TOP画面は問題無く出せました。
ローカル環境でも動作確認できました。
ここでローカルが動作しないのであれば、
ローカル用の Callback URL が適切でないかなと思います。
※rails db:create はしなくても良いと思いますが、自分の環境では何度も書いて消したので
データベースが残ってたか作成されてなかったので作成しました。
Herokuへデプロイ
$ heroku create twitterauthapp
$ git init
$ git add .
$ git commit -am "test auth"
$ git push heroku master
$ heroku run rails db:migrate
$ heroku config:set APP_ID=API key を入れます
$ heroku config:set APP_SECRET=API secret key を入れます
Herokuに API key、API secret key を登録します。
$ heroku config
API key、API secret keyが登録されているか確認できます。
アプリURLを決めてから毎度おなじみコマンドです。
HerokuへAPI key、API secret key とdb:migrateを忘れずに。
認証成功した画面
これでアップした画面のURLをクリックするとTwitter認証画面がでます!