Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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()
Ejemplo n.º 3
0
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()
Ejemplo n.º 4
0
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)