人生100年!生涯エンジニア人生!

楽しいエンジニア人生!

#GWアドベントカレンダー 「1つサービスを作る」の1日目記事 ツイッターログイン作成

以下の GWアドベントカレンダー 「1つサービスを作る」の1日目記事です。

gw-advent.9wick.com

まずはツイッターログインまで作ります。

Rubyを使う

Rubyのバージョンを選んでインストールする。
※2.7以上は色々有るので、2.6系の最新版2.6.6 にする。

  1. 一応rbenvをアップデートする。
  2. インストールできるバージョンの確認をする
  3. 2.6.6をインストールする。
  4. 2.6.6 に設定する。
  5. バージョンを確認する。
brew upgrade rbenv
rbenv install -list
rbenv install 2.6.6
rbenv global 2.6.6
$ ruby -v

ruby 2.6.6p146 (2020-03-31 revision 67876)

railsを選ぶ

gem をアップデートする。

gem update --system
gem -v

今のところ最新版は 3.1.2 のようです。

次にRailsのバージョンを選んでインストールする。
インストール可能なrailsを確認する。

gem list ^rails$ -r -a

今のところ最新版は 6.0.2.2 のようです。
rails (6.0.2.2, 6.0.2.1, 6.0.2, 6.0.1, 6.0.0, 5.2.4.2,

gem install rails -v 6.0.2.2
rails -v

最新版 Rails 6.0.2.2 が入りました。

rails起動まで

新規にプロジェクトを作り、とりあえず起動するまでやる。

rails new profile_card
cd profile_card
rails db:migrate
rails server

起動した。

=> Booting Puma
=> Rails 6.0.2.2 application starting in development
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.3 (ruby 2.6.6-p146), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://[::1]:3000
* Listening on tcp://127.0.0.1:3000
Use Ctrl-C to stop

ツイッターログインする

Twitter Developerは登録済みです。

Gemを入れる

Gemfile に以下の1つを追加する。

gem 'devise'

Gemをインストールする。

bundle install

devise関連の設定をする

rails generate devise:install

だらだらとメッセージが出てきます。

Running via Spring preloader in process 3607
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

とりあえず無視します。(雑やな・・・)
先にユーザーモデルを作ってしまいます。

rails generate devise user
rake db:migrate
rails server

以下にアクセスする。
http://localhost:3000/users/sign_up

ログイン画面が出ました。

f:id:hideaki_kawahara:20200429160047p:plain

omniauth-twitterなどの追加

Gemfile に以下を追加する。

gem 'omniauth-twitter'

追加したらGemをインストールする。

bundle install

userモデルの変更

次にuserモデルに、OmniAuthで必要なuidとproviderを追加します。

rails generate migration AddColumnsToUsers uid:string provider:string
rake db:migrate

devise.rbの変更

config.omniauth のところにツイッターログインの情報を書き込みます。
'API KEY'と 'API SECRET'はTwitter Developerの情報を書き入れます。

config/initializers/devise.rb

  config.omniauth :twitter, 'API KEY', 'API SECRET', callback_url: "http://127.0.0.1:3000/users/auth/twitter/callback"

userモデルの変更

Userモデルの対応はstackoverflowを参考に対応する。
stackoverflow.com

app/models/user.rb

devce に , :omniauthable を追加して、first_or_create でユーザーが存在するときにユーザーを返して、そうでないときはユーザー作成するようにします。

  def self.from_omniauth(auth)
    where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
      user.provider = auth.provider
      user.uid = auth.uid
      user.email = User.dummy_email(auth)
      user.password = Devise.friendly_token[0, 20]
    end
  end

  private

  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end

routesの設定

devise_for にコールバック先を教える記述をします。
config/routes.rb を編集します。

  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }

コールバックの作成

mkdir -p app/controllers/users/ディレクトリを作成してから、 app/controllers/users/omniauth_callbacks_controller.rb を編集します。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def twitter
    @user = User.from_omniauth(request.env["omniauth.auth"])

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication #this will throw if @user is not activated
      set_flash_message(:notice, :success, kind: "Twitter") if is_navigational_format?
    else
      session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

参考 qiita.com

データベースに入るか確認

サーバーを起動します。

rails server

以下にアクセスする。
http://localhost:3000/users/sign_up

Sign in with Twitterのリンクをクリックするとツイッター認証後、home画面無いというエラーで終わりますが、認証はできています。
データベースに情報が入っているか確認します。

sqlite3 db/development.sqlite3
select * from users;

データーが入りました。
f:id:hideaki_kawahara:20200430004921p:plain

omniauthの脆弱性対応

Gemfile に以下を追加する。

gem 'omniauth-rails_csrf_protection'

追加したらGemをインストールする。

bundle install

Viewを編集できるようする。

rails generate devise:views users

config/initializers/devise.rb

# config.scoped_views = falseconfig.scoped_views = trueに変更する。

vim app/views/users/shared/_links.html.erb <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider) %><br /><%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %><br />に変更する。

次の記事はこちらです。
kawahara-ci.hatenablog.com