I tried integrating omniauth with Hartl tutorial user signup authentication. I thought about switching the hartl tutorial authentication to Devise and then Devise to omniauth (since their is a Railscast episode for that), but I'm worried the switch from Hartl to Devise will be the most difficult integration out of the options. What do you think?
Currently if I go to http://0.0.0.0:3000/authentications I will be taken to a login page for facebook. Once I click on the link I get logged into facebook. Score! But then I am redirected to the root route with:
where page shows me "Welcome to the Sample App: Sign up now!" as if I am not logged in. I've been confused by this whole process so if you can tell me where I went wrong I'd greatly greatly appreciate it.
class AuthenticationsController < ApplicationController
def index
@authentications = current_user.authentications if current_user
end
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth.except('extra')
redirect_to root_url
end
end
end
def destroy_facebook
@authentication = current_user.authentications.find(params[:id])
@authentication.destroy_facebook
flash[:notice] = "Successfully destroyed authentication."
redirect_to authentications_url
end
protected
# This is necessary since Rails 3.0.4
# See https://github.com/intridea/omniauth/issues/185
# and http://www.arailsdemo.com/posts/44
def handle_unverified_request
true
end
end
<% if @authentications %>
<% unless @authentications.empty? %>
<p><strong>You can sign in to this account using:</strong></p>
<div class="authentications">
<% for authentication in @authentications %>
<div class="authentication">
<%= image_tag "#{authentication.provider}_32.png",
:size => "32x32" %>
<div class="provider"><%= authentication.provider.titleize↵
%></div>
<div class="uid"><%= authentication.uid %></div>
<%= link_to "X", authentication, :confirm =>
'Are you sure you want to remove this authentication
option?', :method => :delete, :class => "remove" %>
</div>
<% end %>
<div class="clear"></div>
</div>
<% end %>
<p><strong>Add another service to sign in with:</strong></p>
<% else %>
<p><strong>Sign in through one of these services:</strong></p>
<% end %>
<a href="/auth/facebook" class="auth_provider">
<%= image_tag "facebook_64.png", :size => "64x64",
:alt => "Facebook" %>Facebook</a>
<div class="clear"></div>
class User < ActiveRecord::Base
has_many :authentications
has_many :habits, dependent: :destroy
has_many :levels
has_many :valuations, dependent: :destroy
has_many :goals, dependent: :destroy
has_many :quantifieds, dependent: :destroy
has_many :results, dependent: :destroy
accepts_nested_attributes_for :quantifieds, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
attr_accessor :remember_token, :activation_token, :reset_token
before_save :downcase_email
before_create :create_activation_digest
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
validates :password, length: { minimum: 6 }, allow_blank: true
def apply_omniauth(omniauth)
authentications.build(:provider => omniauth['provider'], :uid => omniauth['uid'])
end
def password_required?
(authentications.empty? || !password.blank?) && super
end
# Returns the hash digest of the given string.
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Engine.cost
BCrypt::Password.create(string, cost: cost)
end
# Returns a random token.
def User.new_token
SecureRandom.urlsafe_base64
end
# Remembers a user in the database for use in persistent sessions.
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
# Forgets a user. NOT SURE IF I REMOVE
def forget
update_attribute(:remember_digest, nil)
end
# Returns true if the given token matches the digest.
def authenticated?(attribute, token)
digest = send("#{attribute}_digest")
return false if digest.nil?
BCrypt::Password.new(digest).is_password?(token)
end
# Activates an account.
def activate
update_attribute(:activated, true)
update_attribute(:activated_at, Time.zone.now)
end
# Sends activation email.
def send_activation_email
UserMailer.account_activation(self).deliver_now
end
def create_reset_digest
self.reset_token = User.new_token
update_attribute(:reset_digest, User.digest(reset_token))
update_attribute(:reset_sent_at, Time.zone.now)
end
# Sends password reset email.
def send_password_reset_email
UserMailer.password_reset(self).deliver_now
end
# Returns true if a password reset has expired.
def password_reset_expired?
reset_sent_at < 2.hours.ago
end
# Returns a user's status feed.
def feed
following_ids = "SELECT followed_id FROM relationships
WHERE follower_id = :user_id"
Habit.where("user_id IN (#{following_ids})
OR user_id = :user_id", user_id: id)
Valuation.where("user_id IN (#{following_ids})
OR user_id = :user_id", user_id: id)
Goal.where("user_id IN (#{following_ids})
OR user_id = :user_id", user_id: id)
Quantified.where("user_id IN (#{following_ids})
OR user_id = :user_id", user_id: id)
end
# Follows a user.
def follow(other_user)
active_relationships.create(followed_id: other_user.id)
end
# Unfollows a user.
def unfollow(other_user)
active_relationships.find_by(followed_id: other_user.id).destroy
end
# Returns true if the current user is following the other user.
def following?(other_user)
following.include?(other_user)
end
private
# Converts email to all lower-case.
def downcase_email
self.email = email.downcase
end
# Creates and assigns the activation token and digest.
def create_activation_digest
self.activation_token = User.new_token
self.activation_digest = User.digest(activation_token)
end
end
class RegistrationsController < Devise::RegistrationsController
def create
super
session[:omniauth] = nil unless @user.new_record?
end
private
def build_resource(*args)
super
if session[:omniauth]
@user.apply_omniauth(session[:omniauth])
@user.valid?
end
end
end
class Authentication < ActiveRecord::Base
belongs_to :user
def provider_name
if provider == 'open_id'
"OpenID"
else
provider.titleize
end
end
end
Rails.application.routes.draw do
get 'auth/:provider/callback', to: 'authentications#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'authentications#destroy_facebook', as: 'signout'
get 'password_resets/new'
get 'password_resets/edit'
resources :authentications
resources :habits
resources :goals
resources :valuations
resources :quantifieds
resources :results
resources :users, controller: 'registrations'
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :relationships, only: [:create, :destroy]
get 'tags/:tag', to: 'valuations#index', as: :tagvaluations
get 'tags/:tag', to: 'habits#index', as: :taghabits
get 'tags/:tag', to: 'goals#index', as: :taggoals
get 'tags/:tag', to: 'quantifieds#index', as: :tagquantifieds
resources :users do
member do
get :following, :followers
end
end
get 'about' => 'pages#about'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
root 'pages#home'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end
class CreateAuthentications < ActiveRecord::Migration
def change
create_table :authentications do |t|
t.integer :user_id
t.string :provider
t.string :uid
t.string :index
t.string :create
t.string :destroy_facebook
t.timestamps null: false
end
end
end
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name
t.string :email
t.text :missed_days
t.text :missed_levels
t.timestamps null: false
end
end
end
Yea I just dumped a lot on you. I have no direction. I followed Railscasts for omniauth: http://railscasts.com/episodes/235-omniauth-part-1?view=asciicast, http://railscasts.com/episodes/236-omniauth-part-2?view=asciicast
This same error gave me a headache once. Check if the email you use for facebook is already in your database. If it's there then delete it and it should work.