def _verify_query(self, query_params): """Verify response from the Uber Auth server. Parameters query_params (dict) Dictionary of query parameters attached to your redirect URL after user approved your app and was redirected. Returns authorization_code (str) Code received when user grants your app access. Use this code to request an access token. Raises UberIllegalState (ApiError) Thrown if the redirect URL was missing parameters or if the given parameters were not valid. """ error_message = None if self.state_token is not False: # Check CSRF State Token against state token from GET request received_state_token = query_params.get('state') if received_state_token is None: error_message = 'Bad Request. Missing state parameter.' raise UberIllegalState(error_message) if self.state_token != received_state_token: error_message = 'CSRF Error. Expected {}, got {}' error_message = error_message.format( self.state_token, received_state_token, ) raise UberIllegalState(error_message) # Verify either 'code' or 'error' parameter exists error = query_params.get('error') authorization_code = query_params.get(auth.CODE_RESPONSE_TYPE) if error and authorization_code: error_message = ( 'Code and Error query params code and error ' 'can not both be set.' ) raise UberIllegalState(error_message) if error is None and authorization_code is None: error_message = 'Neither query parameter code or error is set.' raise UberIllegalState(error_message) if error: raise UberIllegalState(error) return authorization_code
def _build_headers(self, method, auth_session): """Create headers for the request. Parameters method (str) HTTP method (e.g. 'POST'). auth_session (Session) The Session object containing OAuth 2.0 credentials. Returns headers (dict) Dictionary of access headers to attach to request. Raises UberIllegalState (ApiError) Raised if headers are invalid. """ token_type = auth_session.token_type if auth_session.server_token: token = auth_session.server_token else: token = auth_session.oauth2credential.access_token if not self._authorization_headers_valid(token_type, token): message = 'Invalid token_type or token.' raise UberIllegalState(message) headers = {'Authorization': ' '.join([token_type, token])} if method in http.BODY_METHODS: headers.update(http.DEFAULT_CONTENT_HEADERS) return headers
def _prepare(self): """Builds a URL and return a PreparedRequest. Returns (requests.PreparedRequest) Raises UberIllegalState (APIError) """ if self.method not in http.ALLOWED_METHODS: raise UberIllegalState('Unsupported HTTP Method.') api_host = self.api_host headers = self._build_headers(self.method, self.auth_session) url = build_url(api_host, self.path) data, params = generate_data(self.method, self.args) return generate_prepared_request( self.method, url, headers, data, params, self.handlers, )
def refresh_access_token(credential): """Use a refresh token to request a new access token. Not suported for access tokens obtained via Implicit Grant. Parameters credential (OAuth2Credential) An authorized user's OAuth 2.0 credentials. Returns (Session) A new Session object with refreshed OAuth 2.0 credentials. Raises UberIllegalState (APIError) Raised if OAuth 2.0 grant type does not support refresh tokens. """ if credential.grant_type == auth.AUTHORIZATION_CODE_GRANT: response = _request_access_token( grant_type=auth.REFRESH_TOKEN, client_id=credential.client_id, client_secret=credential.client_secret, redirect_url=credential.redirect_url, refresh_token=credential.refresh_token, ) oauth2credential = OAuth2Credential.make_from_response( response=response, grant_type=credential.grant_type, client_id=credential.client_id, client_secret=credential.client_secret, redirect_url=credential.redirect_url, ) return Session(oauth2credential=oauth2credential) elif credential.grant_type == auth.CLIENT_CREDENTIAL_GRANT: response = _request_access_token( grant_type=auth.CLIENT_CREDENTIAL_GRANT, client_id=credential.client_id, client_secret=credential.client_secret, scopes=credential.scopes, ) oauth2credential = OAuth2Credential.make_from_response( response=response, grant_type=credential.grant_type, client_id=credential.client_id, client_secret=credential.client_secret, ) return Session(oauth2credential=oauth2credential) message = '{} Grant Type does not support Refresh Tokens.' message = message.format(credential.grant_type) raise UberIllegalState(message)
def __init__( self, server_token=None, oauth2credential=None, ): """Initialize a Session. Parameters sever_token (str) Your application's server token. Available at developer.uber.com. oauth2credential (OAuth2Credential) Access token and additional OAuth 2.0 credentials used to access protected resources. Raises UberIllegalState (APIError) Raised if there is an attempt to create session with both server token and access token. """ if server_token and oauth2credential: message = ( 'Session cannot have both Server ' 'and OAuth 2.0 Credentials.' ) raise UberIllegalState(message) if server_token is None and oauth2credential is None: message = ( 'Session must have either Server ' 'Token or OAuth 2.0 Credentials.' ) raise UberIllegalState(message) if server_token: self.server_token = server_token self.token_type = auth.SERVER_TOKEN_TYPE self.oauth2credential = None elif oauth2credential: self.oauth2credential = oauth2credential self.token_type = auth.OAUTH_TOKEN_TYPE self.server_token = None
def _build_authorization_request_url( self, response_type, redirect_url, state=None ): """Form URL to request an auth code or access token. Parameters response_type (str) Either 'code' (Authorization Code Grant) or 'token' (Implicit Grant) redirect_url (str) The URL that the Uber server will redirect the user to after finishing authorization. The redirect must be HTTPS-based and match the URL you registered your application with. Localhost URLs are permitted and can be either HTTP or HTTPS. state (str) Optional CSRF State token to send to server. Returns (str) The fully constructed authorization request URL. Raises UberIllegalState (ApiError) Raised if response_type parameter is invalid. """ if response_type not in auth.VALID_RESPONSE_TYPES: message = '{} is not a valid response type.' raise UberIllegalState(message.format(response_type)) args = OrderedDict([ ('scope', ' '.join(self.scopes)), ('state', state), ('redirect_uri', redirect_url), ('response_type', response_type), ('client_id', self.client_id), ]) return build_url(auth.AUTH_HOST, auth.AUTHORIZE_PATH, args)
def update_sandbox_ride(self, ride_id, new_status): """Update the status of an ongoing sandbox request. Params ride_id (str) The unique ID of the Ride Request. new_status (str) Status from VALID_PRODUCT_STATUS. Returns (Response) A Response object with successful status_code if ride status was updated. """ if new_status not in VALID_PRODUCT_STATUS: message = '{} is not a valid product status.' raise UberIllegalState(message.format(new_status)) args = {'status': new_status} endpoint = 'v1/sandbox/requests/{}'.format(ride_id) return self._api_call('PUT', endpoint, args=args)
def get_session(self, redirect_url): """Create Session to store credentials. Parameters redirect_url (str) The full URL that the Uber server redirected to after the user authorized your app. Returns (Session) A Session object with OAuth 2.0 credentials. Raises UberIllegalState (APIError) Raised if redirect URL contains an error. """ query_params = self._extract_query(redirect_url) error = query_params.get('error') if error: raise UberIllegalState(error) # convert space delimited string to set scopes = query_params.get('scope') scopes_set = {scope for scope in scopes.split()} oauth2credential = OAuth2Credential( client_id=self.client_id, redirect_url=self.redirect_url, access_token=query_params.get('access_token'), expires_in_seconds=query_params.get('expires_in'), scopes=scopes_set, grant_type=auth.IMPLICIT_GRANT, ) return Session(oauth2credential=oauth2credential)