Beispiel #1
0
    def exchange_code(self,
                      app_config,
                      http_client,
                      code,
                      form_encode=False,
                      redirect_suffix='',
                      client_auth=False):
        """ Exchanges an OAuth access code for associated OAuth token and other data. """
        url_scheme_and_hostname = URLSchemeAndHostname.from_app_config(
            app_config)
        payload = {
            'code':
            code,
            'grant_type':
            'authorization_code',
            'redirect_uri':
            self.get_redirect_uri(url_scheme_and_hostname, redirect_suffix)
        }

        headers = {'Accept': 'application/json'}

        auth = None
        if client_auth:
            auth = (self.client_id(), self.client_secret())
        else:
            payload['client_id'] = self.client_id()
            payload['client_secret'] = self.client_secret()

        token_url = self.token_endpoint().to_url()
        if form_encode:
            get_access_token = http_client.post(token_url,
                                                data=payload,
                                                headers=headers,
                                                auth=auth)
        else:
            get_access_token = http_client.post(token_url,
                                                params=payload,
                                                headers=headers,
                                                auth=auth)

        if get_access_token.status_code // 100 != 2:
            logger.debug('Got get_access_token response %s',
                         get_access_token.text)
            raise OAuthExchangeCodeException(
                'Got non-2XX response for code exchange: %s' %
                get_access_token.status_code)

        json_data = get_access_token.json()
        if not json_data:
            raise OAuthExchangeCodeException(
                'Got non-JSON response for code exchange')

        if 'error' in json_data:
            raise OAuthExchangeCodeException(
                json_data.get('error_description', json_data['error']))

        return json_data
Beispiel #2
0
def test_auth_url(oidc_service, discovery_handler, http_client,
                  authorize_handler):
    config = {"PREFERRED_URL_SCHEME": "https", "SERVER_HOSTNAME": "someserver"}

    with HTTMock(discovery_handler, authorize_handler):
        url_scheme_and_hostname = URLSchemeAndHostname.from_app_config(config)
        auth_url = oidc_service.get_auth_url(url_scheme_and_hostname, "",
                                             "some csrf token", ["one", "two"])

        # Hit the URL and ensure it works.
        result = http_client.get(auth_url).json()
        assert result["state"] == "some csrf token"
        assert result["scope"] == "one two"
Beispiel #3
0
def test_auth_url(oidc_service, discovery_handler, http_client,
                  authorize_handler):
    config = {'PREFERRED_URL_SCHEME': 'https', 'SERVER_HOSTNAME': 'someserver'}

    with HTTMock(discovery_handler, authorize_handler):
        url_scheme_and_hostname = URLSchemeAndHostname.from_app_config(config)
        auth_url = oidc_service.get_auth_url(url_scheme_and_hostname, '',
                                             'some csrf token', ['one', 'two'])

        # Hit the URL and ensure it works.
        result = http_client.get(auth_url).json()
        assert result['state'] == 'some csrf token'
        assert result['scope'] == 'one two'
Beispiel #4
0
    def exchange_code(
        self,
        app_config,
        http_client,
        code,
        form_encode=False,
        redirect_suffix="",
        client_auth=False,
    ):
        """ Exchanges an OAuth access code for associated OAuth token and other data. """
        url_scheme_and_hostname = URLSchemeAndHostname.from_app_config(app_config)
        payload = {
            "code": code,
            "grant_type": "authorization_code",
            "redirect_uri": self.get_redirect_uri(url_scheme_and_hostname, redirect_suffix),
        }

        headers = {"Accept": "application/json"}

        auth = None
        if client_auth:
            auth = (self.client_id(), self.client_secret())
        else:
            payload["client_id"] = self.client_id()
            payload["client_secret"] = self.client_secret()

        token_url = self.token_endpoint().to_url()
        if form_encode:
            get_access_token = http_client.post(token_url, data=payload, headers=headers, auth=auth)
        else:
            get_access_token = http_client.post(
                token_url, params=payload, headers=headers, auth=auth
            )

        if get_access_token.status_code // 100 != 2:
            logger.debug("Got get_access_token response %s", get_access_token.text)
            raise OAuthExchangeCodeException(
                "Got non-2XX response for code exchange: %s" % get_access_token.status_code
            )

        json_data = get_access_token.json()
        if not json_data:
            raise OAuthExchangeCodeException("Got non-JSON response for code exchange")

        if "error" in json_data:
            raise OAuthExchangeCodeException(json_data.get("error_description", json_data["error"]))

        return json_data
Beispiel #5
0
    def from_app(
        cls,
        app,
        config,
        user_password,
        ip_resolver,
        instance_keys,
        client=None,
        config_provider=None,
        init_scripts_location=None,
    ):
        """
        Creates a ValidatorContext from an app config, with a given config to validate.

        :param app: the Flask app to pull configuration information from
        :param config: the config to validate
        :param user_password: request password
        :param instance_keys: The instance keys handler
        :param ip_resolver: an App
        :param client: http client used to connect to services
        :param config_provider: config provider used to access config volume(s)
        :param init_scripts_location: location where initial load scripts are stored
        :return: ValidatorContext
        """
        url_scheme_and_hostname = URLSchemeAndHostname.from_app_config(
            app.config)

        return cls(
            config,
            user_password=user_password,
            http_client=client or app.config["HTTPCLIENT"],
            context=app.app_context,
            url_scheme_and_hostname=url_scheme_and_hostname,
            jwt_auth_max=app.config.get("JWT_AUTH_MAX_FRESH_S", 300),
            registry_title=app.config["REGISTRY_TITLE"],
            ip_resolver=ip_resolver,
            feature_sec_scanner=app.config.get("FEATURE_SECURITY_SCANNER",
                                               False),
            is_testing=app.config.get("TESTING", False),
            uri_creator=get_blob_download_uri_getter(
                app.test_request_context("/"), url_scheme_and_hostname),
            config_provider=config_provider,
            instance_keys=instance_keys,
            init_scripts_location=init_scripts_location,
        )
Beispiel #6
0
    def exchange_code(
        self,
        app_config,
        http_client,
        code,
        form_encode=False,
        redirect_suffix="",
        client_auth=False,
    ):
        """
        Exchanges an OAuth access code for associated OAuth token and other data.
        """
        url_scheme_and_hostname = URLSchemeAndHostname.from_app_config(app_config)
        payload = {
            "code": code,
            "grant_type": "authorization_code",
            "redirect_uri": self.get_redirect_uri(url_scheme_and_hostname, redirect_suffix),
        }
        headers = {"Accept": "application/json"}

        auth = None
        if client_auth:
            auth = (self.client_id(), self.client_secret())
        else:
            payload["client_id"] = self.client_id()
            payload["client_secret"] = self.client_secret()

        token_url = self.token_endpoint().to_url()

        def perform_request():
            attempts = 0
            max_attempts = 3
            timeout = 5 / 1000

            while attempts < max_attempts:
                if self._is_testing:
                    headers["X-Quay-Retry-Attempts"] = str(attempts)

                try:
                    if form_encode:
                        return http_client.post(
                            token_url, data=payload, headers=headers, auth=auth, timeout=5
                        )
                    else:
                        return http_client.post(
                            token_url, params=payload, headers=headers, auth=auth, timeout=5
                        )
                except requests.ConnectionError:
                    logger.debug("Got ConnectionError during OAuth token exchange, retrying.")
                    attempts += 1
                    time.sleep(timeout)

        get_access_token = perform_request()
        if get_access_token is None:
            logger.debug("Received too many ConnectionErrors during code exchange")
            raise OAuthExchangeCodeException(
                "Received too many ConnectionErrors during code exchange"
            )

        if get_access_token.status_code // 100 != 2:
            logger.debug("Got get_access_token response %s", get_access_token.text)
            raise OAuthExchangeCodeException(
                "Got non-2XX response for code exchange: %s" % get_access_token.status_code
            )

        json_data = get_access_token.json()
        if not json_data:
            raise OAuthExchangeCodeException("Got non-JSON response for code exchange")

        if "error" in json_data:
            raise OAuthExchangeCodeException(json_data.get("error_description", json_data["error"]))

        return json_data