Tag: Devise/Twitter認証/古い内容
関連ページ†
参考情報†
- Twitterにログインしその情報をユーザーとして利用する。
Userモデルの生成†
- Userモデルを生成する
$ bundle exec rails g devise User
- user.rbを以下のように編集する。参考情報と異なりconfirmableは実装せず画面上で登録が完結できるようにする。
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:lockable, :timeoutable, :omniauthable, omniauth_providers: [:twitter]
end
- マイグレーションファイルの編集
- 以下ようにする。
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
## Twitter認証用
t.string :provider
t.string :uid
t.string :username, default: "anonymous"
t.timestamps
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :unlock_token, unique: true
end
end
- migration実行
bundle exec rake db:migrate
- このままだとエラーになってログインできない。
undefined method omniauth_authorize_path
Twitterアプリケーションの登録†
Twitter認証のための準備†
devise.rbの編集†
- config/initializers/devise.rbを編集
config.omniauth :twitter, "Consumer Key", "Consumer Secret"
- この段階で「Sign in with Twitter」からログインすると一応Twitterのログイン画面が表示される。
- しかしcallbackが設定されていないのでエラーとなる。
The action 'twitter' could not be found for Devise::OmniauthCallbacksController
コールバック用コントローラーの生成†
- Twitterログイン画面から戻ってきたときに呼び出される処理を行うコントローラーを生成。
bundle exec rails g controller omniauth_callbacks
- 内容を編集。親クラスがDevise::OmniauthCallbacksControllerなので注意。
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def twitter
@user = User.from_omniauth(request.env["omniauth.auth"].except("extra"))
if @user.persisted?
flash.notice = "ログインしました!"
sign_in_and_redirect @user
else
session["devise.user_attributes"] = @user.attributes
redirect_to new_user_registration_url
end
end
end
Userモデルの変更†
- from_omniauthとnew_with_sessionを作成する。
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:lockable, :timeoutable, :omniauthable, omniauth_providers: [:twitter]
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.username = auth["info"]["nickname"]
end
end
def self.new_with_session(params, session)
if session["devise.user_attributes"]
new(session["devise.user_attributes"], without_protection: true) do |user|
user.attributes = params
user.valid?
end
else
super
end
end
end
ルートの設定†
処理の流れ†
- 初回登録時Twitterログイン画面から戻りOmniauthCallbacksControllerの下の分岐から「redirect_to new_user_registration_url」が呼ばれ登録画面が表示される。
- Userのnew_with_sessionはページをまたいでTwitterのアカウントの情報(uidやらproviderやら)を保存するために必要となる。
- Twitterの場合Twitterのアカウント情報からメールアドレスを取得できないので、戻ってきてからメールアドレス、パスワードを入力し始めて登録完了となる。
再ログイン時の流れ†
- Rememberableを実装している場合、Cookieから認証情報を構築して自動的にログイン可能となる。
- ただしCookie有効期間が切れるとTwitterサイトを使った再ログインが必要。
Twitter認証の改良†
- 直接TwitterログインリンクをクリックしTwitterのログイン画面に遷移、戻ってきてから登録ボタンを押したら登録完了とする。
- メール、パスワードの入力はなし。
User.from_omniauthの修正†
- オリジナルではUser.from_omniauthのレコード生成を試み、パスワードが空のため実際は保存されないという流れになっている。ダミーパスワードを設定するとそのまま保存されてしまい、Twitterログイン後、確認してから登録という流れに鳴らない。
- whereで検索する処理とnewでダミーユーザーを生成する処理に分ける
- また登録画面でパスワード未入力のエラーが表示されないようpassword_required?を変更しておく。
def self.from_omniauth(auth)
user = where(provider: auth["provider"], uid: auth["uid"]).first
return user if user
user = User.new
user.provider = auth["provider"]
user.uid = auth["uid"]
user.username = auth["info"]["nickname"]
user.email = "#{auth.provider}-#{auth.uid}@example.com"
user.password = Devise.friendly_token[0,20] #これが必要?
user
def password_required?
provider.blank? && super
end
end
ログイン画面の修正†
- registrations/new.html.erbを変更。
- Twitterのログイン画面からもどってきたあと登録しようとしているTwitterユーザー名を確認し、登録ボタンを押すと実際に登録される。
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<%= @user.username %>を登録します。
<div class="actions">
<%= f.submit "Sign up" %>
</div>
<% end %>
<%= render "devise/shared/links" %>