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")
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
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
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
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")
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
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)
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
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
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")
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)
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
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
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")
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