mirror of
https://github.com/element-hq/synapse
synced 2024-09-02 13:50:21 +00:00
SAML2 Improvements and redirect stuff
Signed-off-by: Alexander Trost <galexrt@googlemail.com>
This commit is contained in:
parent
d828d1dc57
commit
dc3e586938
5 changed files with 55 additions and 2 deletions
|
@ -57,6 +57,7 @@ class LoginType(object):
|
|||
EMAIL_IDENTITY = u"m.login.email.identity"
|
||||
MSISDN = u"m.login.msisdn"
|
||||
RECAPTCHA = u"m.login.recaptcha"
|
||||
SSO = u"m.login.sso"
|
||||
TERMS = u"m.login.terms"
|
||||
DUMMY = u"m.login.dummy"
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ class SAML2Config(Config):
|
|||
# override them.
|
||||
#
|
||||
#saml2_config:
|
||||
# enabled: true
|
||||
# sp_config:
|
||||
# # point this to the IdP's metadata. You can use either a local file or
|
||||
# # (preferably) a URL.
|
||||
|
|
|
@ -727,6 +727,9 @@ class AuthHandler(BaseHandler):
|
|||
if canonical_user_id:
|
||||
defer.returnValue((canonical_user_id, None))
|
||||
|
||||
if login_type == LoginType.SSO:
|
||||
known_login_type = True
|
||||
|
||||
if not known_login_type:
|
||||
raise SynapseError(400, "Unknown login type %s" % login_type)
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@ from synapse.rest.well_known import WellKnownBuilder
|
|||
from synapse.types import UserID, map_username_to_mxid_localpart
|
||||
from synapse.util.msisdn import phone_number_to_msisdn
|
||||
|
||||
import saml2
|
||||
from saml2.client import Saml2Client
|
||||
|
||||
from .base import ClientV1RestServlet, client_path_patterns
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -93,6 +96,7 @@ class LoginRestServlet(ClientV1RestServlet):
|
|||
self.jwt_enabled = hs.config.jwt_enabled
|
||||
self.jwt_secret = hs.config.jwt_secret
|
||||
self.jwt_algorithm = hs.config.jwt_algorithm
|
||||
self.saml2_enabled = hs.config.saml2_enabled
|
||||
self.cas_enabled = hs.config.cas_enabled
|
||||
self.auth_handler = self.hs.get_auth_handler()
|
||||
self.registration_handler = hs.get_registration_handler()
|
||||
|
@ -104,6 +108,9 @@ class LoginRestServlet(ClientV1RestServlet):
|
|||
flows = []
|
||||
if self.jwt_enabled:
|
||||
flows.append({"type": LoginRestServlet.JWT_TYPE})
|
||||
if self.saml2_enabled:
|
||||
flows.append({"type": LoginRestServlet.SSO_TYPE})
|
||||
flows.append({"type": LoginRestServlet.TOKEN_TYPE})
|
||||
if self.cas_enabled:
|
||||
flows.append({"type": LoginRestServlet.SSO_TYPE})
|
||||
|
||||
|
@ -474,6 +481,43 @@ class CasTicketServlet(ClientV1RestServlet):
|
|||
return user, attributes
|
||||
|
||||
|
||||
class SSORedirectServlet(RestServlet):
|
||||
PATTERNS = client_path_patterns("/login/sso/redirect")
|
||||
|
||||
def __init__(self, hs):
|
||||
super(SSORedirectServlet, self).__init__()
|
||||
self.saml2_sp_config = hs.config.saml2_sp_config
|
||||
|
||||
def on_GET(self, request):
|
||||
args = request.args
|
||||
|
||||
saml_client = Saml2Client(self.saml2_sp_config)
|
||||
reqid, info = saml_client.prepare_for_authenticate()
|
||||
|
||||
redirect_url = None
|
||||
|
||||
# Select the IdP URL to send the AuthN request to
|
||||
for key, value in info['headers']:
|
||||
if key is 'Location':
|
||||
redirect_url = value
|
||||
|
||||
if redirect_url is None:
|
||||
raise LoginError(401, "Unsuccessful SSO SAML2 redirect url response",
|
||||
errcode=Codes.UNAUTHORIZED)
|
||||
|
||||
relay_state = "/_matrix/client/r0/login"
|
||||
if b"redirectUrl" in args:
|
||||
relay_state = args[b"redirectUrl"][0]
|
||||
|
||||
url_parts = list(urllib.parse.urlparse(redirect_url))
|
||||
query = dict(urllib.parse.parse_qsl(url_parts[4]))
|
||||
query.update({"RelayState": relay_state})
|
||||
url_parts[4] = urllib.parse.urlencode(query)
|
||||
|
||||
request.redirect(urllib.parse.urlunparse(url_parts))
|
||||
finish_request(request)
|
||||
|
||||
|
||||
class SSOAuthHandler(object):
|
||||
"""
|
||||
Utility class for Resources and Servlets which handle the response from a SSO
|
||||
|
@ -549,3 +593,5 @@ def register_servlets(hs, http_server):
|
|||
if hs.config.cas_enabled:
|
||||
CasRedirectServlet(hs).register(http_server)
|
||||
CasTicketServlet(hs).register(http_server)
|
||||
if hs.config.saml2_enabled:
|
||||
SSORedirectServlet(hs).register(http_server)
|
||||
|
|
|
@ -56,6 +56,7 @@ var show_login = function() {
|
|||
}
|
||||
|
||||
if (matrixLogin.serverAcceptsSso) {
|
||||
$("#sso_form").attr("action", "/_matrix/client/r0/login/sso/redirect");
|
||||
$("#sso_flow").show();
|
||||
} else if (matrixLogin.serverAcceptsCas) {
|
||||
$("#sso_form").attr("action", "/_matrix/client/r0/login/cas/redirect");
|
||||
|
@ -79,7 +80,7 @@ var fetch_info = function(cb) {
|
|||
$.get(matrixLogin.endpoint, function(response) {
|
||||
var serverAcceptsPassword = false;
|
||||
var serverAcceptsCas = false;
|
||||
for (var i=0; i<response.flows.length; i++) {
|
||||
for (var i = 0; i < response.flows.length; i++) {
|
||||
var flow = response.flows[i];
|
||||
if ("m.login.cas" === flow.type) {
|
||||
matrixLogin.serverAcceptsCas = true;
|
||||
|
@ -121,6 +122,7 @@ matrixLogin.onLogin = function(response) {
|
|||
// clobber this function
|
||||
console.log("onLogin - This function should be replaced to proceed.");
|
||||
console.log(response);
|
||||
alert("Login successful!");
|
||||
};
|
||||
|
||||
var parseQsFromUrl = function(query) {
|
||||
|
@ -143,7 +145,7 @@ var try_token = function() {
|
|||
if (pos == -1) {
|
||||
return false;
|
||||
}
|
||||
var qs = parseQsFromUrl(window.location.href.substr(pos+1));
|
||||
var qs = parseQsFromUrl(window.location.href.substr(pos + 1));
|
||||
|
||||
var loginToken = qs.loginToken;
|
||||
|
||||
|
|
Loading…
Reference in a new issue