mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 09:42:07 +08:00
Add Google Oauth2 authenticator. The current Google OpenID authentication has been deprecated by Google and will NOT work for any new websites.
This commit is contained in:
parent
ca95bdb023
commit
742841ddce
1
Gemfile
1
Gemfile
|
@ -129,6 +129,7 @@ gem 'omniauth-facebook'
|
|||
gem 'omniauth-twitter'
|
||||
gem 'omniauth-github'
|
||||
gem 'omniauth-oauth2', require: false
|
||||
gem 'omniauth-google-oauth2'
|
||||
gem 'oj'
|
||||
# while resolving https://groups.google.com/forum/#!topic/ruby-pg/5_ylGmog1S4
|
||||
gem 'pg', '0.15.1'
|
||||
|
|
|
@ -197,6 +197,9 @@ GEM
|
|||
omniauth-github (1.1.1)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-google-oauth2 (0.2.4)
|
||||
omniauth (~> 1.0)
|
||||
omniauth-oauth2 (~> 1.1)
|
||||
omniauth-oauth (1.0.1)
|
||||
oauth
|
||||
omniauth (~> 1.0)
|
||||
|
@ -436,6 +439,7 @@ DEPENDENCIES
|
|||
omniauth
|
||||
omniauth-facebook
|
||||
omniauth-github
|
||||
omniauth-google-oauth2
|
||||
omniauth-oauth2
|
||||
omniauth-openid
|
||||
omniauth-twitter
|
||||
|
|
|
@ -31,6 +31,7 @@ Discourse.LoginMethod.reopenClass({
|
|||
* */
|
||||
|
||||
[ "google",
|
||||
"google_oauth2",
|
||||
"facebook",
|
||||
"cas",
|
||||
"twitter",
|
||||
|
@ -41,7 +42,7 @@ Discourse.LoginMethod.reopenClass({
|
|||
|
||||
var params = {name: name};
|
||||
|
||||
if (name === "google") {
|
||||
if (name === "google" || name === "google_oauth2") {
|
||||
params.frameWidth = 850;
|
||||
params.frameHeight = 500;
|
||||
} else if (name === "facebook") {
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
font-family: zocial;
|
||||
line-height: 0.9;
|
||||
}
|
||||
&.google {
|
||||
&.google, &.google_oauth2 {
|
||||
background: $google;
|
||||
&:before {
|
||||
content: "G";
|
||||
|
|
|
@ -8,6 +8,7 @@ class Users::OmniauthCallbacksController < ApplicationController
|
|||
BUILTIN_AUTH = [
|
||||
Auth::FacebookAuthenticator.new,
|
||||
Auth::OpenIdAuthenticator.new("google", "https://www.google.com/accounts/o8/id", trusted: true),
|
||||
Auth::GoogleOAuth2Authenticator.new,
|
||||
Auth::OpenIdAuthenticator.new("yahoo", "https://me.yahoo.com", trusted: true),
|
||||
Auth::GithubAuthenticator.new,
|
||||
Auth::TwitterAuthenticator.new
|
||||
|
|
|
@ -27,6 +27,9 @@ class AdminDashboardData
|
|||
gc_checks,
|
||||
sidekiq_check || queue_size_check,
|
||||
ram_check,
|
||||
old_google_config_check,
|
||||
both_googles_config_check,
|
||||
google_oauth2_config_check,
|
||||
facebook_config_check,
|
||||
twitter_config_check,
|
||||
github_config_check,
|
||||
|
@ -45,6 +48,7 @@ class AdminDashboardData
|
|||
].compact
|
||||
end
|
||||
|
||||
|
||||
def self.fetch_stats
|
||||
AdminDashboardData.new
|
||||
end
|
||||
|
@ -106,8 +110,20 @@ class AdminDashboardData
|
|||
I18n.t('dashboard.memory_warning') if MemInfo.new.mem_total and MemInfo.new.mem_total < 1_000_000
|
||||
end
|
||||
|
||||
def old_google_config_check
|
||||
I18n.t('dashboard.enable_google_logins_warning') if SiteSetting.enable_google_logins
|
||||
end
|
||||
|
||||
def both_googles_config_check
|
||||
I18n.t('dashboard.both_googles_warning') if SiteSetting.enable_google_logins && SiteSetting.enable_google_oauth2_logins
|
||||
end
|
||||
|
||||
def google_oauth2_config_check
|
||||
I18n.t('dashboard.google_oauth2_config_warning') if SiteSetting.enable_google_logins && (SiteSetting.google_oauth2_client_id.blank? || SiteSetting.google_oauth2_client_secret.blank?)
|
||||
end
|
||||
|
||||
def facebook_config_check
|
||||
I18n.t('dashboard.facebook_config_warning') if SiteSetting.enable_facebook_logins and (SiteSetting.facebook_app_id.blank? or SiteSetting.facebook_app_secret.blank?)
|
||||
I18n.t('dashboard.facebook_config_warning') if SiteSetting.enable_facebook_logins && (SiteSetting.facebook_app_id.blank? || SiteSetting.facebook_app_secret.blank?)
|
||||
end
|
||||
|
||||
def twitter_config_check
|
||||
|
|
3
app/models/google_user_info.rb
Normal file
3
app/models/google_user_info.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class GoogleUserInfo < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
end
|
|
@ -509,6 +509,9 @@ en:
|
|||
google:
|
||||
title: "with Google"
|
||||
message: "Authenticating with Google (make sure pop up blockers are not enabled)"
|
||||
google_oauth2:
|
||||
title: "with Google"
|
||||
message: "Authenticating with Google (make sure pop up blockers are not enabled)"
|
||||
twitter:
|
||||
title: "with Twitter"
|
||||
message: "Authenticating with Twitter (make sure pop up blockers are not enabled)"
|
||||
|
|
|
@ -518,6 +518,9 @@ en:
|
|||
sidekiq_warning: 'Sidekiq is not running. Many tasks, like sending emails, are executed asynchronously by sidekiq. Please ensure at least one sidekiq process is running. <a href="https://github.com/mperham/sidekiq" target="_blank">Learn about Sidekiq here</a>.'
|
||||
queue_size_warning: 'The number of queued jobs is %{queue_size}, which is high. This could indicate a problem with the Sidekiq process(es), or you may need to add more Sidekiq workers.'
|
||||
memory_warning: 'Your server is running with less than 1 GB of total memory. At least 1 GB of memory is recommended.'
|
||||
enable_google_logins_warning: "You are using a deprecated version of Google's OpenID authentication. Google will be ending support for OpenID by April 20, 2015. Start using Google Oauth2 as soon as possible."
|
||||
both_googles_warning: "You have both enable_google_logins and enable_google_oauth2_logins checked in the site settings. Disable enable_google_logins."
|
||||
google_oauth2_config_warning: 'The server is configured to allow signup and log in with Google Oauth2 (enable_google_oauth2_logins), but the client id and client secret values are not set. Go to <a href="/admin/site_settings">the Site Settings</a> and update the settings.'
|
||||
facebook_config_warning: 'The server is configured to allow signup and log in with Facebook (enable_facebook_logins), but the app id and app secret values are not set. Go to <a href="/admin/site_settings">the Site Settings</a> and update the settings. <a href="https://meta.discourse.org/t/configuring-facebook-login-for-discourse/13394" target="_blank">See this guide to learn more</a>.'
|
||||
twitter_config_warning: 'The server is configured to allow signup and log in with Twitter (enable_twitter_logins), but the key and secret values are not set. Go to <a href="/admin/site_settings">the Site Settings</a> and update the settings. <a href="https://meta.discourse.org/t/configuring-twitter-login-for-discourse/13395" target="_blank">See this guide to learn more</a>.'
|
||||
github_config_warning: 'The server is configured to allow signup and log in with GitHub (enable_github_logins), but the client id and secret values are not set. Go to <a href="/admin/site_settings">the Site Settings</a> and update the settings. <a href="https://meta.discourse.org/t/configuring-github-login-for-discourse/13745" target="_blank">See this guide to learn more</a>.'
|
||||
|
@ -720,9 +723,13 @@ en:
|
|||
sso_overrides_name: "Overrides local name with external site name from SSO payload (WARNING: discrepancies can occur due to normalization of local names)"
|
||||
|
||||
enable_local_logins: "Enable traditional, local username and password authentication"
|
||||
enable_google_logins: "Enable Google authentication"
|
||||
enable_google_logins: "(deprecated) Enable Google authentication. This is the OpenID method of authentication which Google has deprecated. New installs will NOT work with this. Use Google Oauth2 instead. Existing installs must move to Google Oauth2 by April 20, 2015."
|
||||
enable_yahoo_logins: "Enable Yahoo authentication"
|
||||
|
||||
enable_google_oauth2_logins: "Enable Google Oauth2 authentication. This is the method of authentication that Google currently supports. Requires key and secret."
|
||||
google_oauth2_client_id: "Client ID of your Google application."
|
||||
google_oauth2_client_secret: "Client secret of your Google application."
|
||||
|
||||
enable_twitter_logins: "Enable Twitter authentication, requires twitter_consumer_key and twitter_consumer_secret"
|
||||
twitter_consumer_key: "Consumer key for Twitter authentication, registered at http://dev.twitter.com"
|
||||
twitter_consumer_secret: "Consumer secret for Twitter authentication, registered at http://dev.twitter.com"
|
||||
|
|
|
@ -114,8 +114,13 @@ users:
|
|||
default: 8
|
||||
block_common_passwords: true
|
||||
enable_google_logins:
|
||||
client: true
|
||||
default: false
|
||||
enable_google_oauth2_logins:
|
||||
client: true
|
||||
default: true
|
||||
google_oauth2_client_id: ''
|
||||
google_oauth2_client_secret: ''
|
||||
enable_yahoo_logins:
|
||||
client: true
|
||||
default: true
|
||||
|
|
20
db/migrate/20140521192142_create_google_user_infos.rb
Normal file
20
db/migrate/20140521192142_create_google_user_infos.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
class CreateGoogleUserInfos < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :google_user_infos do |t|
|
||||
t.integer :user_id, null: false
|
||||
t.string :google_user_id, null: false
|
||||
t.string :first_name
|
||||
t.string :last_name
|
||||
t.string :email
|
||||
t.string :gender
|
||||
t.string :name
|
||||
t.string :link
|
||||
t.string :profile_link
|
||||
t.string :picture
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :google_user_infos, :user_id, unique: true
|
||||
add_index :google_user_infos, :google_user_id, unique: true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class GoogleOpenidDefaultHasChanged < ActiveRecord::Migration
|
||||
def up
|
||||
result = Category.exec_sql("SELECT count(*) FROM site_settings WHERE name = 'enable_google_logins'")
|
||||
if result[0]['count'].to_i == 0
|
||||
# The old default was true, so add a row to keep it that way.
|
||||
execute "INSERT INTO site_settings (name, data_type, value, created_at, updated_at) VALUES ('enable_google_logins', 5, 't', now(), now())"
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# No need to undo.
|
||||
end
|
||||
end
|
|
@ -6,3 +6,4 @@ require_dependency 'auth/facebook_authenticator'
|
|||
require_dependency 'auth/open_id_authenticator'
|
||||
require_dependency 'auth/github_authenticator'
|
||||
require_dependency 'auth/twitter_authenticator'
|
||||
require_dependency 'auth/google_oauth2_authenticator'
|
||||
|
|
67
lib/auth/google_oauth2_authenticator.rb
Normal file
67
lib/auth/google_oauth2_authenticator.rb
Normal file
|
@ -0,0 +1,67 @@
|
|||
class Auth::GoogleOAuth2Authenticator < Auth::Authenticator
|
||||
|
||||
def name
|
||||
"google_oauth2"
|
||||
end
|
||||
|
||||
def after_authenticate(auth_hash)
|
||||
session_info = parse_hash(auth_hash)
|
||||
google_hash = session_info[:google]
|
||||
|
||||
result = Auth::Result.new
|
||||
result.email = session_info[:email]
|
||||
result.email_valid = session_info[:email_valid]
|
||||
result.name = session_info[:name]
|
||||
|
||||
result.extra_data = google_hash
|
||||
|
||||
user_info = GoogleUserInfo.find_by(google_user_id: google_hash[:google_user_id])
|
||||
result.user = user_info.try(:user)
|
||||
|
||||
if !result.user && !result.email.blank? && result.user = User.find_by(email: Email.downcase(result.email))
|
||||
GoogleUserInfo.create({user_id: result.user.id}.merge(google_hash))
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
def after_create_account(user, auth)
|
||||
data = auth[:extra_data]
|
||||
GoogleUserInfo.create({user_id: user.id}.merge(data))
|
||||
end
|
||||
|
||||
def register_middleware(omniauth)
|
||||
omniauth.provider :google_oauth2,
|
||||
:setup => lambda { |env|
|
||||
strategy = env["omniauth.strategy"]
|
||||
strategy.options[:client_id] = SiteSetting.google_oauth2_client_id
|
||||
strategy.options[:client_secret] = SiteSetting.google_oauth2_client_secret
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def parse_hash(hash)
|
||||
extra = hash[:extra][:raw_info]
|
||||
|
||||
h = {}
|
||||
|
||||
h[:email] = hash[:info][:email]
|
||||
h[:name] = hash[:info][:name]
|
||||
h[:email_valid] = hash[:extra][:raw_info][:email_verified]
|
||||
|
||||
h[:google] = {
|
||||
google_user_id: hash[:uid] || extra[:sub],
|
||||
email: extra[:email],
|
||||
first_name: extra[:given_name],
|
||||
last_name: extra[:family_name],
|
||||
gender: extra[:gender],
|
||||
name: extra[:name],
|
||||
link: extra[:hd],
|
||||
profile_link: extra[:profile],
|
||||
picture: extra[:picture]
|
||||
}
|
||||
|
||||
h
|
||||
end
|
||||
end
|
58
spec/components/auth/google_oauth2_authenticator_spec.rb
Normal file
58
spec/components/auth/google_oauth2_authenticator_spec.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
require 'spec_helper'
|
||||
|
||||
# For autospec:
|
||||
Auth.send(:remove_const, :GoogleOAuth2Authenticator)
|
||||
load 'auth/google_oauth2_authenticator.rb'
|
||||
|
||||
describe Auth::GoogleOAuth2Authenticator do
|
||||
|
||||
context 'after_authenticate' do
|
||||
it 'can authenticate and create a user record for already existing users' do
|
||||
authenticator = described_class.new
|
||||
user = Fabricate(:user)
|
||||
|
||||
hash = {
|
||||
:uid => "123456789",
|
||||
:info => {
|
||||
:name => "John Doe",
|
||||
:email => user.email
|
||||
},
|
||||
:extra => {
|
||||
:raw_info => {
|
||||
:email => "user@domain.example.com",
|
||||
:email_verified => true,
|
||||
:name => "John Doe"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = authenticator.after_authenticate(hash)
|
||||
|
||||
result.user.id.should == user.id
|
||||
end
|
||||
|
||||
it 'can create a proper result for non existing users' do
|
||||
hash = {
|
||||
:uid => "123456789",
|
||||
:info => {
|
||||
:name => "Jane Doe",
|
||||
:email => "jane.doe@the.google.com"
|
||||
},
|
||||
:extra => {
|
||||
:raw_info => {
|
||||
:email => "jane.doe@the.google.com",
|
||||
:email_verified => true,
|
||||
:name => "Jane Doe"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
authenticator = described_class.new
|
||||
result = authenticator.after_authenticate(hash)
|
||||
|
||||
result.user.should be_nil
|
||||
result.extra_data[:name].should == "Jane Doe"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in New Issue
Block a user