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:
Matt Marjanović 2020-02-03 09:53:14 -08:00 committed by GitHub
parent 98e9302c26
commit ad2aa7b52c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 0 deletions

View File

@ -54,6 +54,12 @@ class SessionController < ApplicationController
return
end
if sso.logout
params[:return_url] = sso.return_sso_url
destroy
return
end
if current_user
sso.name = current_user.name
sso.username = current_user.username

View File

@ -16,6 +16,7 @@ class SingleSignOn
groups
locale
locale_force_update
logout
name
nonce
profile_background_url
@ -34,6 +35,7 @@ class SingleSignOn
admin
avatar_force_update
locale_force_update
logout
moderator
require_activation
suppress_welcome_message

View File

@ -1105,6 +1105,32 @@ RSpec.describe SessionController do
expect(sso2.profile_background_url).to start_with(SiteSetting.s3_cdn_url)
expect(sso2.card_background_url).to start_with(SiteSetting.s3_cdn_url)
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