def test_unauthenticated_enroll_username_deny(self): """Test un-authenticated user enrolling (deny on username)""" User.objects.create(username="******", email="*****@*****.**") self.source.user_matching_mode = SourceUserMatchingModes.USERNAME_DENY # With non-existent username, enroll flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, { "username": "******", }, ) action, _ = flow_manager.get_action() self.assertEqual(action, Action.ENROLL) flow_manager.get_flow() # With username flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {"username": "******"}, ) action, _ = flow_manager.get_action() self.assertEqual(action, Action.DENY) flow_manager.get_flow()
def test_error_non_applicable_flow(self): """Test error handling when a source selected flow is non-applicable due to a policy""" self.source.user_matching_mode = SourceUserMatchingModes.USERNAME_LINK flow = Flow.objects.create(name="test", slug="test", title="test", designation=FlowDesignation.ENROLLMENT) policy = ExpressionPolicy.objects.create( name="false", expression="""ak_message("foo");return False""") PolicyBinding.objects.create( policy=policy, target=flow, order=0, ) self.source.enrollment_flow = flow self.source.save() flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {"username": "******"}, ) action, _ = flow_manager.get_action() self.assertEqual(action, Action.ENROLL) response = flow_manager.get_flow() self.assertIsInstance(response, AccessDeniedResponse) # pylint: disable=no-member self.assertEqual(response.error_message, "foo")
def test_request_id_invalid(self): """Test generated AuthNRequest with invalid request ID""" http_request = get_request("/") # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() # change the request ID http_request.session[SESSION_REQUEST_ID] = "test" http_request.session.save() # To get an assertion we need a parsed request (parsed by provider) parsed_request = AuthNRequestParser(self.provider).parse( b64encode(request.encode()).decode(), "test_state") # Now create a response and convert it to string (provider) response_proc = AssertionProcessor(self.provider, http_request, parsed_request) response = response_proc.build_response() # Now parse the response (source) http_request.POST = QueryDict(mutable=True) http_request.POST["SAMLResponse"] = b64encode( response.encode()).decode() response_parser = ResponseProcessor(self.source) with self.assertRaises(MismatchedRequestID): response_parser.parse(http_request)
def test_device_challenge_webauthn(self): """Test webauthn""" request = get_request("/") request.user = self.user webauthn_device = WebAuthnDevice.objects.create( user=self.user, public_key=bytes_to_base64url(b"qwerqwerqre"), credential_id=bytes_to_base64url(b"foobarbaz"), sign_count=0, rp_id="foo", ) challenge = get_challenge_for_device(request, webauthn_device) del challenge["challenge"] self.assertEqual( challenge, { "allowCredentials": [{ "id": "Zm9vYmFyYmF6", "type": "public-key", }], "rpId": "testserver", "timeout": 60000, "userVerification": "preferred", }, ) with self.assertRaises(ValidationError): validate_challenge_webauthn({}, request, self.user)
def test_request_attributes_invalid(self): """Test full SAML Request/Response flow, fully signed""" user = create_test_admin_user() http_request = get_request("/", user=user) # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() # Create invalid PropertyMapping scope = SAMLPropertyMapping.objects.create(name="test", saml_name="test", expression="q") self.provider.property_mappings.add(scope) # To get an assertion we need a parsed request (parsed by provider) parsed_request = AuthNRequestParser(self.provider).parse( b64encode(request.encode()).decode(), "test_state") # Now create a response and convert it to string (provider) response_proc = AssertionProcessor(self.provider, http_request, parsed_request) self.assertIn(user.username, response_proc.build_response()) events = Event.objects.filter(action=EventAction.CONFIGURATION_ERROR, ) self.assertTrue(events.exists()) self.assertEqual( events.first().context["message"], "Failed to evaluate property-mapping: name 'q' is not defined", )
def test_unauthenticated_enroll(self): """Test un-authenticated user enrolling""" flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {}) action, _ = flow_manager.get_action() self.assertEqual(action, Action.ENROLL) flow_manager.get_flow()
def setUp(self) -> None: self.user = User.objects.create(username="******") self.token = Token.objects.create( expiring=False, user=self.user, intent=TokenIntents.INTENT_APP_PASSWORD ) # To test with session we need to create a request and pass it through all middlewares self.request = get_request("/") self.request.session[SESSION_KEY_PLAN] = FlowPlan("test")
def test_unauthenticated_auth(self): """Test un-authenticated user authenticating""" UserOAuthSourceConnection.objects.create(user=get_anonymous_user(), source=self.source, identifier=self.identifier) flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {}) action, _ = flow_manager.get_action() self.assertEqual(action, Action.AUTH) flow_manager.get_flow()
def test_authenticated_link(self): """Test authenticated user linking""" UserOAuthSourceConnection.objects.create(user=get_anonymous_user(), source=self.source, identifier=self.identifier) user = User.objects.create(username="******", email="*****@*****.**") flow_manager = OAuthSourceFlowManager(self.source, get_request("/", user=user), self.identifier, {}) action, _ = flow_manager.get_action() self.assertEqual(action, Action.LINK) flow_manager.get_flow()
def test_signed_valid(self): """Test generated AuthNRequest with valid signature""" http_request = get_request("/") # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() # Now we check the ID and signature parsed_request = AuthNRequestParser(self.provider).parse( b64encode(request.encode()).decode(), "test_state") self.assertEqual(parsed_request.id, request_proc.request_id) self.assertEqual(parsed_request.relay_state, "test_state")
def test_unauthenticated_enroll_link_non_existent(self): """Test un-authenticated user enrolling (link on username), username doesn't exist""" self.source.user_matching_mode = SourceUserMatchingModes.USERNAME_LINK flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {"username": "******"}, ) action, _ = flow_manager.get_action() self.assertEqual(action, Action.ENROLL) flow_manager.get_flow()
def test_unauthenticated_enroll_email(self): """Test un-authenticated user enrolling (link on email)""" User.objects.create(username="******", email="*****@*****.**") self.source.user_matching_mode = SourceUserMatchingModes.EMAIL_LINK # Without email, deny flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {}) action, _ = flow_manager.get_action() self.assertEqual(action, Action.DENY) flow_manager.get_flow() # With email flow_manager = OAuthSourceFlowManager( self.source, get_request("/", user=AnonymousUser()), self.identifier, {"email": "*****@*****.**"}, ) action, _ = flow_manager.get_action() self.assertEqual(action, Action.LINK) flow_manager.get_flow()
def test_request_schema(self): """Test generated AuthNRequest against Schema""" http_request = get_request("/") # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() metadata = etree.fromstring(request) # nosec schema = etree.XMLSchema( etree.parse("xml/saml-schema-protocol-2.0.xsd")) # nosec self.assertTrue(schema.validate(metadata))
def test_request_attributes(self): """Test full SAML Request/Response flow, fully signed""" user = create_test_admin_user() http_request = get_request("/", user=user) # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() # To get an assertion we need a parsed request (parsed by provider) parsed_request = AuthNRequestParser(self.provider).parse( b64encode(request.encode()).decode(), "test_state") # Now create a response and convert it to string (provider) response_proc = AssertionProcessor(self.provider, http_request, parsed_request) self.assertIn(user.username, response_proc.build_response())
def test_signed_valid_detached(self): """Test generated AuthNRequest with valid signature (detached)""" http_request = get_request("/") # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") params = request_proc.build_auth_n_detached() # Now we check the ID and signature parsed_request = AuthNRequestParser(self.provider).parse_detached( params["SAMLRequest"], params["RelayState"], params["Signature"], params["SigAlg"], ) self.assertEqual(parsed_request.id, request_proc.request_id) self.assertEqual(parsed_request.relay_state, "test_state")
def test_response_schema(self): """Test generated AuthNRequest against Schema""" http_request = get_request("/") # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() # To get an assertion we need a parsed request (parsed by provider) parsed_request = AuthNRequestParser(self.provider).parse( b64encode(request.encode()).decode(), "test_state") # Now create a response and convert it to string (provider) response_proc = AssertionProcessor(self.provider, http_request, parsed_request) response = response_proc.build_response() metadata = etree.fromstring(response) # nosec schema = etree.XMLSchema( etree.parse("xml/saml-schema-protocol-2.0.xsd")) self.assertTrue(schema.validate(metadata))
def test_request_full_signed(self): """Test full SAML Request/Response flow, fully signed""" http_request = get_request("/") # First create an AuthNRequest request_proc = RequestProcessor(self.source, http_request, "test_state") request = request_proc.build_auth_n() # To get an assertion we need a parsed request (parsed by provider) parsed_request = AuthNRequestParser(self.provider).parse( b64encode(request.encode()).decode(), "test_state") # Now create a response and convert it to string (provider) response_proc = AssertionProcessor(self.provider, http_request, parsed_request) response = response_proc.build_response() # Now parse the response (source) http_request.POST = QueryDict(mutable=True) http_request.POST["SAMLResponse"] = b64encode( response.encode()).decode() response_parser = ResponseProcessor(self.source) response_parser.parse(http_request)