mirror of
https://github.com/discourse/discourse.git
synced 2025-02-13 14:55:06 +00:00
Authenticate with Discourse via OAuth2
See https://github.com/michaelkirk/discourse_oauth2_example for an example of how you might integrate your existing oauth2 provider's authentication via a Discourse plugin.
This commit is contained in:
parent
a67b1ba32c
commit
4af8a9102e
1
Gemfile
1
Gemfile
@ -97,6 +97,7 @@ gem 'openid-redis-store'
|
|||||||
gem 'omniauth-facebook'
|
gem 'omniauth-facebook'
|
||||||
gem 'omniauth-twitter'
|
gem 'omniauth-twitter'
|
||||||
gem 'omniauth-github'
|
gem 'omniauth-github'
|
||||||
|
gem 'omniauth-oauth2'
|
||||||
gem 'omniauth-browserid', git: 'https://github.com/callahad/omniauth-browserid.git', branch: 'observer_api'
|
gem 'omniauth-browserid', git: 'https://github.com/callahad/omniauth-browserid.git', branch: 'observer_api'
|
||||||
gem 'omniauth-cas'
|
gem 'omniauth-cas'
|
||||||
gem 'oj'
|
gem 'oj'
|
||||||
|
@ -497,6 +497,7 @@ DEPENDENCIES
|
|||||||
omniauth-cas
|
omniauth-cas
|
||||||
omniauth-facebook
|
omniauth-facebook
|
||||||
omniauth-github
|
omniauth-github
|
||||||
|
omniauth-oauth2
|
||||||
omniauth-openid
|
omniauth-openid
|
||||||
omniauth-twitter
|
omniauth-twitter
|
||||||
openid-redis-store
|
openid-redis-store
|
||||||
|
@ -29,6 +29,10 @@ class Users::OmniauthCallbacksController < ApplicationController
|
|||||||
create_or_sign_on_user_using_openid request.env["omniauth.auth"]
|
create_or_sign_on_user_using_openid request.env["omniauth.auth"]
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
|
elsif p.name == provider && p.type == :oauth2
|
||||||
|
create_or_sign_on_user_using_oauth2 request.env["omniauth.auth"]
|
||||||
|
found = true
|
||||||
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -194,6 +198,58 @@ class Users::OmniauthCallbacksController < ApplicationController
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_or_sign_on_user_using_oauth2(auth_token)
|
||||||
|
oauth2_provider = auth_token[:provider]
|
||||||
|
oauth2_uid = auth_token[:uid]
|
||||||
|
data = auth_token[:info]
|
||||||
|
email = data[:email]
|
||||||
|
name = data[:name]
|
||||||
|
|
||||||
|
oauth2_user_info = Oauth2UserInfo.where(uid: oauth2_uid, provider: oauth2_provider).first
|
||||||
|
|
||||||
|
if oauth2_user_info.blank? && user = User.find_by_email(email)
|
||||||
|
# TODO is only safe if we trust our oauth2 provider to return an email
|
||||||
|
# legitimately owned by our user
|
||||||
|
oauth2_user_info = Oauth2UserInfo.create(uid: oauth2_uid,
|
||||||
|
provider: oauth2_provider,
|
||||||
|
name: name,
|
||||||
|
email: name,
|
||||||
|
user: user)
|
||||||
|
end
|
||||||
|
|
||||||
|
authenticated = oauth2_user_info.present?
|
||||||
|
|
||||||
|
if authenticated
|
||||||
|
user = oauth2_user_info.user
|
||||||
|
|
||||||
|
# If we have to approve users
|
||||||
|
if Guardian.new(user).can_access_forum?
|
||||||
|
log_on_user(user)
|
||||||
|
@data = {authenticated: true}
|
||||||
|
else
|
||||||
|
@data = {awaiting_approval: true}
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@data = {
|
||||||
|
email: email,
|
||||||
|
name: User.suggest_name(name),
|
||||||
|
username: UserNameSuggester.suggest(email),
|
||||||
|
email_valid: true ,
|
||||||
|
auth_provider: oauth2_provider
|
||||||
|
}
|
||||||
|
|
||||||
|
session[:authentication] = {
|
||||||
|
oauth2: {
|
||||||
|
provider: oauth2_provider,
|
||||||
|
uid: oauth2_uid,
|
||||||
|
},
|
||||||
|
name: name,
|
||||||
|
email: @data[:email],
|
||||||
|
email_valid: @data[:email_valid]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def create_or_sign_on_user_using_openid(auth_token)
|
def create_or_sign_on_user_using_openid(auth_token)
|
||||||
|
|
||||||
|
@ -432,6 +432,16 @@ class UsersController < ApplicationController
|
|||||||
github_user_id: auth[:github_user_id]
|
github_user_id: auth[:github_user_id]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if oauth2_auth?(auth)
|
||||||
|
Oauth2UserInfo.create(
|
||||||
|
uid: auth[:oauth2][:uid],
|
||||||
|
provider: auth[:oauth2][:provider],
|
||||||
|
name: auth[:name],
|
||||||
|
email: auth[:email],
|
||||||
|
user_id: user.id
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def twitter_auth?(auth)
|
def twitter_auth?(auth)
|
||||||
@ -448,4 +458,9 @@ class UsersController < ApplicationController
|
|||||||
auth[:github_user_id] && auth[:github_screen_name] &&
|
auth[:github_user_id] && auth[:github_screen_name] &&
|
||||||
GithubUserInfo.find_by_github_user_id(auth[:github_user_id]).nil?
|
GithubUserInfo.find_by_github_user_id(auth[:github_user_id]).nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def oauth2_auth?(auth)
|
||||||
|
auth[:oauth2].is_a?(Hash) && auth[:oauth2][:provider] && auth[:oauth2][:uid] &&
|
||||||
|
Oauth2UserInfo.where(provider: auth[:oauth2][:provider], uid: auth[:oauth2][:uid]).empty?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
4
app/models/oauth2_user_info.rb
Normal file
4
app/models/oauth2_user_info.rb
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
class Oauth2UserInfo < ActiveRecord::Base
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
end
|
@ -34,6 +34,7 @@ class User < ActiveRecord::Base
|
|||||||
has_one :twitter_user_info, dependent: :destroy
|
has_one :twitter_user_info, dependent: :destroy
|
||||||
has_one :github_user_info, dependent: :destroy
|
has_one :github_user_info, dependent: :destroy
|
||||||
has_one :cas_user_info, dependent: :destroy
|
has_one :cas_user_info, dependent: :destroy
|
||||||
|
has_one :oauth2_user_info, dependent: :destroy
|
||||||
belongs_to :approved_by, class_name: 'User'
|
belongs_to :approved_by, class_name: 'User'
|
||||||
|
|
||||||
has_many :group_users
|
has_many :group_users
|
||||||
|
@ -25,6 +25,14 @@ Rails.application.config.middleware.use OmniAuth::Builder do
|
|||||||
:store => OpenID::Store::Redis.new($redis),
|
:store => OpenID::Store::Redis.new($redis),
|
||||||
:require => "omniauth-openid"
|
:require => "omniauth-openid"
|
||||||
}.merge(p.options)
|
}.merge(p.options)
|
||||||
|
elsif p.type == :oauth2
|
||||||
|
provider :oauth2,
|
||||||
|
p.options[:client_id],
|
||||||
|
p.options[:client_secret],
|
||||||
|
{
|
||||||
|
:name => p.name,
|
||||||
|
:require => "omniauth-oauth2"
|
||||||
|
}.merge(p.options)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
14
db/migrate/20130816024250_create_oauth2_user_infos.rb
Normal file
14
db/migrate/20130816024250_create_oauth2_user_infos.rb
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
class CreateOauth2UserInfos < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :oauth2_user_infos do |t|
|
||||||
|
t.integer :user_id, null: false
|
||||||
|
t.string :uid, null: false
|
||||||
|
t.string :provider, null: false
|
||||||
|
t.string :email
|
||||||
|
t.string :name
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :oauth2_user_infos, [:uid, :provider], unique: true
|
||||||
|
end
|
||||||
|
end
|
@ -164,4 +164,25 @@ describe Users::OmniauthCallbacksController do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'oauth2' do
|
||||||
|
before do
|
||||||
|
Discourse.stubs(:auth_providers).returns([stub(name: 'my_oauth2_provider', type: :oauth2)])
|
||||||
|
request.env["omniauth.auth"] = { uid: 'my-uid', provider: 'my-oauth-provider-domain.net', info: {email: 'eviltrout@made.up.email', name: 'Chatanooga'}}
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#create_or_sign_on_user_using_oauth2" do
|
||||||
|
context "User already exists" do
|
||||||
|
before do
|
||||||
|
User.stubs(:find_by_email).returns(Fabricate(:user))
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should create an OauthUserInfo" do
|
||||||
|
expect {
|
||||||
|
post :complete, provider: 'my_oauth2_provider'
|
||||||
|
}.to change { Oauth2UserInfo.count }.by(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user