FEATURE: SSO to handle return_path automatically

This commit is contained in:
Sam 2014-02-26 09:58:30 +11:00
parent 890d06ac04
commit 440435f023
5 changed files with 20 additions and 16 deletions

View file

@ -15,7 +15,8 @@ Discourse.ApplicationRoute = Em.Route.extend({
bootbox.alert(I18n.t("read_only_mode.login_disabled"));
} else {
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 {
Discourse.Route.showModal(this, 'login');
this.controllerFor('login').resetForm();

View file

@ -9,7 +9,7 @@ class SessionController < ApplicationController
def sso
if SiteSetting.enable_sso
redirect_to DiscourseSingleSignOn.generate_url
redirect_to DiscourseSingleSignOn.generate_url(params[:return_path] || '/')
else
render nothing: true, status: 404
end
@ -27,11 +27,12 @@ class SessionController < ApplicationController
return
end
return_path = sso.return_path
sso.expire_nonce!
if user = sso.lookup_or_create_user
log_on_user user
redirect_to sso.return_url || "/"
redirect_to return_path
else
render text: "unable to log on user", status: 500
end

View file

@ -8,17 +8,16 @@ class DiscourseSingleSignOn < SingleSignOn
SiteSetting.sso_secret
end
def self.generate_url(return_url="/")
def self.generate_url(return_path="/")
sso = new
sso.return_url = return_url
sso.nonce = SecureRandom.hex
sso.register_nonce
sso.register_nonce(return_path)
sso.to_url
end
def register_nonce
def register_nonce(return_path)
if nonce
$redis.setex(nonce_key, NONCE_EXPIRY_TIME, payload)
$redis.setex(nonce_key, NONCE_EXPIRY_TIME, return_path)
end
end
@ -26,6 +25,10 @@ class DiscourseSingleSignOn < SingleSignOn
nonce && $redis.get(nonce_key).present?
end
def return_path
$redis.get(nonce_key) || "/"
end
def expire_nonce!
if nonce
$redis.del nonce_key

View file

@ -1,5 +1,5 @@
class SingleSignOn
ACCESSORS = [:nonce, :return_url, :name, :username, :email, :about_me, :external_id]
ACCESSORS = [:nonce, :name, :username, :email, :about_me, :external_id]
FIXNUMS = []
NONCE_EXPIRY_TIME = 10.minutes

View file

@ -13,11 +13,11 @@ describe SessionController do
SiteSetting.stubs("sso_secret").returns(@sso_secret)
end
def get_sso
def get_sso(return_path)
nonce = SecureRandom.hex
dso = DiscourseSingleSignOn.new
dso.nonce = nonce
dso.register_nonce
dso.register_nonce(return_path)
sso = SingleSignOn.new
sso.nonce = nonce
@ -26,7 +26,7 @@ describe SessionController do
end
it 'can take over an account' do
sso = get_sso
sso = get_sso("/")
user = Fabricate(:user)
sso.email = user.email
sso.external_id = "abc"
@ -41,14 +41,14 @@ describe SessionController do
end
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.email = 'bob@bob.com'
sso.name = 'Sam Saffron'
sso.username = 'sam'
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
@ -61,9 +61,8 @@ describe SessionController do
it 'allows login to existing account with valid nonce' do
sso = get_sso
sso = get_sso('/hello/world')
sso.external_id = '997'
sso.return_url = '/hello/world'
user = Fabricate(:user)
user.create_single_sign_on_record(external_id: '997', last_payload: '')