mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 21:21:19 +08:00
FEATURE: Add logout functionality to SSO Provider protocol (#8816)
This commit adds support for an optional "logout" parameter in the payload of the /session/sso_provider endpoint. If an SSO Consumer adds a "logout=true" parameter to the encoded/signed "sso" payload, then Discourse will treat the request as a logout request instead of an authentication request. The logout flow works something like this: * User requests logout at SSO-Consumer site (e.g., clicks "Log me out!" on web browser). * SSO-Consumer site does whatever it does to destroy User's session on the SSO-Consumer site. * SSO-Consumer then redirects browser to the Discourse sso_provider endpoint, with a signed request bearing "logout=true" in addition to the usual nonce and the "return_sso_url". * Discourse destroys User's discourse session and redirects browser back to the "return_sso_url". * SSO-Consumer site does whatever it does --- notably, it cannot request SSO credentials from Discourse without the User being prompted to login again.
This commit is contained in:
@ -54,6 +54,12 @@ class SessionController < ApplicationController
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if sso.logout
|
||||||
|
params[:return_url] = sso.return_sso_url
|
||||||
|
destroy
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if current_user
|
if current_user
|
||||||
sso.name = current_user.name
|
sso.name = current_user.name
|
||||||
sso.username = current_user.username
|
sso.username = current_user.username
|
||||||
|
@ -16,6 +16,7 @@ class SingleSignOn
|
|||||||
groups
|
groups
|
||||||
locale
|
locale
|
||||||
locale_force_update
|
locale_force_update
|
||||||
|
logout
|
||||||
name
|
name
|
||||||
nonce
|
nonce
|
||||||
profile_background_url
|
profile_background_url
|
||||||
@ -34,6 +35,7 @@ class SingleSignOn
|
|||||||
admin
|
admin
|
||||||
avatar_force_update
|
avatar_force_update
|
||||||
locale_force_update
|
locale_force_update
|
||||||
|
logout
|
||||||
moderator
|
moderator
|
||||||
require_activation
|
require_activation
|
||||||
suppress_welcome_message
|
suppress_welcome_message
|
||||||
|
@ -1105,6 +1105,32 @@ RSpec.describe SessionController do
|
|||||||
expect(sso2.profile_background_url).to start_with(SiteSetting.s3_cdn_url)
|
expect(sso2.profile_background_url).to start_with(SiteSetting.s3_cdn_url)
|
||||||
expect(sso2.card_background_url).to start_with(SiteSetting.s3_cdn_url)
|
expect(sso2.card_background_url).to start_with(SiteSetting.s3_cdn_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "successfully logs out and redirects user to return_sso_url when the user is logged in" do
|
||||||
|
sign_in(@user)
|
||||||
|
|
||||||
|
@sso.logout = true
|
||||||
|
get "/session/sso_provider", params: Rack::Utils.parse_query(@sso.payload("secretForOverRainbow"))
|
||||||
|
|
||||||
|
location = response.header["Location"]
|
||||||
|
expect(location).to match(/^http:\/\/somewhere.over.rainbow\/sso$/)
|
||||||
|
|
||||||
|
expect(response.status).to eq(302)
|
||||||
|
expect(session[:current_user_id]).to be_blank
|
||||||
|
expect(response.cookies["_t"]).to be_blank
|
||||||
|
end
|
||||||
|
|
||||||
|
it "successfully logs out and redirects user to return_sso_url when the user is not logged in" do
|
||||||
|
@sso.logout = true
|
||||||
|
get "/session/sso_provider", params: Rack::Utils.parse_query(@sso.payload("secretForOverRainbow"))
|
||||||
|
|
||||||
|
location = response.header["Location"]
|
||||||
|
expect(location).to match(/^http:\/\/somewhere.over.rainbow\/sso$/)
|
||||||
|
|
||||||
|
expect(response.status).to eq(302)
|
||||||
|
expect(session[:current_user_id]).to be_blank
|
||||||
|
expect(response.cookies["_t"]).to be_blank
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user