예제 #1
0
    def read_validate_params(self, request):
        self.client_id = request.post_param("client_id")

        if self.client_id is None:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Missing client_id in request body")

        client_secret = request.post_param("client_secret")

        if client_secret is None:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Missing client_secret in request body")

        try:
            client = self.client_store.fetch_by_client_id(self.client_id)

            if client.secret != client_secret:
                raise OAuthInvalidError(error="invalid_request",
                                        explanation="Invalid client secret")
        except ClientNotFoundError:
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Unknown client")

        self.scope_handler.parse(request=request, source="body")
예제 #2
0
def request_body(request):
    """
    Extracts the credentials of a client from the
    *application/x-www-form-urlencoded* body of a request.

    Expects the client_id to be the value of the ``client_id`` parameter and
    the client_secret to be the value of the ``client_secret`` parameter.

    :param request: The incoming request
    :type request: oauth2.web.Request

    :return: A tuple in the format of `(<CLIENT ID>, <CLIENT SECRET>)`
    :rtype: tuple
    """
    client_id = request.post_param("client_id")
    if client_id is None:
        raise OAuthInvalidError(error="invalid_request",
                                explanation="Missing client identifier")

    client_secret = request.post_param("client_secret")
    if client_secret is None:
        raise OAuthInvalidError(error="invalid_request",
                                explanation="Missing client credentials")

    return client_id, client_secret
예제 #3
0
    def read_validate_params(self, request):
        """
        Checks if all incoming parameters meet the expected values.
        """
        self.client_id = request.post_param("client_id")

        if self.client_id is None:
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Missing client_id parameter")

        try:
            client = self.client_store.fetch_by_client_id(self.client_id)
        except ClientNotFoundError:
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Unknown client")

        if client.secret != request.post_param("client_secret"):
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Could not authenticate client")

        self.password = request.post_param("password")
        self.username = request.post_param("username")

        self.scope_handler.parse(request=request, source="body")

        return True
예제 #4
0
    def _validate_code(self):
        try:
            stored_code = self.auth_code_store.fetch_by_code(self.code)
        except AuthCodeNotFound:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Invalid authorization code parameter")

        if stored_code.code != self.code:
            raise OAuthInvalidError(
                error="invalid_grant",
                explanation="Invalid code parameter in request")

        if stored_code.redirect_uri != self.redirect_uri:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Invalid redirect_uri parameter")

        if stored_code.is_expired():
            raise OAuthInvalidError(
                error="invalid_grant",
                explanation="Authorization code has expired")

        self.data = stored_code.data
        self.scopes = stored_code.scopes
        self.user_id = stored_code.user_id
예제 #5
0
def http_basic_auth(request):
    """
    Extracts the credentials of a client using HTTP Basic Auth.

    Expects the client_id to be the username and the client_secret to be the
    password part of the Authorization header.

    :param request: An instance of :class:`oauth2.web.Request`

    :return: A tuple in the format of (<CLIENT ID>, <CLIENT SECRET>)`
    """
    auth_header = request.header("authorization")

    if auth_header is None:
        raise OAuthInvalidError(error="invalid_request",
                                explanation="Authorization header is missing")

    auth_parts = auth_header.strip().encode("latin1").split(None)

    if auth_parts[0].strip().lower() != b'basic':
        raise OAuthInvalidError(
            error="invalid_request",
            explanation="Provider supports basic authentication only")

    client_id, client_secret = b64decode(auth_parts[1]).split(b':', 1)

    return client_id.decode("latin1"), client_secret.decode("latin1")
예제 #6
0
    def by_identifier_secret(self, request):
        """
        Authenticates a client by its identifier and secret (aka password).

        :param request: An instance of :class:`oauth2.web.Request`.

        :return: An instance of :class:`oauth2.datatype.Client`.
        """
        client_id, client_secret = self.source(request=request)

        try:
            client = self.client_store.fetch_by_client_id(client_id)
        except ClientNotFoundError:
            raise OAuthInvalidError(error="invalid_client",
                                    explanation="No client could be found")

        grant_type = request.post_param("grant_type")
        if client.grant_type_supported(grant_type) is False:
            raise OAuthInvalidError(error="unauthorized_client",
                                    explanation="The client is not allowed "
                                    "to use this grant type")

        if client.secret != client_secret:
            raise OAuthInvalidError(error="invalid_client",
                                    explanation="Invalid client credentials")

        return client
    def process(self, request, response, environ):
        """
        Takes the incoming request, asks the concrete SiteAdapter to validate
        it and issues a new access token that is returned to the client on
        successful validation.
        """
        try:
            data = self.site_adapter.authenticate(request, environ,
                                                  self.scope_handler.scopes,
                                                  self.client)
            data = AuthorizeMixin.sanitize_return_value(data)
        except UserNotAuthenticated:
            raise OAuthInvalidError(error="invalid_client",
                                    explanation=self.OWNER_NOT_AUTHENTICATED)

        if isinstance(data, Response):
            return data

        token_data = self.create_token(
            client_id=self.client.identifier,
            data=data[0],
            grant_type=ResourceOwnerGrant.grant_type,
            scopes=self.scope_handler.scopes,
            user_id=data[1])

        if self.scope_handler.send_back:
            token_data["scope"] = encode_scopes(self.scope_handler.scopes)

        json_success_response(data=token_data, response=response)

        return response
예제 #8
0
    def authorize(self, request, response, environ, scopes):
        """
        Controls all steps to authorize a request by a user.

        :param request: The incoming :class:`oauth2.web.Request`
        :param response: The :class:`oauth2.web.Response` that will be
                         returned eventually
        :param environ: The environment variables of this request
        :param scopes: The scopes requested by an application
        :return: A tuple containing (`dict`, user_id) or the response.

        """
        if self.site_adapter.user_has_denied_access(request) is True:
            raise OAuthInvalidError(error="access_denied",
                                    explanation="Authorization denied by user")

        try:
            result = self.site_adapter.authenticate(request, environ, scopes,
                                                    self.client)

            return self.sanitize_return_value(result)
        except UserNotAuthenticated:
            return self.site_adapter.render_auth_page(request, response,
                                                      environ, scopes,
                                                      self.client)
예제 #9
0
    def _read_params(self, request):
        self.client = self.client_authenticator.by_identifier_secret(request)
        self.code = request.post_param("code")
        self.redirect_uri = request.post_param("redirect_uri")

        if self.code is None or self.redirect_uri is None:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Missing required parameter in request")

        try:
            self.client.redirect_uri = self.redirect_uri
        except RedirectUriUnknown:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Invalid redirect_uri parameter")
    def parse(self, request, source):
        """
        Parses scope value in given request.

        Expects the value of the "scope" parameter in request to be a string
        where each requested scope is separated by a white space::

            # One scope requested
            "profile_read"

            # Multiple scopes
            "profile_read profile_write"

        :param request: An instance of :class:`oauth2.web.Request`.
        :param source: Where to read the scope from. Pass "body" in case of a
                       application/x-www-form-urlencoded body and "query" in
                       case the scope is supplied as a query parameter in the
                       URL of a request.
        """
        if source == "body":
            req_scope = request.post_param("scope")
        elif source == "query":

            req_scope = request.get_param("scope")
            print req_scope
        else:
            raise ValueError("Unknown scope source '" + source + "'")

        if req_scope is None:
            if self.default is not None:
                self.scopes = [self.default]
                self.send_back = True
                return
            elif len(self.available_scopes) != 0:
                raise OAuthInvalidError(
                    error="invalid_scope",
                    explanation="Missing scope parameter in request")
            else:
                return

        req_scopes = req_scope.split(self.separator)
        print req_scope
        print self.available_scopes
        print req_scope in self.available_scopes
        for scope in self.available_scopes:
            print scope

        for scope in req_scopes:
            print scope

        self.scopes = [
            scope for scope in req_scopes if scope in self.available_scopes
        ]
        print "self.scopes: "
        print self.scopes
        print len(self.scopes)
        if len(self.scopes) == 0 and self.default is not None:
            self.scopes = [self.default]
            self.send_back = True
예제 #11
0
    def _determine_grant_type(self, request):
        for grant in self.grant_types:
            grant_handler = grant(request, self)
            if grant_handler is not None:
                return grant_handler

        raise OAuthInvalidError(error="unsupported_response_type",
                                explanation="Server does not support given "
                                "response_type")
    def read_validate_params(self, request):
        print "4"
        """
        Validate the incoming request.

        :param request: The incoming :class:`oauth2.web.Request`.

        :return: Returns ``True`` if data is valid.

        :raises: :class:`oauth2.error.OAuthInvalidError`

        """
        self.refresh_token = request.post_param("refresh_token")

        if self.refresh_token is None:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Missing refresh_token in request body")

        self.client = self.client_authenticator.by_identifier_secret(request)

        try:
            access_token = self.access_token_store.fetch_by_refresh_token(
                self.refresh_token)
        except AccessTokenNotFound:
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Invalid refresh token")

        refresh_token_expires_at = access_token.refresh_expires_at
        self.refresh_grant_type = access_token.grant_type

        if refresh_token_expires_at != 0 and \
           refresh_token_expires_at < int(time.time()):
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Invalid refresh token")

        self.data = access_token.data
        self.user_id = access_token.user_id

        self.scope_handler.parse(request, "body")
        self.scope_handler.compare(access_token.scopes)

        return True
예제 #13
0
    def _read_params(self, request):
        self.client_id = request.post_param("client_id")
        self.client_secret = request.post_param("client_secret")
        self.code = request.post_param("code")
        self.redirect_uri = request.post_param("redirect_uri")

        if (self.code is None or self.client_id is None
                or self.client_secret is None or self.redirect_uri is None):
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Missing required parameter " \
                                                "in request")
예제 #14
0
    def dispatch(self, request, environ):
        """
        Checks which Grant supports the current request and dispatches to it.

        :param request: The incoming request.
        :type request: :class:`oauth2.web.Request`
        :param environ: Dict containing variables of the environment.
        :type environ: dict

        :return: An instance of ``oauth2.web.Response``.
        """
        try:
            grant_type = self._determine_grant_type(request)

            response = self.response_class()

            grant_type.read_validate_params(request)

            return grant_type.process(request, response, environ)
        except OAuthInvalidNoRedirectError:
            response = self.response_class()
            response.add_header("Content-Type", "application/json")
            response.status_code = 400
            response.body = json.dumps({
                "error":
                "invalid_redirect_uri",
                "error_description":
                "Invalid redirect URI"
            })

            return response
        except OAuthInvalidError as err:
            response = self.response_class()
            return grant_type.handle_error(error=err, response=response)
        except UnsupportedGrantError:
            response = self.response_class()
            response.add_header("Content-Type", "application/json")
            response.status_code = 400
            response.body = json.dumps({
                "error":
                "unsupported_response_type",
                "error_description":
                "Grant not supported"
            })

            return response
        except:
            app_log.error("Uncaught Exception", exc_info=True)
            response = self.response_class()
            return grant_type.handle_error(error=OAuthInvalidError(
                error="server_error", explanation="Internal server error"),
                                           response=response)
예제 #15
0
    def read_validate_params(self, request):
        """
        Reads and validates data in an incoming request as required by
        the Authorization Request of the Authorization Code Grant and the
        Implicit Grant.
        """
        client_id = request.get_param("client_id")
        if client_id is None:
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="Missing client_id parameter")
        self.client_id = client_id

        try:
            client_data = self.client_store.fetch_by_client_id(self.client_id)
        except ClientNotFoundError:
            raise OAuthInvalidError(error="invalid_request",
                                    explanation="No client registered")

        redirect_uri = request.get_param("redirect_uri")

        if redirect_uri is not None:
            if client_data.has_redirect_uri(redirect_uri) == False:
                raise OAuthInvalidError(
                    error="invalid_request",
                    explanation="redirect_uri is not registered for this " \
                                "client")
            else:
                self.redirect_uri = redirect_uri
        else:
            # redirect_uri is an optional param.
            # If not supplied, we use the first entry stored in db as default.
            self.redirect_uri = client_data.redirect_uris[0]

        self.state = request.get_param("state")

        self.scope_handler.parse(request, "query")

        return True
예제 #16
0
    def compare(self, previous_scopes):
        """
        Compares the scopes read from request with previously issued scopes.

        :param previous_scopes: A list of scopes.
        :return: ``True``
        """
        for scope in self.scopes:
            if scope not in previous_scopes:
                raise OAuthInvalidError(
                    error="invalid_scope",
                    explanation="Invalid scope parameter in request")

        return True
예제 #17
0
    def _validate_client(self):
        try:
            client = self.client_store.fetch_by_client_id(self.client_id)
        except ClientNotFoundError:
            raise OAuthClientError(error="invalid_client",
                                   explanation="Unknown client")

        if client.secret != self.client_secret:
            raise OAuthClientError(error="invalid_client",
                                   explanation="Invalid client_secret")

        if client.has_redirect_uri(self.redirect_uri) is False:
            raise OAuthInvalidError(
                error="invalid_request",
                explanation="Invalid redirect_uri parameter")
예제 #18
0
    def read_validate_params(self, request):
        """
        Reads and validates data in an incoming request as required by
        the Authorization Request of the Authorization Code Grant and the
        Implicit Grant.
        """
        self.client = self.client_authenticator.by_identifier(request)

        response_type = request.get_param("response_type")

        if self.client.response_type_supported(response_type) is False:
            raise OAuthInvalidError(error="unauthorized_client")

        self.state = request.get_param("state")

        self.scope_handler.parse(request, "query")

        return True