def setup(self): self.config = { 'server_info': { 'authorization_endpoint': FB_AUTH_ENDPOINT, 'token_endpoint': 'https://graph.facebook.com/v2.5/oauth/access_token' }, 'client_secret': 'facebook_secret', 'base_url': BASE_URL, 'state_encryption_key': 'state_encryption_key', 'encryption_key': 'encryption_key', 'fields': [ 'id', 'name', 'first_name', 'last_name', 'middle_name', 'picture', 'email', 'verified', 'gender', 'timezone', 'locale', 'updated_time' ], 'authz_page': AUTHZ_PAGE, 'client_config': { 'client_id': CLIENT_ID } } self.fb_backend = FacebookBackend(None, INTERNAL_ATTRIBUTES, self.config)
def setup(self): self.config = { 'server_info': {'authorization_endpoint': FB_AUTH_ENDPOINT, 'token_endpoint': 'https://graph.facebook.com/v2.5/oauth/access_token'}, 'client_secret': 'facebook_secret', 'base_url': BASE_URL, 'state_encryption_key': 'state_encryption_key', 'encryption_key': 'encryption_key', 'fields': ['id', 'name', 'first_name', 'last_name', 'middle_name', 'picture', 'email', 'verified', 'gender', 'timezone', 'locale', 'updated_time'], 'authz_page': AUTHZ_PAGE, 'client_config': {'client_id': CLIENT_ID} } self.fb_backend = FacebookBackend(None, INTERNAL_ATTRIBUTES, self.config)
class TestFacebook: @pytest.fixture(autouse=True) def setup(self): self.config = { 'server_info': { 'authorization_endpoint': FB_AUTH_ENDPOINT, 'token_endpoint': 'https://graph.facebook.com/v2.5/oauth/access_token' }, 'client_secret': 'facebook_secret', 'base_url': BASE_URL, 'state_encryption_key': 'state_encryption_key', 'encryption_key': 'encryption_key', 'fields': [ 'id', 'name', 'first_name', 'last_name', 'middle_name', 'picture', 'email', 'verified', 'gender', 'timezone', 'locale', 'updated_time' ], 'authz_page': AUTHZ_PAGE, 'client_config': { 'client_id': CLIENT_ID } } self.fb_backend = FacebookBackend(None, INTERNAL_ATTRIBUTES, self.config) def test_register_endpoints(self): resp_map = self.fb_backend.register_endpoints() test_map = [('^facebook?(.*)$', self.fb_backend.authn_response), ('^facebook$', self.fb_backend.authn_response)] assert len(resp_map) == len( test_map), "The endpoint registration is not working!" for idx, val in enumerate(resp_map): assert val == test_map[ idx], "The endpoint registration is not working!" def test_start_auth(self): context = Context() context.path = 'facebook/sso/redirect' context.state = State() internal_request = InternalRequest(UserIdHashType.transient, 'http://localhost:8087/sp.xml') get_state = Mock() get_state.return_value = STATE resp = self.fb_backend.start_auth(context, internal_request, get_state) # assert resp.headers[0][0] == "Set-Cookie", "Not the correct return cookie" # assert len(resp.headers[0][1]) > 1, "Not the correct return cookie" resp_url = resp.message.split("?") test_url = FB_REDIRECT_URL.split("?") resp_attr = parse_qs(resp_url[1]) test_attr = parse_qs(test_url[1]) assert resp_url[0] == test_url[0] assert len(resp_attr) == len(test_attr), "Redirect url is not correct!" for key in test_attr: assert key in resp_attr, "Redirect url is not correct!" assert test_attr[key] == resp_attr[ key], "Redirect url is not correct!" def verify_callback(self, context, internal_response): assert len(FB_RESPONSE_CHECK) == len( internal_response._attributes), "Not a correct callback!" for key in internal_response._attributes: assert key in FB_RESPONSE_CHECK, "Not a correct callback!" assert FB_RESPONSE_CHECK[key] == internal_response._attributes[key], \ "Not a correct callback!" def verify_do_access_token_request(self, request_args, state, **kwargs): assert request_args[ "code"] == FB_RESPONSE_CODE, "Not a correct at request!" assert request_args["redirect_uri"] == "%s/%s" % (BASE_URL, AUTHZ_PAGE), \ "Not a correct at request!" assert request_args["state"] == STATE, "Not a correct at request!" assert state == STATE, "Not a correnct state!" return {"access_token": "fb access token"} def verify_request_fb(self, url, payload): resp = Mock() resp.text = json.dumps(FB_RESPONSE) return resp def test_authn_response(self): context = Context() context.path = 'facebook/sso/redirect' context.state = State() internal_request = InternalRequest(UserIdHashType.transient, 'http://localhost:8087/sp.xml') get_state = Mock() get_state.return_value = STATE resp = self.fb_backend.start_auth(context, internal_request, get_state) context.cookie = resp.headers[0][1] context.request = {"code": FB_RESPONSE_CODE, "state": STATE} # context.request = json.dumps(context.request) self.fb_backend.auth_callback_func = self.verify_callback tmp_consumer = self.fb_backend.get_consumer() tmp_consumer.do_access_token_request = self.verify_do_access_token_request self.fb_backend.get_consumer = Mock() self.fb_backend.get_consumer.return_value = tmp_consumer self.fb_backend.request_fb = self.verify_request_fb self.fb_backend.authn_response(context) @responses.activate def test_with_pyoidc(self): responses.add(responses.POST, "https://graph.facebook.com/v2.5/oauth/access_token", body=json.dumps({ "access_token": "qwerty", "token_type": "bearer", "expires_in": 9999999999999 }), adding_headers={"set-cookie": "TEST=testing; path=/"}, status=200, content_type='application/json') responses.add(responses.GET, "https://graph.facebook.com/v2.5/me", match_querystring=False, body=json.dumps(FB_RESPONSE), status=200, content_type='application/json') context = Context() context.path = 'facebook/sso/redirect' context.state = State() internal_request = InternalRequest(UserIdHashType.transient, 'http://localhost:8087/sp.xml') get_state = Mock() get_state.return_value = STATE resp = self.fb_backend.start_auth(context, internal_request, get_state) context.cookie = resp.headers[0][1] context.request = {"code": FB_RESPONSE_CODE, "state": STATE} self.fb_backend.auth_callback_func = self.verify_callback self.fb_backend.authn_response(context)
def create_backend(self): self.fb_backend = FacebookBackend(Mock(), INTERNAL_ATTRIBUTES, FB_CONFIG, "base_url", "facebook")
class TestFacebookBackend(object): @pytest.fixture(autouse=True) def create_backend(self): self.fb_backend = FacebookBackend(Mock(), INTERNAL_ATTRIBUTES, FB_CONFIG, "base_url", "facebook") @pytest.fixture def incoming_authn_response(self, context): context.path = 'facebook/sso/redirect' state_data = dict(state=mock_get_state.return_value) context.state[self.fb_backend.name] = state_data context.request = { "code": FB_RESPONSE_CODE, "state": mock_get_state.return_value } return context def setup_facebook_response(self): responses.add(responses.GET, "https://graph.facebook.com/v2.5/me", body=json.dumps(FB_RESPONSE), status=200, content_type='application/json') def assert_expected_attributes(self): expected_attributes = { "edupersontargetedid": [FB_RESPONSE["id"]], "surname": [FB_RESPONSE["last_name"]], "name": [FB_RESPONSE["name"]], "mail": [FB_RESPONSE["email"]], "givenname": [FB_RESPONSE["first_name"]], "gender": [FB_RESPONSE["gender"]], } context, internal_resp = self.fb_backend.auth_callback_func.call_args[ 0] assert internal_resp.attributes == expected_attributes def assert_token_request(self, request_args, state, **kwargs): assert request_args["code"] == FB_RESPONSE_CODE assert request_args["redirect_uri"] == "%s/%s" % (BASE_URL, AUTHZ_PAGE) assert request_args["state"] == mock_get_state.return_value assert state == mock_get_state.return_value def test_register_endpoints(self): url_map = self.fb_backend.register_endpoints() expected_url_map = [('^facebook$', self.fb_backend._authn_response)] assert url_map == expected_url_map def test_start_auth(self, context): context.path = 'facebook/sso/redirect' internal_request = InternalRequest(UserIdHashType.transient, 'test_requester') resp = self.fb_backend.start_auth(context, internal_request, mock_get_state) login_url = resp.message assert login_url.startswith(FB_AUTH_ENDPOINT) expected_params = { "client_id": CLIENT_ID, "state": mock_get_state.return_value, "response_type": "code", "redirect_uri": "%s/%s" % (BASE_URL, AUTHZ_PAGE) } actual_params = dict(parse_qsl(urlparse(login_url).query)) assert actual_params == expected_params @responses.activate def test_authn_response(self, incoming_authn_response): self.setup_facebook_response() mock_do_access_token_request = Mock( return_value={"access_token": "fb access token"}) self.fb_backend.consumer.do_access_token_request = mock_do_access_token_request self.fb_backend._authn_response(incoming_authn_response) assert self.fb_backend.name not in incoming_authn_response.state self.assert_expected_attributes() self.assert_token_request(**mock_do_access_token_request.call_args[1]) @responses.activate def test_entire_flow(self, context): """Tests start of authentication (incoming auth req) and receiving auth response.""" responses.add(responses.POST, "https://graph.facebook.com/v2.5/oauth/access_token", body=json.dumps({ "access_token": "qwerty", "token_type": "bearer", "expires_in": 9999999999999 }), status=200, content_type='application/json') self.setup_facebook_response() context.path = 'facebook/sso/redirect' internal_request = InternalRequest(UserIdHashType.transient, 'test_requester') self.fb_backend.start_auth(context, internal_request, mock_get_state) context.request = { "code": FB_RESPONSE_CODE, "state": mock_get_state.return_value } self.fb_backend._authn_response(context) assert self.fb_backend.name not in context.state self.assert_expected_attributes()
class TestFacebookBackend(object): @pytest.fixture(autouse=True) def create_backend(self): self.fb_backend = FacebookBackend(Mock(), INTERNAL_ATTRIBUTES, FB_CONFIG, "base_url", "facebook") @pytest.fixture def incoming_authn_response(self, context): context.path = 'facebook/sso/redirect' state_data = dict(state=mock_get_state.return_value) context.state[self.fb_backend.name] = state_data context.request = { "code": FB_RESPONSE_CODE, "state": mock_get_state.return_value } return context def setup_facebook_response(self): responses.add(responses.GET, "https://graph.facebook.com/v2.5/me", body=json.dumps(FB_RESPONSE), status=200, content_type='application/json') def assert_expected_attributes(self): expected_attributes = { "edupersontargetedid": [FB_RESPONSE["id"]], "surname": [FB_RESPONSE["last_name"]], "name": [FB_RESPONSE["name"]], "mail": [FB_RESPONSE["email"]], "givenname": [FB_RESPONSE["first_name"]], "gender": [FB_RESPONSE["gender"]], } context, internal_resp = self.fb_backend.auth_callback_func.call_args[0] assert internal_resp.attributes == expected_attributes def assert_token_request(self, request_args, state, **kwargs): assert request_args["code"] == FB_RESPONSE_CODE assert request_args["redirect_uri"] == "%s/%s" % (BASE_URL, AUTHZ_PAGE) assert request_args["state"] == mock_get_state.return_value assert state == mock_get_state.return_value def test_register_endpoints(self): url_map = self.fb_backend.register_endpoints() expected_url_map = [('^facebook$', self.fb_backend._authn_response)] assert url_map == expected_url_map def test_start_auth(self, context): context.path = 'facebook/sso/redirect' internal_request = InternalRequest(UserIdHashType.transient, 'test_requester') resp = self.fb_backend.start_auth(context, internal_request, mock_get_state) login_url = resp.message assert login_url.startswith(FB_AUTH_ENDPOINT) expected_params = { "client_id": CLIENT_ID, "state": mock_get_state.return_value, "response_type": "code", "redirect_uri": "%s/%s" % (BASE_URL, AUTHZ_PAGE) } actual_params = dict(parse_qsl(urlparse(login_url).query)) assert actual_params == expected_params @responses.activate def test_authn_response(self, incoming_authn_response): self.setup_facebook_response() mock_do_access_token_request = Mock(return_value={"access_token": "fb access token"}) self.fb_backend.consumer.do_access_token_request = mock_do_access_token_request self.fb_backend._authn_response(incoming_authn_response) assert self.fb_backend.name not in incoming_authn_response.state self.assert_expected_attributes() self.assert_token_request(**mock_do_access_token_request.call_args[1]) @responses.activate def test_entire_flow(self, context): """Tests start of authentication (incoming auth req) and receiving auth response.""" responses.add(responses.POST, "https://graph.facebook.com/v2.5/oauth/access_token", body=json.dumps({"access_token": "qwerty", "token_type": "bearer", "expires_in": 9999999999999}), status=200, content_type='application/json') self.setup_facebook_response() context.path = 'facebook/sso/redirect' internal_request = InternalRequest(UserIdHashType.transient, 'test_requester') self.fb_backend.start_auth(context, internal_request, mock_get_state) context.request = { "code": FB_RESPONSE_CODE, "state": mock_get_state.return_value } self.fb_backend._authn_response(context) assert self.fb_backend.name not in context.state self.assert_expected_attributes()
class TestFacebook: @pytest.fixture(autouse=True) def setup(self): self.config = { 'server_info': {'authorization_endpoint': FB_AUTH_ENDPOINT, 'token_endpoint': 'https://graph.facebook.com/v2.5/oauth/access_token'}, 'client_secret': 'facebook_secret', 'base_url': BASE_URL, 'state_encryption_key': 'state_encryption_key', 'encryption_key': 'encryption_key', 'fields': ['id', 'name', 'first_name', 'last_name', 'middle_name', 'picture', 'email', 'verified', 'gender', 'timezone', 'locale', 'updated_time'], 'authz_page': AUTHZ_PAGE, 'client_config': {'client_id': CLIENT_ID} } self.fb_backend = FacebookBackend(None, INTERNAL_ATTRIBUTES, self.config) def test_register_endpoints(self): resp_map = self.fb_backend.register_endpoints() test_map = [('^facebook?(.*)$', self.fb_backend.authn_response), ('^facebook$', self.fb_backend.authn_response)] assert len(resp_map) == len(test_map), "The endpoint registration is not working!" for idx, val in enumerate(resp_map): assert val == test_map[idx], "The endpoint registration is not working!" def test_start_auth(self): context = Context() context.path = 'facebook/sso/redirect' context.state = State() internal_request = InternalRequest(UserIdHashType.transient, 'http://localhost:8087/sp.xml') get_state = Mock() get_state.return_value = STATE resp = self.fb_backend.start_auth(context, internal_request, get_state) # assert resp.headers[0][0] == "Set-Cookie", "Not the correct return cookie" # assert len(resp.headers[0][1]) > 1, "Not the correct return cookie" resp_url = resp.message.split("?") test_url = FB_REDIRECT_URL.split("?") resp_attr = parse_qs(resp_url[1]) test_attr = parse_qs(test_url[1]) assert resp_url[0] == test_url[0] assert len(resp_attr) == len(test_attr), "Redirect url is not correct!" for key in test_attr: assert key in resp_attr, "Redirect url is not correct!" assert test_attr[key] == resp_attr[key], "Redirect url is not correct!" def verify_callback(self, context, internal_response): assert len(FB_RESPONSE_CHECK) == len( internal_response._attributes), "Not a correct callback!" for key in internal_response._attributes: assert key in FB_RESPONSE_CHECK, "Not a correct callback!" assert FB_RESPONSE_CHECK[key] == internal_response._attributes[key], \ "Not a correct callback!" def verify_do_access_token_request(self, request_args, state, **kwargs): assert request_args["code"] == FB_RESPONSE_CODE, "Not a correct at request!" assert request_args["redirect_uri"] == "%s/%s" % (BASE_URL, AUTHZ_PAGE), \ "Not a correct at request!" assert request_args["state"] == STATE, "Not a correct at request!" assert state == STATE, "Not a correnct state!" return {"access_token": "fb access token"} def verify_request_fb(self, url, payload): resp = Mock() resp.text = json.dumps(FB_RESPONSE) return resp def test_authn_response(self): context = Context() context.path = 'facebook/sso/redirect' context.state = State() internal_request = InternalRequest(UserIdHashType.transient, 'http://localhost:8087/sp.xml') get_state = Mock() get_state.return_value = STATE resp = self.fb_backend.start_auth(context, internal_request, get_state) context.cookie = resp.headers[0][1] context.request = { "code": FB_RESPONSE_CODE, "state": STATE } # context.request = json.dumps(context.request) self.fb_backend.auth_callback_func = self.verify_callback tmp_consumer = self.fb_backend.get_consumer() tmp_consumer.do_access_token_request = self.verify_do_access_token_request self.fb_backend.get_consumer = Mock() self.fb_backend.get_consumer.return_value = tmp_consumer self.fb_backend.request_fb = self.verify_request_fb self.fb_backend.authn_response(context) @responses.activate def test_with_pyoidc(self): responses.add(responses.POST, "https://graph.facebook.com/v2.5/oauth/access_token", body=json.dumps({"access_token": "qwerty", "token_type": "bearer", "expires_in": 9999999999999}), adding_headers={"set-cookie": "TEST=testing; path=/"}, status=200, content_type='application/json') responses.add(responses.GET, "https://graph.facebook.com/v2.5/me", match_querystring=False, body=json.dumps(FB_RESPONSE), status=200, content_type='application/json') context = Context() context.path = 'facebook/sso/redirect' context.state = State() internal_request = InternalRequest(UserIdHashType.transient, 'http://localhost:8087/sp.xml') get_state = Mock() get_state.return_value = STATE resp = self.fb_backend.start_auth(context, internal_request, get_state) context.cookie = resp.headers[0][1] context.request = { "code": FB_RESPONSE_CODE, "state": STATE } self.fb_backend.auth_callback_func = self.verify_callback self.fb_backend.authn_response(context)