def test_is_valid_simple(self): encoded_response = base64.b64encode(test_response) fake_signature = 'foo signature' res = Response( response=encoded_response, signature='foo signature', ) def fake_clock(): return datetime(2004, 12, 05, 9, 18, 45, 462796) private_key_file = "/tmp/tes.txt" idp_cert_filename = "/tmp/junk.txt" fake_verifier = fudge.Fake( 'verifier', callable=True, ) fake_verifier.times_called(1) fake_verifier.with_args(res._document, fake_signature, idp_cert_filename, private_key_file) fake_verifier.returns((True, "<xml></xml>")) msg = res.is_valid( idp_cert_filename, private_key_file, _clock=fake_clock, _verifier=fake_verifier, ) eq(msg, True)
def do_POST(self): """Serve a POST request.""" if not self.path == self.saml_post_path: self._bad_request() return length = int(self.headers['Content-Length']) data = self.rfile.read(length) query = urlparse.parse_qs(data) res = Response( query['SAMLResponse'].pop(), self.settings['idp_cert_fingerprint'], ) valid = res.is_valid() name_id = res.name_id if valid: msg = 'The identity of {name_id} has been verified'.format( name_id=name_id, ) self._serve_msg(200, msg) else: msg = '{name_id} is not authorized to use this resource'.format( name_id=name_id, ) self._serve_msg(401, msg)
def logged_in(): # IDPorten redirects to this URL if all ok with login app.logger.info("User logged in via ID-porten: request.values=%s", request.values) SAMLResponse = request.values['SAMLResponse'] res = IdpResponse( SAMLResponse, "TODO: remove signature parameter" ) # Decrypt response from IDPorten with our private key, and make sure that the response is valid # (it was encrypted with same key) valid = res.is_valid(app.idporten_settings["idp_cert_file"], app.idporten_settings["private_key_file"]) if valid: national_id_number = res.get_decrypted_assertion_attribute_value("uid")[0] idporten_parameters = { "session_index": res.get_session_index(), "name_id": res.name_id } auth_user = authentication.login_idporten_user_by_private_id(national_id_number, idporten_parameters) login_user(auth_user, remember=True) # Force the user to fill in the profile if unregistered if not auth_user.is_registered(): app.logger.info("Logged in: %s Uregistrert bruker (%s)", datetime.now().isoformat(), national_id_number[:6]) response = make_response(redirect("/profile")) else: app.logger.info("Logged in: %s %s %s (%s)", datetime.now().isoformat(), auth_user.first_name, auth_user.last_name, national_id_number[:6]) # Check if the user wants to redirect to a specific page redirect_target = get_redirect_target_from_cookie(request) response = make_response(redirect(redirect_target or request.args.get('next') or '/')) invalidate_redirect_target_cookie(response) set_cookie(response, 'auth_token', make_auth_token(auth_user.user_id)) return response else: abort(404, 'Ugyldig innlogging.')
def logged_in(): app.logger.info("User logged in via ID-porten: request.values=%s", request.values) SAMLResponse = request.values['SAMLResponse'] res = IdpResponse( SAMLResponse, "TODO: remove signature parameter" ) valid = res.is_valid(settings["idp_cert_file"], settings["private_key_file"]) if valid: national_id_number = res.get_decrypted_assertion_attribute_value("uid")[0] idporten_parameters = { "session_index": res.get_session_index(), "name_id": res.name_id } auth_user = authentication.login_user_by_private_id(national_id_number, idporten_parameters) # Force the user to fill in the profile if unregistered if not auth_user.is_registered(): app.logger.info("Logged in: %s Uregistrert bruker (%s)", datetime.now().isoformat(), national_id_number[:6]) response = make_response(redirect("/profile")) else: app.logger.info("Logged in: %s %s %s (%s)", datetime.now().isoformat(), auth_user.first_name, auth_user.last_name, national_id_number[:6]) # Check if the user wants to redirect to a specific page redirect_target = request.cookies.get("redirect_target", None) if not redirect_target or not is_safe_url(redirect_target): redirect_target = None response = make_response( redirect(redirect_target or request.args.get('next') or '/')) # Invalidate the redirect cookie by giving it a past expiry date response.set_cookie("redirect_target", "", expires=0) set_cookie(response, 'auth_token', make_auth_token(auth_user.user_id)) return response else: abort(404, 'Ugyldig innlogging.')
def test_get_name_id_simple(self): encoded_response = base64.b64encode(test_response) res = Response( response=encoded_response, signature=None, ) name_id = res.name_id eq('3f7b3dcf-1674-4ecd-92c8-1544f346baf8', name_id)
def logged_in(): print "USER LOGGED IN VIA IDPORTEN" print request.values SAMLResponse = request.values['SAMLResponse'] res = Response( SAMLResponse, "TODO: remove signature parameter" ) valid = res.is_valid(settings["idp_cert_file"], settings["private_key_file"]) uid = res.get_decrypted_assertion_attribute_value("uid") name_id = res.name_id print "UID", uid print "NAME ID: ", name_id print "Session index: ", res.get_session_index() user_info["uid"] = uid user_info["name_id"] = name_id user_info["session_index"] = res.get_session_index() return render_template('home.html', decrypted = res.decrypted, uid = uid)
def test_is_valid_current_time_on_or_after(self): encoded_response = base64.b64encode(test_response) res = Response( response=encoded_response, signature=None, ) def fake_clock(): return datetime(2004, 12, 05, 9, 30, 45, 462796) msg = assert_raises( ResponseValidationError, res.is_valid, _clock=fake_clock, ) eq( str(msg), ('There was a problem validating the response: Current time is ' + 'on or after NotOnOrAfter condition'), )
def test__init__(self): fake_base64 = fudge.Fake('base64') fake_base64.remember_order() decode = fake_base64.expects('b64decode') decode.with_args('foo response') decode.returns('foo decoded response') fake_etree = fudge.Fake('etree') fake_etree.remember_order() from_string = fake_etree.expects('fromstring') from_string.with_args('foo decoded response') from_string.returns('foo document') res = Response( response='foo response', signature='foo signature', _base64=fake_base64, _etree=fake_etree, ) eq(res._document, 'foo document') eq(res._signature, 'foo signature')
def logged_in(): print "USER LOGGED IN VIA IDPORTEN" print request.values SAMLResponse = request.values['SAMLResponse'] res = Response(SAMLResponse, "TODO: remove signature parameter") valid = res.is_valid(settings["idp_cert_file"], settings["private_key_file"]) uid = res.get_decrypted_assertion_attribute_value("uid") name_id = res.name_id print "UID", uid print "NAME ID: ", name_id print "Session index: ", res.get_session_index() user_info["uid"] = uid user_info["name_id"] = name_id user_info["session_index"] = res.get_session_index() return render_template('home.html', decrypted=res.decrypted, uid=uid)
def test_is_valid_not_on_or_after_missing(self): response = """<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_2" InResponseTo="identifier_1" Version="2.0" IssueInstant="2004-12-05T09:22:05Z" Destination="https://sp.example.com/SAML2/SSO/POST"> <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_3" Version="2.0" IssueInstant="2004-12-05T09:22:05Z"> <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">foo signature</ds:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient"> 3f7b3dcf-1674-4ecd-92c8-1544f346baf8 </saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="identifier_1" Recipient="https://sp.example.com/SAML2/SSO/POST" NotOnOrAfter="2004-12-05T09:27:05Z"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2004-12-05T09:27:05Z"> <saml:AudienceRestriction> <saml:Audience>https://sp.example.com/SAML2</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2004-12-05T09:22:00Z" SessionIndex="identifier_3"> <saml:AuthnContext> <saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response> """ encoded_response = base64.b64encode(response) res = Response( response=encoded_response, signature=None, ) msg = assert_raises( ResponseConditionError, res.is_valid, ) eq( str(msg), ('There was a problem validating a condition: Did not find ' + 'NotOnOrAfter condition'), )
def test_get_name_id_none(self): response = """<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_2" InResponseTo="identifier_1" Version="2.0" IssueInstant="2004-12-05T09:22:05Z" Destination="https://sp.example.com/SAML2/SSO/POST"> <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="identifier_3" Version="2.0" IssueInstant="2004-12-05T09:22:05Z"> <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature> <saml:Subject> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="identifier_1" Recipient="https://sp.example.com/SAML2/SSO/POST" NotOnOrAfter="2004-12-05T09:27:05Z"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2004-12-05T09:17:05Z" NotOnOrAfter="2004-12-05T09:27:05Z"> <saml:AudienceRestriction> <saml:Audience>https://sp.example.com/SAML2</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2004-12-05T09:22:00Z" SessionIndex="identifier_3"> <saml:AuthnContext> <saml:AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport </saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> </saml:Assertion> </samlp:Response> """ encoded_response = base64.b64encode(response) res = Response( response=encoded_response, signature=None, ) msg = assert_raises( ResponseNameIDError, res._get_name_id, ) eq( str(msg), ('There was a problem getting the name ID: Did not find a name ' + 'ID'), )