-
Notifications
You must be signed in to change notification settings - Fork 228
External
Facebook users, please use Sorcery version 0.11.0 or greater, see: #53
In this tutorial we will build upon the app created at Simple Password Authentication so make sure you understand it.
First Add some db fields:
rails g sorcery:install external --only-submodules
Which will create:
class SorceryExternal < ActiveRecord::Migration
def change
create_table :authentications do |t|
t.integer :user_id, :null => false
t.string :provider, :uid, :null => false
t.timestamps
end
end
end
rake db:migrate
And generate the model Authentication without migration:
rails g model Authentication --migration=false
Let's add the submodule and configuration:
# config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:external, blabla, blablu, ...]
Rails.application.config.sorcery.configure do |config|
...
config.external_providers = [:twitter, :facebook]
#add this file to .gitignore BEFORE putting any secret keys in here, or use a system like Figaro to abstract it!!!
config.twitter.key = "<your key here>"
config.twitter.secret = "<your key here>"
config.twitter.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=twitter"
config.twitter.user_info_mapping = {:email => "screen_name"}
config.facebook.key = "<your key here>"
config.facebook.secret = "<your key here>"
config.facebook.callback_url = "http://0.0.0.0:3000/oauth/callback?provider=facebook"
config.facebook.user_info_path = "me?fields=email,name,username" #etc
config.facebook.user_info_mapping = {:email => "email", :name => "name", :username => "username", :hometown => "hometown/name"} #etc
config.facebook.scope = "email,user_hometown,user_interests,user_likes" #etc
config.facebook.display = "popup"
...
# --- user config ---
config.user_config do |user|
...
# -- external --
user.authentications_class = Authentication
...
end
...
end
You will need to register your app with Twitter/Facebook to get your keys of course.
The 'user_info_mapping' takes care of converting the user info from the provider (Twitter/Facebook) into the attributes that your user has, in this case we only used it to have a username.
Now we need to associate User with Authentication:
# app/models/user.rb
class User < ActiveRecord::Base
has_many :authentications, :dependent => :destroy
accepts_nested_attributes_for :authentications
end
# app/models/authentication.rb
class Authentication < ActiveRecord::Base
belongs_to :user
end
Let's add links to connect to Twitter and Facebook (you would probably use images in a real app):
# app/views/layouts/application.html.erb
...
<%= link_to 'Login with Twitter', login_at(:twitter) %> |
<%= link_to 'Login with Facebook', login_at(:facebook) %>
We'll need a controller to handle the authentications:
rails g controller Oauths oauth callback
# app/controllers/oauths_controller.rb
class OauthsController < ApplicationController
skip_before_action :require_login, raise: false
# sends the user on a trip to the provider,
# and after authorizing there back to the callback url.
def oauth
login_at(params[:provider])
end
def callback
provider = params[:provider]
if @user = login_from(provider)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
else
begin
@user = create_from(provider)
# NOTE: this is the place to add '@user.activate!' if you are using user_activation submodule
reset_session # protect from session fixation attack
auto_login(@user)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
rescue
redirect_to root_path, :alert => "Failed to login from #{provider.titleize}!"
end
end
end
#example for Rails 4: add private method below and use "auth_params[:provider]" in place of
#"params[:provider] above.
# private
# def auth_params
# params.permit(:code, :provider)
# end
end
Let's add routes for this controller:
# config/routes.rb
post "oauth/callback" => "oauths#callback"
get "oauth/callback" => "oauths#callback" # for use with Github, Facebook
get "oauth/:provider" => "oauths#oauth", :as => :auth_at_provider
Basically how this works is like this: The user asks to login using a provider. We send the user to authorize at the provider's site, and he is then redirected back. If he doesn't exist in our db, he is auto-created and logged in. If he already exists in our db, he just gets logged in.
Meta
Using Sorcery
- Activity Logging
- Brute Force Protection
- DataMapper Support
- DelayedJob Integration
- Distinguish login failure reasons
- External
- External---Microsoft-Graph-authentication
- Fetching Currently Active Users
- HTTP Basic Auth
- Integration Testing
- OAuth Landing Page
- Password-less Activation
- Remember Me
- Reset Password
- Routes Constraints
- Session Timeout
- Simple Password Authentication
- Single Table Inheritance Support
- Testing Rails
- User Activation
Contributing to Sorcery