def _create_saml_auth(self, idp): """Get an instance of OneLogin_Saml2_Auth""" config = self.generate_saml_config(idp) request_info = { 'https': 'on' if self.strategy.request_is_secure() else 'off', 'http_host': self.strategy.request_host(), 'script_name': self.strategy.request_path(), 'server_port': self.strategy.request_port(), 'get_data': self.strategy.request_get(), 'post_data': self.strategy.request_post(), } return OneLogin_Saml2_Auth(request_info, config)
async def load_login_config(request: Request) -> LoginConfiguration: if ask_sso_enabled() and ask_saml2_enabled(): from watchmen_rest_doll.sso.saml.saml_helper import prepare_from_fastapi_request # noinspection PyPackageRequirements from onelogin.saml2.auth import OneLogin_Saml2_Auth req = await prepare_from_fastapi_request(request) auth = OneLogin_Saml2_Auth(req, ask_saml2_settings()) callback_url = auth.login() return LoginConfiguration(method=SSOTypes.SAML2, url=callback_url) else: return LoginConfiguration(method=SSOTypes.DOLL)
def render_GET(self, request): request.setHeader(b"content-type", b"text/plain") req = self._prepare_from_twisted_request(request) auth = OneLogin_Saml2_Auth(req, old_settings=self.settings) saml_settings = auth.get_settings() metadata = saml_settings.get_sp_metadata() errors = saml_settings.validate_metadata(metadata) if len(errors) == 0: content = metadata else: content = "Error found on Metadata: %s" % (', '.join(errors)) return content.encode("ascii")
def POST(self): SAML_PATH = config_get('saml', 'config_path') request = ctx.env data = dict(param_input()) req = prepare_webpy_request(request, data) auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH) auth.process_response() errors = auth.get_errors() if not errors: if auth.is_authenticated(): setcookie('saml-nameid', value=auth.get_nameid(), path='/')
def metadata(): auth = OneLogin_Saml2_Auth(prepare_saml_request(request), current_app.config["SAML"]) metadata = auth.get_settings().get_sp_metadata() errors = auth.get_settings().validate_metadata(metadata) if len(errors) == 0: resp = make_response(metadata, 200) resp.headers['Content-Type'] = 'text/xml' else: resp = make_response(', '.join(errors), 500) return resp
def GET(self, id): settings = self.user_manager.get_auth_method(id).get_settings() auth = OneLogin_Saml2_Auth(prepare_request(settings), settings) metadata = auth.get_settings().get_sp_metadata() errors = auth.get_settings().validate_metadata(metadata) if len(errors) == 0: web.header('Content-Type', 'text/xml') return metadata else: web.ctx.status = "500 Internal Server Error" return ', '.join(errors)
def GET(self): global settings auth = OneLogin_Saml2_Auth(prepare_request(), settings) metadata = auth.get_settings().get_sp_metadata() errors = auth.get_settings().validate_metadata(metadata) if len(errors) == 0: web.header('Content-Type', 'text/xml') return metadata else: web.ctx.status = "500 Internal Server Error" return ', '.join(errors)
def logout(request, **kwargs): idp = get_request_idp(request, **kwargs) redir = idp.get_logout_redirect(request.GET.get(REDIRECT_FIELD_NAME)) saml = OneLogin_Saml2_Auth(idp.prepare_request(request), old_settings=idp.settings) if saml.get_slo_url() and idp.logout_triggers_slo: # If the IdP supports SLO, send it a logout request (it will call our SLO). return redirect(saml.logout(redir)) else: # Handle the logout "locally", i.e. log out via django.contrib.auth by default. idp.logout(request) return redirect(redir)
def testGetSessionIndex(self): """ Tests the get_session_index method of the OneLogin_Saml2_Auth class """ settings_info = self.loadSettingsJSON() auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) self.assertIsNone(auth.get_session_index()) request_data = self.get_request() message = self.file_contents( join(self.data_path, 'responses', 'valid_response.xml.base64')) del request_data['get_data'] request_data['post_data'] = {'SAMLResponse': message} auth2 = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON()) self.assertIsNone(auth2.get_session_index()) auth2.process_response() self.assertEqual('_6273d77b8cde0c333ec79d22a9fa0003b9fe2d75cb', auth2.get_session_index())
def init_saml_auth(req, config): """Prepare SAML request :param req: :class:`microkubes.security.chain.Request`, wrapped HTTP Request. :param config: ``dict``, SAML config :returns: an instance of OneLogin_Saml2_Auth """ settingsSAML = OneLogin_Saml2_Settings(settings=config) auth = OneLogin_Saml2_Auth(req, old_settings=settingsSAML) return auth
def testProcessNoResponse(self): """ Tests the process_response method of the OneLogin_Saml2_Auth class Case No Response, An exception is throw """ auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=self.loadSettingsJSON()) with self.assertRaisesRegexp(OneLogin_Saml2_Error, 'SAML Response not found'): auth.process_response() self.assertEqual(auth.get_errors(), ['invalid_binding'])
def testProcessNoSLO(self): """ Tests the process_slo method of the OneLogin_Saml2_Auth class Case No Message, An exception is throw """ auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=self.loadSettingsJSON()) try: auth.process_slo(True) except Exception as e: self.assertIn('SAML LogoutRequest/LogoutResponse not found', e.message) self.assertEqual(auth.get_errors(), ['invalid_binding'])
async def saml_login(request: Request): req = await prepare_saml_from_fastapi_request(request) auth = OneLogin_Saml2_Auth(req, self.saml_settings) # saml_settings = auth.get_settings() # metadata = saml_settings.get_sp_metadata() # errors = saml_settings.validate_metadata(metadata) # if len(errors) == 0: # print(metadata) # else: # print("Error found on Metadata: %s" % (', '.join(errors))) callback_url = auth.login() response = RedirectResponse(url=callback_url) return response
def init_saml_auth( request, provider_key: str) -> Tuple[OneLogin_Saml2_Auth, dict, dict]: """ Gets the SAML provider settings and returns a prepared SAML request and OneLogin Auth object """ saml_req = prepare_django_request(request) provider_settings, user_map = get_provider_settings(saml_req, provider_key) saml_req["lowercase_urlencoding"] = provider_settings.get( "lowercase_urlencoding", False) saml_req["idp_initiated_auth"] = provider_settings.get( "idp_initiated_auth", True) auth = OneLogin_Saml2_Auth(saml_req, provider_settings) return auth, saml_req, user_map
def testLoginSetNameIDPolicy(self): """ Tests the login method of the OneLogin_Saml2_Auth class Case Logout with no parameters. A AuthN Request is built with and without NameIDPolicy """ settings_info = self.loadSettingsJSON() return_to = u'http://example.com/returnto' sso_url = settings_info['idp']['singleSignOnService']['url'] auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) target_url = auth.login(return_to) parsed_query = parse_qs(urlparse(target_url)[4]) sso_url = settings_info['idp']['singleSignOnService']['url'] self.assertIn(sso_url, target_url) self.assertIn('SAMLRequest', parsed_query) request = OneLogin_Saml2_Utils.decode_base64_and_inflate( parsed_query['SAMLRequest'][0]) self.assertIn('<samlp:NameIDPolicy', request) auth_2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) target_url_2 = auth_2.login(return_to, False, False, True) parsed_query_2 = parse_qs(urlparse(target_url_2)[4]) self.assertIn(sso_url, target_url_2) self.assertIn('SAMLRequest', parsed_query_2) request_2 = OneLogin_Saml2_Utils.decode_base64_and_inflate( parsed_query_2['SAMLRequest'][0]) self.assertIn('<samlp:NameIDPolicy', request_2) auth_3 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) target_url_3 = auth_3.login(return_to, False, False, False) parsed_query_3 = parse_qs(urlparse(target_url_3)[4]) self.assertIn(sso_url, target_url_3) self.assertIn('SAMLRequest', parsed_query_3) request_3 = OneLogin_Saml2_Utils.decode_base64_and_inflate( parsed_query_3['SAMLRequest'][0]) self.assertNotIn('<samlp:NameIDPolicy', request_3)
def testRedirectTo(self): """ Tests the redirect_to method of the OneLogin_Saml2_Auth class (phpunit raises an exception when a redirect is executed, the exception is catched and we check that the targetURL is correct) Case redirect without url parameter """ request_data = self.get_request() relay_state = 'http://sp.example.com' request_data['get_data']['RelayState'] = relay_state auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON()) target_url = auth.redirect_to() self.assertEqual(target_url, relay_state)
def testGetSettings(self): """ Tests the get_settings method of the OneLogin_Saml2_Auth class Build a OneLogin_Saml2_Settings object with a setting array and compare the value returned from the method of the auth object """ settings_info = self.loadSettingsJSON() settings = OneLogin_Saml2_Settings(settings_info) auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) auth_settings = auth.get_settings() self.assertEqual(settings.get_sp_data(), auth_settings.get_sp_data())
def callback(): auth = OneLogin_Saml2_Auth(prepare_saml_request(request), current_app.config["SAML"]) auth.process_response() errors = auth.get_errors() if len(errors) == 0: auth_attrs = auth.get_attributes() mappings = current_app.config["SAML"]["attributes"] attrs = { key: auth_attrs[mapping][0] for key, mapping in mappings.items() } user = User.query.get(attrs["uid"]) if not user: user = User(id=attrs["uid"], name=attrs["sn"], first_name=attrs["givenName"], email=attrs["email"]) db.session.add(user) db.session.commit() session["logged_in"] = True session["user_id"] = user.id session["first_name"] = user.first_name session["name"] = user.name session["email"] = user.email session["admin"] = user.admin # To do : create function to avoid duplication with pub_page '/moderate' if user.admin: chans = get_moderate_channels_for_user(user) pubs_per_chan = (db.session.query(Publishing).filter( (Publishing.channel_id == c.id) & (Publishing.state == 0)) for c in chans) flattened_list_pubs = [y for x in pubs_per_chan for y in x] session["notification"] = len(flattened_list_pubs) else: session["notification"] = 0 # Redirect to desired url self_url = OneLogin_Saml2_Utils.get_self_url( prepare_saml_request(request)) if 'RelayState' in request.form and self_url != request.form[ 'RelayState']: return redirect(auth.redirect_to(request.form['RelayState'])) else: return make_response(", ".join(errors), 500) return make_response("saml_acs_error", 500)
def init_saml_auth(): parsed_url = urlparse(request.url) request_data = { "https": "on" if request.scheme == "https" else "off", "http_host": request.host, "server_port": parsed_url.port, "script_name": request.path, "get_data": request.args.copy(), "post_data": request.form.copy(), "query_string": request.query_string } auth = OneLogin_Saml2_Auth(request_data, custom_base_path=get_env("INFRABOX_ACCOUNT_SAML_SETTINGS_PATH")) return auth
def login(request): """Kick off a SAML login request.""" req = prepare_django_request(request) saml_auth = OneLogin_Saml2_Auth( req, old_settings=settings.ONELOGIN_SAML_SETTINGS) if 'next' in request.GET: redirect_to = OneLogin_Saml2_Utils.get_self_url( req) + request.GET['next'] else: redirect_to = OneLogin_Saml2_Utils.get_self_url( req) + settings.SAML_LOGIN_REDIRECT url = saml_auth.login(redirect_to) request.session['AuthNRequestID'] = saml_auth.get_last_request_id() return HttpResponseRedirect(url)
def testLoginWithUnicodeSettings(self): """ Tests the login method of the OneLogin_Saml2_Auth class Case Login with unicode settings. An AuthnRequest is built an redirect executed """ settings_info = self.loadSettingsJSON('settings6.json') request_data = self.get_request() auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_info) target_url = auth.login() parsed_query = parse_qs(urlparse(target_url)[4]) hostname = OneLogin_Saml2_Utils.get_self_host(request_data) self.assertIn(u'http://%s/index.html' % hostname, parsed_query['RelayState'])
def testBuildRequestSignature(self): """ Tests the build_request_signature method of the OneLogin_Saml2_Auth """ settings = self.loadSettingsJSON() message = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request_deflated.xml.base64')) relay_state = 'http://relaystate.com' auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings) signature = auth.build_request_signature(message, relay_state) valid_signature = 'Pb1EXAX5TyipSJ1SndEKZstLQTsT+1D00IZAhEepBM+OkAZQSToivu3njgJu47HZiZAqgXZFgloBuuWE/+GdcSsRYEMkEkiSDWTpUr25zKYLJDSg6GNo6iAHsKSuFt46Z54Xe/keYxYP03Hdy97EwuuSjBzzgRc5tmpV+KC7+a0=' self.assertEqual(signature, valid_signature) settings['sp']['privatekey'] = '' settings['custom_base_path'] = u'invalid/path/' auth2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings) with self.assertRaisesRegexp( OneLogin_Saml2_Error, "Trying to sign the SAMLRequest but can't load the SP private key" ): auth2.build_request_signature(message, relay_state)
def testGetLastLogoutRequest(self): settings = self.loadSettingsJSON() auth = OneLogin_Saml2_Auth( { 'http_host': 'localhost', 'script_name': 'thing' }, old_settings=settings) auth.logout() expectedFragment = ( ' Destination="http://idp.example.com/SingleLogoutService.php">\n' ' <saml:Issuer>http://stuff.com/endpoints/metadata.php</saml:Issuer>\n' ' <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" SPNameQualifier="http://stuff.com/endpoints/metadata.php">http://idp.example.com/</saml:NameID>\n' ' \n </samlp:LogoutRequest>') self.assertIn(expectedFragment, auth.get_last_request_xml()) request = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request.xml')) message = OneLogin_Saml2_Utils.deflate_and_base64_encode(request) message_wrapper = {'get_data': {'SAMLRequest': message}} auth = OneLogin_Saml2_Auth(message_wrapper, old_settings=settings) auth.process_slo() self.assertEqual(request, auth.get_last_request_xml())
def init_saml_auth(req, saml_path): """ Init SAML authentication for remote application. Args: req(dict): saml_path(str): The path to the configuration files for python3-saml. Returns: The SAML SP instance. """ auth = OneLogin_Saml2_Auth(req, custom_base_path=saml_path) return auth
def testBuildResponseSignature(self): """ Tests the build_response_signature method of the OneLogin_Saml2_Auth """ settings = self.loadSettingsJSON() message = self.file_contents( join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64')) relay_state = 'http://relaystate.com' auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings) signature = auth.build_response_signature(message, relay_state) valid_signature = 'IcyWLRX6Dz3wHBfpcUaNLVDMGM3uo6z2Z11Gjq0/APPJaHboKGljffsgMVAGBml497yckq+eYKmmz+jpURV9yTj2sF9qfD6CwX2dEzSzMdRzB40X7pWyHgEJGIhs6BhaOt5oXEk4T+h3AczERqpVYFpL00yo7FNtyQkhZFpHFhM=' self.assertEqual(signature, valid_signature) settings['sp']['privatekey'] = '' settings['custom_base_path'] = u'invalid/path/' auth2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings) with self.assertRaisesRegexp( OneLogin_Saml2_Error, "Trying to sign the SAMLResponse but can't load the SP private key" ): auth2.build_response_signature(message, relay_state)
def callback(self, auth_storage): req = prepare_request(self._settings) input_data = web.input() auth = OneLogin_Saml2_Auth(req, self._settings) auth.process_response() errors = auth.get_errors() # Try and check if IdP is using several signature certificates # This is a limitation of python3-saml for cert in self._settings["idp"].get("additionalX509certs", []): if auth.get_last_error_reason() == "Signature validation failed. SAML Response rejected": # Change used IdP certificate logging.getLogger('inginious.webapp.plugin.auth.saml').debug("Trying another certificate...") new_settings = copy.deepcopy(self._settings) new_settings["idp"]["x509cert"] = cert # Retry processing response auth = OneLogin_Saml2_Auth(req, new_settings) auth.process_response() errors = auth.get_errors() if len(errors) == 0 and "attributes" in self._settings: attrs = auth.get_attributes() username = attrs[self._settings["attributes"]["uid"]][0] realname = attrs[self._settings["attributes"]["cn"]][0] email = attrs[self._settings["attributes"]["email"]][0] # Redirect to desired url self_url = OneLogin_Saml2_Utils.get_self_url(req) if 'RelayState' in input_data and self_url != input_data['RelayState']: redirect_url = auth.redirect_to(input_data['RelayState']) # Initialize session in user manager and update cache return (str(username), realname, email) if redirect_url == auth_storage["redir_url"] else None else: logging.getLogger('inginious.webapp.plugin.auth.saml').error("Errors while processing response : ", ", ".join(errors)) return None
def build_auth(request, saml_config): """ Construct a OneLogin_Saml2_Auth object for the current request. """ url = urlparse(options.get("system.url-prefix")) saml_request = { "https": "on" if url.scheme == "https" else "off", "http_host": url.hostname, "script_name": request.META["PATH_INFO"], "server_port": url.port, "get_data": request.GET.copy(), "post_data": request.POST.copy(), } return OneLogin_Saml2_Auth(saml_request, saml_config)
async def saml_login_callback(request: Request): req = await prepare_from_fastapi_request(request, True) auth = OneLogin_Saml2_Auth(req, saml_settings) auth.process_response() # Process IdP response errors = auth.get_errors() # This method receives an array with the errors if len(errors) == 0: if not auth.is_authenticated( ): # This check if the response was ok and the user data retrieved or not (user authenticated) return "user Not authenticated" else: return "User authenticated" else: print("Error when processing SAML Response: %s %s" % (', '.join(errors), auth.get_last_error_reason())) return "Error in callback"
def build_auth(request, saml_config): """ Construct a OneLogin_Saml2_Auth object for the current request. """ url = urlparse(options.get('system.url-prefix')) saml_request = { 'https': 'on' if url.scheme == 'https' else 'off', 'http_host': url.hostname, 'script_name': request.META['PATH_INFO'], 'server_port': url.port, 'get_data': request.GET.copy(), 'post_data': request.POST.copy() } return OneLogin_Saml2_Auth(saml_request, saml_config)
def POST(self): if not EXTRA_MODULES['onelogin']: header('X-Rucio-Auth-Token', None) return "SAML not configured on the server side." SAML_PATH = config_get('saml', 'config_path') req = prepare_saml_request(ctx.env, dict(param_input())) auth = OneLogin_Saml2_Auth(req, custom_base_path=SAML_PATH) auth.process_response() errors = auth.get_errors() if not errors: if auth.is_authenticated(): setcookie('saml-nameid', value=auth.get_nameid(), path='/')