def testLogoutNoSLO(self): """ Tests the logout method of the OneLogin_Saml2_Auth class Case IdP no SLO endpoint. """ settings_info = self.loadSettingsJSON() del settings_info['idp']['singleLogoutService'] auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) with self.assertRaisesRegexp( OneLogin_Saml2_Error, 'The IdP does not support Single Log Out'): # The Header of the redirect produces an Exception auth.logout('http://example.com/returnto')
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) try: auth2.build_request_signature(message, relay_state) except Exception as e: self.assertIn( "Trying to sign the SAMLRequest but can't load the SP private key", e.message)
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) try: auth2.build_response_signature(message, relay_state) except Exception as e: self.assertIn( "Trying to sign the SAMLResponse but can't load the SP private key", e.message)
async def saml_login(request: Request): req = await prepare_from_fastapi_request(request) auth = OneLogin_Saml2_Auth(req, 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) # return metadata # else: # print("Error found on Metadata: %s" % (', '.join(errors))) # return "error" callback_url = auth.login() response = RedirectResponse(url=callback_url) return response
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 = 'E17GU1STzanOXxBTKjweB1DovP8aMJdj5BEy0fnGoEslKdP6hpPc3enjT/bu7I8D8QzLoir8SxZVWdUDXgIxJIEgfK5snr+jJwfc5U2HujsOa/Xb3c4swoyPcyQhcxLRDhDjPq5cQxJfYoPeElvCuI6HAD1mtdd5PS/xDvbIxuw=' 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) try: auth2.build_request_signature(message, relay_state) except Exception as e: self.assertIn( "Trying to sign the SAMLRequest but can't load the SP private key", e.message)
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='/')
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 testLogoutNoSLO(self): """ Tests the logout method of the OneLogin_Saml2_Auth class Case IdP no SLO endpoint. """ settings_info = self.loadSettingsJSON() del settings_info['idp']['singleLogoutService'] auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) try: # The Header of the redirect produces an Exception auth.logout('http://example.com/returnto') self.assertFalse(True) except Exception as e: self.assertIn('The IdP does not support Single Log Out', e.message)
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()) try: auth.process_response() self.assertFalse(True) except Exception as e: self.assertIn('SAML Response not found', e.message) self.assertEqual(auth.get_errors(), ['invalid_binding'])
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 wrapper(): app = flask.current_app saml_app_extension = app.extensions.setdefault('saml', {}) saml_settings = saml_app_extension.get(key) if not saml_settings: settings_dict = settings.get_saml_settings(app, idp=idp_enabled) saml_settings = OneLogin_Saml2_Settings( settings_dict, sp_validation_only=not idp_enabled) saml_app_extension[key] = saml_settings logger.debug('SAML Metadata Settings ({}): \n{}'.format( key, settings_dict)) req = _prepare_flask_request(app.config) auth = OneLogin_Saml2_Auth(req, saml_settings) return func(auth)
def testRedirectTowithUrl(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 with url parameter """ request_data = self.get_request() relay_state = 'http://sp.example.com' url_2 = 'http://sp2.example.com' request_data['get_data']['RelayState'] = relay_state auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON()) target_url = auth.redirect_to(url_2) self.assertEqual(target_url, url_2)
def post(self): if "onelogin" not in current_app.config.get("ACTIVE_PROVIDERS"): return "Onelogin is not enabled in the config. See the ACTIVE_PROVIDERS section.", 404 auth = OneLogin_Saml2_Auth(self.req, current_app.config.get("ONELOGIN_SETTINGS")) self.reqparse.add_argument('return_to', required=False, default=current_app.config.get('WEB_PATH')) self.reqparse.add_argument('acs', required=False) self.reqparse.add_argument('sls', required=False) args = self.reqparse.parse_args() return_to = args['return_to'] if args['acs'] != None: # valids the SAML response and checks if successfully authenticated if self._consumer(auth): email = auth.get_attribute(current_app.config.get("ONELOGIN_EMAIL_FIELD"))[0] user = User.query.filter(User.email == email).first() # if we get an sso user create them an account if not user: user = User( email=email, active=True, role=current_app.config.get('ONELOGIN_DEFAULT_ROLE') # profile_picture=profile.get('thumbnailPhotoUrl') ) db.session.add(user) db.session.commit() db.session.refresh(user) # Tell Flask-Principal the identity changed identity_changed.send(current_app._get_current_object(), identity=Identity(user.id)) login_user(user) db.session.commit() db.session.refresh(user) self_url = OneLogin_Saml2_Utils.get_self_url(self.req) if 'RelayState' in request.form and self_url != request.form['RelayState']: return redirect(auth.redirect_to(request.form['RelayState']), code=302) else: return redirect(current_app.config.get('BASE_URL'), code=302) else: return dict(message='OneLogin authentication failed.'), 403 elif args['sls'] != None: return dict(message='OneLogin SLS not implemented yet.'), 405 else: return redirect(auth.login(return_to=return_to))
def acs(request, idp_slug): idp = get_object_or_404(IdP, slug=idp_slug, is_active=True) if request.POST.get("RelayState"): # Login with state relayed from our application. state = signing.loads(request.POST["RelayState"], max_age=300) else: # IdP-initiated login. state = {"test": False, "verify": False, "redir": ""} saml = OneLogin_Saml2_Auth(idp.prepare_request(request), old_settings=idp.settings) saml.process_response() errors = saml.get_errors() if errors: return render( request, "sp/error.html", {"idp": idp, "state": state, "errors": errors, "reason": saml.get_last_error_reason()}, status=500, ) else: if state.get("test", False): attrs = [] for saml_attr, value in saml.get_attributes().items(): attr, created = idp.attributes.get_or_create(saml_attribute=saml_attr) attrs.append((attr, "; ".join(value))) return render( request, "sp/test.html", {"idp": idp, "attrs": attrs, "nameid": saml.get_nameid(), "nameid_format": saml.get_nameid_format()}, ) elif state.get("verify", False): user = idp.authenticate(request, saml) if user == request.user: return redirect(idp.get_login_redirect(state.get("redir"))) else: return render( request, "sp/unauth.html", {"nameid": idp.get_nameid(saml), "idp": idp, "verify": True}, status=401 ) else: user = idp.authenticate(request, saml) if user: idp.login(request, user, saml) idp.last_login = timezone.now() idp.save(update_fields=("last_login",)) return redirect(idp.get_login_redirect(state.get("redir"))) else: return render( request, "sp/unauth.html", {"nameid": idp.get_nameid(saml), "idp": idp, "verify": False}, status=401 )
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: """ auth = OneLogin_Saml2_Auth( req, custom_base_path=saml_path ) return auth
def get_saml_auth(self, request): saml_request = dict(SamlSettings.get_request_settings()) # Update not existing keys saml_request['https'] = saml_request.get( 'https', 'on' if request.is_secure() else 'off') saml_request['http_host'] = saml_request.get('http_host', request.META['HTTP_HOST']) saml_request['script_name'] = saml_request.get( 'script_name', request.META['PATH_INFO']) saml_request['server_port'] = saml_request.get( 'server_port', request.META['SERVER_PORT']) # add get and post data saml_request['get_data'] = request.GET.copy() saml_request['post_data'] = request.POST.copy() return saml_request, OneLogin_Saml2_Auth(saml_request, SamlSettings.get())
def logout(request): """Kick off a SAML logout request.""" req = prepare_django_request(request) saml_auth = OneLogin_Saml2_Auth(req, old_settings=settings.ONELOGIN_SAML_SETTINGS) name_id = request.session.get('samlNameId', None) session_index = request.session.get('samlSessionIndex', None) name_id_format = request.session.get('samlNameIdFormat', None) name_id_nq = request.session.get('samlNameIdNameQualifier', None) name_id_spnq = request.session.get('samlNameIdSPNameQualifier', None) auth.logout(request) url = saml_auth.logout( name_id=name_id, session_index=session_index, nq=name_id_nq, name_id_format=name_id_format, spnq=name_id_spnq, return_to=OneLogin_Saml2_Utils.get_self_url(req) + settings.SAML_LOGOUT_REDIRECT ) request.session['LogoutRequestID'] = saml_auth.get_last_request_id() return HttpResponseRedirect(url)
def login(request, test=False, verify=False, **kwargs): idp = get_request_idp(request, **kwargs) saml = OneLogin_Saml2_Auth(idp.prepare_request(request), old_settings=idp.settings) reauth = verify or "reauth" in request.GET state = signing.dumps({ "test": test, "verify": verify, "redir": request.GET.get(REDIRECT_FIELD_NAME, ""), }) # When verifying, we want to pass the (unmapped) SAML nameid, stored in the session. # TODO: do we actually want UPN here, or some other specified mapped field? At least # Auth0 is pre-populating the email field with nameid, which is not what we want. nameid = get_session_nameid(request) if verify else None return redirect( saml.login(state, force_authn=reauth, name_id_value_req=nameid))
def init_saml_auth(req): # load based on production information. saml_dir = os.path.abspath( os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'saml')) saml_file = os.path.join(saml_dir, settings.SAML_SETTINGS) json_data_file = open(saml_file, 'r') settings_data = json.load(json_data_file) json_data_file.close() # create auth object with required settings. auth = OneLogin_Saml2_Auth(req, settings_data) # return it return auth, settings_data
def _saml_auth(self, req_dict=None): """ Instantiate a OneLogin_Saml2_Auth object from the current request data (or from req_dict, if given). :param req_dict: A dict containing request information, optional. :type req_dict: dict :returns: a SAML Auth object :rtype: onelogin.saml2.auth.OneLogin_Saml2_Auth """ if req_dict is None: req_dict = self._saml_req_dict_from_request() auth = OneLogin_Saml2_Auth(req_dict, self.saml_config) return auth
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 _init_saml_request(self): tmpl = get_template('saml_settings.json') config = tmpl.render( strict=str(self.dbconfig.get('strict', self.ns, True)).lower(), debug=str(self.dbconfig.get('debug', self.ns, False)).lower(), sp_entity_id=self.dbconfig.get('sp_entity_id', self.ns), sp_acs=self.dbconfig.get('sp_acs', self.ns), sp_sls=self.dbconfig.get('sp_sls', self.ns), idp_entity_id=self.dbconfig.get('idp_entity_id', self.ns), idp_ssos=self.dbconfig.get('idp_ssos', self.ns), idp_sls=self.dbconfig.get('idp_sls', self.ns), idp_x509cert=self.dbconfig.get('idp_x509cert', self.ns) ) auth = OneLogin_Saml2_Auth(self.req, json.loads(config)) auth.set_strict(False) return auth
def testGetLastErrorReason(self): """ Tests the get_last_error_reason method of the OneLogin_Saml2_Auth class Case Invalid Response """ request_data = self.get_request() message = self.file_contents( join(self.data_path, 'responses', 'response1.xml.base64')) del request_data['get_data'] request_data['post_data'] = {'SAMLResponse': message} auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON()) auth.process_response() self.assertEqual( auth.get_last_error_reason(), 'Signature validation failed. SAML Response rejected')
def _prepare_saml_auth(request): saml_setting = OneLogin_Saml2_Settings( custom_base_path=settings.SAML_FOLDER) metadata = saml_setting.get_sp_data() saml_server_url = metadata['assertionConsumerService']['url'] parsed_saml_server_url = urlparse(saml_server_url) req = { 'https': 'on' if parsed_saml_server_url.scheme == 'https' else 'off', 'http_host': parsed_saml_server_url.hostname, 'script_name': parsed_saml_server_url.path.split('/')[0], 'server_port': parsed_saml_server_url.port, 'get_data': request.GET.copy(), 'lowercase_urlencoding': True, 'post_data': request.POST.copy(), } auth = OneLogin_Saml2_Auth(req, custom_base_path=settings.SAML_FOLDER) return auth
def _create_auth_object(self, db, idp_entity_id): """Creates and initializes an OneLogin_Saml2_Auth object :param db: Database session :type db: sqlalchemy.orm.session.Session :param idp_entity_id: IdP's entityID :type idp_entity_id: string :return: OneLogin_Saml2_Auth object :rtype: OneLogin_Saml2_Auth """ request_data = self._get_request_data() settings = self._configuration.get_settings(db, idp_entity_id) auth = OneLogin_Saml2_Auth(request_data, old_settings=settings) return auth
def testProcessSLORequestDeletingSession(self): """ Tests the process_slo method of the OneLogin_Saml2_Auth class Case Valid Logout Request, validating that the local session is deleted, a LogoutResponse is created and a redirection executed """ settings_info = self.loadSettingsJSON() request_data = self.get_request() message = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request_deflated.xml.base64')) # In order to avoid the destination problem plain_message = OneLogin_Saml2_Utils.decode_base64_and_inflate(message) current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) plain_message = plain_message.replace( 'http://stuff.com/endpoints/endpoints/sls.php', current_url) message = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message) request_data['get_data']['SAMLRequest'] = message # FIXME # if (!isset($_SESSION)) { # $_SESSION = array(); # } # $_SESSION['samltest'] = true; auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_info) auth.set_strict(True) target_url = auth.process_slo(True) parsed_query = parse_qs(urlparse(target_url)[4]) slo_url = settings_info['idp']['singleLogoutService']['url'] self.assertIn(slo_url, target_url) self.assertIn('SAMLResponse', parsed_query) self.assertNotIn('RelayState', parsed_query) # FIXME // Session is not alive # $this->assertFalse(isset($_SESSION['samltest'])); # $_SESSION['samltest'] = true; auth.set_strict(True) target_url_2 = auth.process_slo(True) target_url_2 = auth.process_slo(True) parsed_query_2 = parse_qs(urlparse(target_url_2)[4]) slo_url = settings_info['idp']['singleLogoutService']['url'] self.assertIn(slo_url, target_url_2) self.assertIn('SAMLResponse', parsed_query_2) self.assertNotIn('RelayState', parsed_query_2)
def _create_saml_auth(self, idp, remove_signature_from_get=False): """ Добавляет возможность удалить 'Signature' из параметров, https://github.com/wfmexpert/wfmportal/issues/1111 """ get_data = self.strategy.request_get() if remove_signature_from_get: get_data.pop('Signature', None) 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': get_data, 'post_data': self.strategy.request_post(), } return OneLogin_Saml2_Auth(request_info, config)
def prepare_auth_request(request, saml_config): """Helper function to prepare authenitcation request. """ if settings.DEBUG: server_port = '5050' else: server_port = '443' saml_request = { 'https': 'on' if request.is_secure() else 'off', 'http_host': request.META['HTTP_HOST'], 'script_name': request.META['PATH_INFO'], 'server_port': server_port, 'get_data': request.GET.copy(), 'post_data': request.POST.copy() } return OneLogin_Saml2_Auth(saml_request, saml_config)
def testLogin(self): """ Tests the login method of the OneLogin_Saml2_Auth class Case Login with no parameters. An AuthnRequest is built an redirect executed """ settings_info = self.loadSettingsJSON() 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]) sso_url = settings_info['idp']['singleSignOnService']['url'] self.assertIn(sso_url, target_url) self.assertIn('SAMLRequest', parsed_query) self.assertIn('RelayState', parsed_query) hostname = OneLogin_Saml2_Utils.get_self_host(request_data) self.assertIn(u'http://%s/index.html' % hostname, parsed_query['RelayState'])
def testLogoutWithRelayState(self): """ Tests the logout method of the OneLogin_Saml2_Auth class Case Logout with relayState. A logout Request with a the RelayState in the assertion is built and redirect executed """ settings_info = self.loadSettingsJSON() auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info) relay_state = 'http://sp.example.com' target_url = auth.logout(relay_state) parsed_query = parse_qs(urlparse(target_url)[4]) slo_url = settings_info['idp']['singleLogoutService']['url'] self.assertIn(slo_url, target_url) self.assertIn('SAMLRequest', parsed_query) self.assertIn('RelayState', parsed_query) self.assertIn(relay_state, parsed_query['RelayState'])