mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-30 10:58:31 -05:00
FEATURE: SSO to handle return_path automatically
This commit is contained in:
parent
890d06ac04
commit
440435f023
5 changed files with 20 additions and 16 deletions
|
@ -15,7 +15,8 @@ Discourse.ApplicationRoute = Em.Route.extend({
|
||||||
bootbox.alert(I18n.t("read_only_mode.login_disabled"));
|
bootbox.alert(I18n.t("read_only_mode.login_disabled"));
|
||||||
} else {
|
} else {
|
||||||
if(Discourse.SiteSettings.enable_sso) {
|
if(Discourse.SiteSettings.enable_sso) {
|
||||||
window.location = Discourse.getURL('/session/sso');
|
var returnPath = encodeURIComponent(window.location.pathname);
|
||||||
|
window.location = Discourse.getURL('/session/sso?return_path=' + returnPath);
|
||||||
} else {
|
} else {
|
||||||
Discourse.Route.showModal(this, 'login');
|
Discourse.Route.showModal(this, 'login');
|
||||||
this.controllerFor('login').resetForm();
|
this.controllerFor('login').resetForm();
|
||||||
|
|
|
@ -9,7 +9,7 @@ class SessionController < ApplicationController
|
||||||
|
|
||||||
def sso
|
def sso
|
||||||
if SiteSetting.enable_sso
|
if SiteSetting.enable_sso
|
||||||
redirect_to DiscourseSingleSignOn.generate_url
|
redirect_to DiscourseSingleSignOn.generate_url(params[:return_path] || '/')
|
||||||
else
|
else
|
||||||
render nothing: true, status: 404
|
render nothing: true, status: 404
|
||||||
end
|
end
|
||||||
|
@ -27,11 +27,12 @@ class SessionController < ApplicationController
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return_path = sso.return_path
|
||||||
sso.expire_nonce!
|
sso.expire_nonce!
|
||||||
|
|
||||||
if user = sso.lookup_or_create_user
|
if user = sso.lookup_or_create_user
|
||||||
log_on_user user
|
log_on_user user
|
||||||
redirect_to sso.return_url || "/"
|
redirect_to return_path
|
||||||
else
|
else
|
||||||
render text: "unable to log on user", status: 500
|
render text: "unable to log on user", status: 500
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,17 +8,16 @@ class DiscourseSingleSignOn < SingleSignOn
|
||||||
SiteSetting.sso_secret
|
SiteSetting.sso_secret
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.generate_url(return_url="/")
|
def self.generate_url(return_path="/")
|
||||||
sso = new
|
sso = new
|
||||||
sso.return_url = return_url
|
|
||||||
sso.nonce = SecureRandom.hex
|
sso.nonce = SecureRandom.hex
|
||||||
sso.register_nonce
|
sso.register_nonce(return_path)
|
||||||
sso.to_url
|
sso.to_url
|
||||||
end
|
end
|
||||||
|
|
||||||
def register_nonce
|
def register_nonce(return_path)
|
||||||
if nonce
|
if nonce
|
||||||
$redis.setex(nonce_key, NONCE_EXPIRY_TIME, payload)
|
$redis.setex(nonce_key, NONCE_EXPIRY_TIME, return_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -26,6 +25,10 @@ class DiscourseSingleSignOn < SingleSignOn
|
||||||
nonce && $redis.get(nonce_key).present?
|
nonce && $redis.get(nonce_key).present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def return_path
|
||||||
|
$redis.get(nonce_key) || "/"
|
||||||
|
end
|
||||||
|
|
||||||
def expire_nonce!
|
def expire_nonce!
|
||||||
if nonce
|
if nonce
|
||||||
$redis.del nonce_key
|
$redis.del nonce_key
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
class SingleSignOn
|
class SingleSignOn
|
||||||
ACCESSORS = [:nonce, :return_url, :name, :username, :email, :about_me, :external_id]
|
ACCESSORS = [:nonce, :name, :username, :email, :about_me, :external_id]
|
||||||
FIXNUMS = []
|
FIXNUMS = []
|
||||||
NONCE_EXPIRY_TIME = 10.minutes
|
NONCE_EXPIRY_TIME = 10.minutes
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ describe SessionController do
|
||||||
SiteSetting.stubs("sso_secret").returns(@sso_secret)
|
SiteSetting.stubs("sso_secret").returns(@sso_secret)
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_sso
|
def get_sso(return_path)
|
||||||
nonce = SecureRandom.hex
|
nonce = SecureRandom.hex
|
||||||
dso = DiscourseSingleSignOn.new
|
dso = DiscourseSingleSignOn.new
|
||||||
dso.nonce = nonce
|
dso.nonce = nonce
|
||||||
dso.register_nonce
|
dso.register_nonce(return_path)
|
||||||
|
|
||||||
sso = SingleSignOn.new
|
sso = SingleSignOn.new
|
||||||
sso.nonce = nonce
|
sso.nonce = nonce
|
||||||
|
@ -26,7 +26,7 @@ describe SessionController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'can take over an account' do
|
it 'can take over an account' do
|
||||||
sso = get_sso
|
sso = get_sso("/")
|
||||||
user = Fabricate(:user)
|
user = Fabricate(:user)
|
||||||
sso.email = user.email
|
sso.email = user.email
|
||||||
sso.external_id = "abc"
|
sso.external_id = "abc"
|
||||||
|
@ -41,14 +41,14 @@ describe SessionController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'allows you to create an account' do
|
it 'allows you to create an account' do
|
||||||
sso = get_sso
|
sso = get_sso('/a/')
|
||||||
sso.external_id = '666' # the number of the beast
|
sso.external_id = '666' # the number of the beast
|
||||||
sso.email = 'bob@bob.com'
|
sso.email = 'bob@bob.com'
|
||||||
sso.name = 'Sam Saffron'
|
sso.name = 'Sam Saffron'
|
||||||
sso.username = 'sam'
|
sso.username = 'sam'
|
||||||
|
|
||||||
get :sso_login, Rack::Utils.parse_query(sso.payload)
|
get :sso_login, Rack::Utils.parse_query(sso.payload)
|
||||||
response.should redirect_to('/')
|
response.should redirect_to('/a/')
|
||||||
|
|
||||||
logged_on_user = Discourse.current_user_provider.new(request.env).current_user
|
logged_on_user = Discourse.current_user_provider.new(request.env).current_user
|
||||||
|
|
||||||
|
@ -61,9 +61,8 @@ describe SessionController do
|
||||||
|
|
||||||
it 'allows login to existing account with valid nonce' do
|
it 'allows login to existing account with valid nonce' do
|
||||||
|
|
||||||
sso = get_sso
|
sso = get_sso('/hello/world')
|
||||||
sso.external_id = '997'
|
sso.external_id = '997'
|
||||||
sso.return_url = '/hello/world'
|
|
||||||
|
|
||||||
user = Fabricate(:user)
|
user = Fabricate(:user)
|
||||||
user.create_single_sign_on_record(external_id: '997', last_payload: '')
|
user.create_single_sign_on_record(external_id: '997', last_payload: '')
|
||||||
|
|
Loading…
Reference in a new issue