FEATURE: Add prompt=none functionality to SSO Provider protocol (#22393)

This commit adds support for an optional `prompt` parameter in the
payload of the /session/sso_provider endpoint.  If an SSO Consumer
adds a `prompt=none` parameter to the encoded/signed `sso` payload,
then Discourse will avoid trying to login a not-logged-in user:

 * If the user is already logged in, Discourse will immediately
   redirect back to the Consumer with the user's credentials in a
   signed payload, as usual.

 * If the user is not logged in, Discourse will immediately redirect
   back to the Consumer with a signed payload bearing the parameter
   `failed=true`.

This allows the SSO Consumer to simply test whether or not a user is
logged in, without forcing the user to try to log in.  This is useful
when the SSO Consumer allows both anonymous and authenticated access.
(E.g., users that are already logged-in to Discourse can be seamlessly
logged-in to the Consumer site, and anonymous users can remain
anonymous until they explicitly ask to log in.)

This feature is similar to the `prompt=none` functionality in an
OpenID Connect Authentication Request; see
https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
This commit is contained in:
Matt Marjanović
2023-09-28 04:53:28 -07:00
committed by GitHub
parent b72ed3cb38
commit 619d43ea47
6 changed files with 88 additions and 7 deletions

View File

@ -59,9 +59,14 @@ class SessionController < ApplicationController
end
if data[:no_current_user]
cookies[:sso_payload] = payload || request.query_string
redirect_to path("/login")
return
if data[:prompt] == "none"
redirect_to data[:sso_redirect_url], allow_other_host: true
return
else
cookies[:sso_payload] = payload || request.query_string
redirect_to path("/login")
return
end
end
if request.xhr?
@ -88,6 +93,8 @@ class SessionController < ApplicationController
render plain: I18n.t("discourse_connect.login_error"), status: 422
rescue DiscourseConnectProvider::BlankReturnUrl
render plain: "return_sso_url is blank, it must be provided", status: 400
rescue DiscourseConnectProvider::InvalidParameterValueError => e
render plain: I18n.t("discourse_connect.invalid_parameter_value", param: e.param), status: 400
end
# For use in development mode only when login options could be limited or disabled.