(2016/2/21現在)
プログラミング。
人生で初めて、HTMLの基本からプログラミングというものを学び始め、触れてまだ1ヶ月ちょっとなので まっったく!と言っていいほど参考にはならないと思います。
むしろ、ハマってしまった部分について先人の方々の投稿に助けていただきながらアプリケーション作成をしています。ですのでそこを、是非プログラミングの先輩方からアドバイスをご教授頂ないかな...って思ってます。
では、本題へ。
今回の目的
devise,omniauth-facebook,dotenvでfacebook認証の実装
自分でもメールアドレス、パスワードなどの情報で登録できる機能は実装できるようになったものの、validationのemail正規表現だったり、本物のemailか見極める設定だったりはまだ自分には無理だったので、deviseを使ったユーザー登録機能実装を決断。
また、それに加えてFacebookでもログインできるように機能追加をする。
開発環境(ローカル開発中)と使うGem
- Cloud9
- Rails 4.2.5
- Devise(現時点最新ver.)
- omniauth-facebook (3.0.0)
- Dotenv-rails
前提
gem 'devise'
を使って、parameterで取得したメールアドレスに確認フォームを送信し、メール内容に貼られたurlを押すことでユーザ登録完了するオリジナルログイン機能は実装済み。
アプリケーションの枠組みやデザインもある程度できている。
自分のためにも軽くおさらいしながら現状の説明をして、ハマっている部分の解決方法をご教授していただければと思っています。
ですので、特に必要のない方は「問題はここから!」へ飛ばしてください。
参考にさせていただいたサイト
1 2 3
などなど、大変参考になりました。
メールが送られてこない。等は上記参考サイトを参考にして解決しました。ユーザネームとメールアドレスのどちらからでもログインできるようにしたいのですが、上手くいかずまだ解決出来ないのでとりあえず後回しです。。
一応、他にも僕みたいにプログラミングがド初心者の方がお勉強&ネット上で疲れ果てているかもしれないので、過程も載せます。
メールとパスワードの2つ + :confirmableを使用してユーザ認証を実装する時の内容
必要なところをコメントアウト
config.mailer_sender = '任意のメールアカウント@gmail.com'`
config.authentication_keys = [:email]
#(↑defaultでは確かコメントアウト'#'されてた?のをインさせた記憶が。)
config.reconfirmable = false
#(↑これはtrueだったりfalseだったりサイトごとで違ってあ良くわからないけど、
(初心者なもので、すいません)現状これで動いている。)
以下をコメントアウト&少し編集
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.default_url_options = { :host => "https://ホストurl" }
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => 'https://xxxxxxxxxxxx',
:user_name => ENV["GMAIL_ADDRESS"],
:password => ENV["GMAIL_PASSWORD"],
:authentication => :plain,
:enable_starttls_auto => true
}
ここでは大切な情報を gem 'Dotenv-rails'
を使って ENV['GMAIL_ADDRESS']
と ENV['GMAIL_PASSWORD']
という環境変数に入れてある。
また、実際の機密情報はsecret.yml
ではなく、コマンドで'$ rails c ls -a'と叩くと表示される隠しファイルとして.env
をアプリケーションディレクトリ直下に作ってそこに情報を入れる。
*Githubを使っていて、そこにレポジトリの開発編集履歴を記録している場合は、pushした時にファイル(emailやそのpasswordの個人情報や後々のFacebook認証で取得するAPIのidであったりを反映させないように).gitignoreさせた方がいいらしいが、まだやっていない。
- Dotenvについて。以下の、ド初心者でも分かり易かったサイトを参考に
- http://shuzo-kino.hateblo.jp/entry/2014/04/15/225517
- http://tnakamura.hatenablog.com/entry/2014/09/22/dotenv
次に、user.rbでconfirm!を定義する
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :lockable, trckable, ...ect
devise :database_authenticatable, :registerable, :rememberable,
:validatable, :timeoutable, :confirmable←を追加!
# user.rbでdeviseのconfirmableモデルをオーバーライド
# override Devise::Models::Confirmable#confirm!
def confirm!
super
if confirmed?
UserMailer.welcome_email(self).deliver
end
end
end
また、devise標準の見た目をカスタムしたかったので、以下を作成、編集。
< Devise::SessionsController
でクラスを継承すること。
登録やログイン後のアクションを変更したい場合はdef create super end
のようにオーバーライドで処理を追加してやれば良い。
class Users::SessionsController < Devise::SessionsController
def create
super
#新たな処理を与え上書き変更する
end
def destroy
super
end
end
↓ログイン後のページをuserページにしたかったのでオーバーライド
class Users::RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
user_path(current_user)
end
end
と、同時にルーティング
Rails.application.routes.draw do
root to: "static_pages#home"
devise_for :users, controllers: {
sessions: "users/sessions",
registrations: "users/registrations",
}
resources :users, only: [:show] #/views/users/show を作ってlogin後のユーザページを作る
すると、このような _path
が生成 & 一部変更
(users/sessionsやusers/registrationsがそう)される。
そしてそして、実際にviewをカスタマイズするためにrails g devise:views users
で views/users/.../
となるようにusers配下にviewファイルを作成。
ちなみに、rails g devise:views users
をすれば、deviseのviewカスタマイズの為のファイルを自動的に色々と作成してくれます。 入力formやらスタイルやらを1から作らなくていいって、ちょっと...いや、だいぶ嬉しい。
初心者なのにサボってたらプログラミング上達しな...orz
それはさておき、作成されたviewをbootstrapやらで好きなようにカスタマイズして..
※ gem 'devise-bootstrap-views'
を追加してbundle install
require "omniauth-facebook" ←追加
Devise.setup do |config|
・・・
end
ものすごく分かりやすい参考サイト。ありがとうございます!
https://www.tamurasouko.com/?p=929
さあ、rails s -p $PORT -b $IP
(←Cloud9の場合)でサーバーを立ち上げて、実際にユーザー登録をしてみましょう。
メール送信元のhot server?にgmailを使っていて、メールが来ない場合は安全性の低いアプリで”安全性の低いアプリのアクセス”の設定をオンに変更してください。
これで、とりあえず僕は成功しました。:confirmable でハマっている誰かしらに貢献できていればいいですが。。
問題はここからです!!!
タダでご教授いただこう何て甘ったれた事は思っていないので本題に入るここまでに時間かかったわけです!どうぞ、みなさま、何卒お力添えを。
*前置き*
ちなみにここからは説明のために過程も載せていきますが、Facebookに飛ぶところまではできており、その(facebookに飛んだ)時にエラーが図れるのでそのことを頭に入れておいていただければと思います。
エラー内容は一番下に写真を数枚貼っています。
Facebookでログイン
Facebook用のgem 'omniauth-facebook'
ライブラリを追加。
bundle install
rails g migration AddOmniauthToUsers provider:index uid:index
でカラムを追加。
https://developers.facebook.com/
Facebook Developerにログイン(またはアカウント作成)登録して、アプリを作りダッシュボードからApp IDとApp Secretを取得。
devise.rbにAPP_IDやAPI_SECRETを環境変数を使って入れる。
require "omniauth-facebook" ←追加する
Devise.setup do |config|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
# Devise will use the `secret_key_base` on Rails 4+ applications as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
# ここも追加編集
config.omniauth( :facebook,
ENV['FACEBOOK_APP_ID'],
ENV['FACEBOOK_API_SECRET'],
{:scope => 'email'} #email必須にしてるのでこれで合ってる?
)
・・・省略・・・
end
omniauthの認証を適応させるため omniauthable
`などを追加。
devise :database_authenticatable, :registerable, :confirmable,
:omniauthable, :omniauth_providers => [:facebook] ←この行を追加
また、rake routes
でcallbackとauthorizeのurl_pathがそれぞれ生成されていることを確認。
...で、最後にcallbackの設定をしていきます。
コントローラ作成
callback用のコントローラを作成する。
rails g controller devise:users omniauthcallbacks
だったかな。
とにかくファイルの中はこうなってます。 *クラス継承など注意
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
callback_from :facebook
end
private
def callback_from(provider)
provider = provider.to_s
@user = User.find_for_oauth(request.env['omniauth.auth'])
if @user.persisted?
flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize)
sign_in_and_redirect @user, event: :authentication
else
session["devise.#{provider}_data"] = request.env['omniauth.auth']
redirect_to new_user_registration_url
end
end
end
コントローラーで使ったfind_for_oauth
メソッドの処理をを定義する。
※ここでもemailは現段階では必須としているためFacebookでの認証時には取得したuid, provider
に紐付いたダミーのアドレスを作らせる。
# self.find_for_oauthを定義。
# callback後のユーザー登録で、取得した情報を参照しまだuserでない場合はダミーメール作成しユーザー情報を保存。
def self.find_for_oauth(auth)
user = User.where(uid: auth.uid, provider: auth.provider).first
unless user
user = User.create(
uid: auth.uid,
provider: auth.provider,
email: User.dummy_email(auth),
#この下のpasswordの部分ですが他の参考サイトで
「# ==> Configuration for :validatable
# Range for password length.
config.password_length = 8..72」に
合わせたほうがいいというのを読んだので合わせてますが..
password: Devise.friendly_token[8..70]
)
end
user
end
private
# Create dummy email for OAuth
def self.dummy_email(auth)
"#{auth.uid}-#{auth.provider}@example.com"
end
end
で、そしたらcallbackの時に今設定したcallback_controllerが呼ばれるようルーティングを設定。
Rails.application.routes.draw do
devise_for :users, controllers: {
sessions: "users/sessions",
registrations: "users/registrations",
omniauth_callbacks: 'users/omniauth_callbacks' #この行を追加。
・・・
end
で、あとは認証用リンクを設置して実際にログインをしてみる。
user_omniauth_authorize_path(:facebook)
参考URL
http://qiita.com/kami_zh/items/94aec2d94a2b4e9a1d0b
http://totutotu.hatenablog.com/entry/2015/10/06/Devise%E3%81%A7Facebook%E3%81%AEAOuth%E8%AA%8D%E8%A8%BC%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%99%E3%82%8B
※ここからハマります。
Facebook Developersでサイトページを入れたりと設定をしてあるんですが
Facebookに飛んだ時このようなエラーが出てしまいます。
APP_IDやAPI_SECRETはこの前にエラーを解決したので渡せています。
開発環境でも書きましたが、ドメインやアプリケーションのデプロイはしていません。
ローカル開発中です。ですので、ドメインやらサイトURLなどは仮のもので設定しています。
多分その辺が関係あるのだと思いますが。。。
Facebook Developers上での設定内容
サイトURLhttps://クラウド9アカウント名-ワークディレクトリ名-.c9users.io/
app domains: 上記と同じ。
コンタクトEmail: 本物入力済み
Valid OAuth redirect URIs: https://クラウド9アカウント名-ワークディレクトリ名-.c9users.io/users/auth/:action/callback
どうか、参考になるサイトまたは同じエラーになったことのある方で解決方法をご教授頂ければ幸いです。
よろしくお願いいたします。
イージミスや挙動に多大な問題を発生させるような記述ミスがあれば、ご指摘の程よろしくお願いいたします。