I am using the Omniauth gem paired with the Devise gem for user authentication (here is a wiki. I chose Oauth2 strategy for authenticating Instagram user in my app.
My issue is that Users signing in through Instagram authentication are not persisted to my User model. After authenticating with Instagram they are redirected to a new user registration path localhost:3000/users/sign_up.
controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def instagram
# You need to implement the method below in your model (e.g. app/models/user.rb)
@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 => "Instagram") if is_navigational_format?
else
session["devise.instagram_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
devise :omniauthable, :omniauth_providers => [:instagram]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
# user.name = auth.info.name # assuming the user model has a name
# user.image = auth.info.image # assuming the user model has an image
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.instagram_data"] && session["devise.instagram_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
Users table has the appropriate column (provider
, uid
)
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
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"
t.datetime "created_at"
t.datetime "updated_at"
t.string "provider"
t.string "uid"
end
Finally, here is the output when signing in via Instagram authentication
Started GET "/users/auth/instagram" for ::1 at 2015-09-25 09:57:54 -0400
I, [2015-09-25T09:57:54.577637 #7451] INFO -- omniauth: (instagram) Request phase initiated.
Started GET "/users/auth/instagram" for ::1 at 2015-09-25 09:57:54 -0400
I, [2015-09-25T09:57:54.655615 #7451] INFO -- omniauth: (instagram) Request phase initiated.
Started GET "/users/auth/instagram/callback?code=SOME_CODE&state=SOME_STATE" for ::1 at 2015-09-25 09:57:54 -0400
I, [2015-09-25T09:57:54.811861 #7451] INFO -- omniauth: (instagram) Callback phase initiated.
Processing by Users::OmniauthCallbacksController#instagram as HTML
Parameters: {"code"=>"SOME_CODE", "state"=>"SOME_STATE"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."provider" = ? AND "users"."uid" = ? ORDER BY "users"."id" ASC LIMIT 1 [["provider", "instagram"], ["uid", "343664764"]]
(0.1ms) begin transaction
(0.1ms) rollback transaction
Redirected to http://localhost:3000/users/sign_up