def prepare_authorization_response(self, request, token, headers, body, status): """Place token according to response mode. Base classes can define a default response mode for their authorization response by overriding the static `default_response_mode` member. """ request.response_mode = request.response_mode or self.default_response_mode if request.response_mode not in ('query', 'fragment'): log.debug('Overriding invalid response mode %s with %s', request.response_mode, self.default_response_mode) request.response_mode = self.default_response_mode token_items = token.items() if request.response_type == 'none': state = token.get('state', None) if state: token_items = [('state', state)] else: token_items = [] if request.response_mode == 'query': headers['Location'] = add_params_to_uri( request.redirect_uri, token_items, fragment=False) return headers, body, status if request.response_mode == 'fragment': headers['Location'] = add_params_to_uri( request.redirect_uri, token_items, fragment=True) return headers, body, status raise NotImplementedError( 'Subclasses must set a valid default_response_mode')
def create_authorization_response(self, request, token_handler): try: self.validate_authorization_request(request) log.debug('Pre resource owner authorization validation ok for %r.', request) # If the request fails due to a missing, invalid, or mismatching # redirection URI, or if the client identifier is missing or invalid, # the authorization server SHOULD inform the resource owner of the # error and MUST NOT automatically redirect the user-agent to the # invalid redirection URI. except errors.FatalClientError as e: log.debug('Fatal client error during validation of %r. %r.', request, e) raise # If the resource owner denies the access request or if the request # fails for reasons other than a missing or invalid redirection URI, # the authorization server informs the client by adding the following # parameters to the query component of the redirection URI using the # "application/x-www-form-urlencoded" format, per Appendix B: # http://tools.ietf.org/html/rfc6749#appendix-B except errors.OAuth2Error as e: log.debug('Client error during validation of %r. %r.', request, e) request.redirect_uri = request.redirect_uri or self.error_uri return common.add_params_to_uri(request.redirect_uri, e.twotuples), None, None, e.status_code grant = self.create_authorization_code(request) logging.debug('Saving grant %r for %r.', grant, request) self.request_validator.save_authorization_code(request, grant) return common.add_params_to_uri(request.redirect_uri, grant.items()), None, None, 200
def decorated(*args, **kwargs): if request.method == 'POST': if not f(*args, **kwargs): uri = add_params_to_uri( self.error_uri, [('error', 'denied')] ) return redirect(uri) return self.confirm_authorization_request() server = self.server uri, http_method, body, headers = extract_params() try: realms, credentials = server.get_realms_and_credentials( uri, http_method=http_method, body=body, headers=headers ) kwargs['realms'] = realms kwargs.update(credentials) return f(*args, **kwargs) except errors.OAuth1Error as e: return redirect(e.in_uri(self.error_uri)) except errors.InvalidClientError as e: return redirect(e.in_uri(self.error_uri)) except Exception as e: return redirect(add_params_to_uri( self.error_uri, {'error': e.message} ))
def decorated(*args, **kwargs): # raise if server not implemented server = self.server uri, http_method, body, headers = extract_params() if request.method in ('GET', 'HEAD'): redirect_uri = request.args.get('redirect_uri', self.error_uri) log.debug('Found redirect_uri %s.', redirect_uri) try: ret = server.validate_authorization_request( uri, http_method, body, headers ) scopes, credentials = ret kwargs['scopes'] = scopes kwargs.update(credentials) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) return redirect(e.in_uri(redirect_uri)) except Exception as e: log.warning('Exception caught while processing request, %s.' % e, exc_info=True) return redirect(add_params_to_uri( self.error_uri, {'error': str(e) } )) else: redirect_uri = request.values.get( 'redirect_uri', self.error_uri ) try: rv = f(*args, **kwargs) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) return redirect(e.in_uri(redirect_uri)) except Exception as e: log.warning('Exception caught while processing request, %s.' % e, exc_info=True) return redirect(add_params_to_uri( self.error_uri, {'error': str(e) } )) if not isinstance(rv, bool): # if is a response or redirect return rv if not rv: # denied by user e = oauth2.AccessDeniedError() return redirect(e.in_uri(redirect_uri)) return self.confirm_authorization_request()
def create_authorization_response(self, request, token_handler): try: self.request_validator.validate_request(request) except errors.OAuth2Error as e: request.redirect_uri = getattr(request, 'redirect_uri', self.error_uri) return add_params_to_uri(request.redirect_uri, e.twotuples) grant = self.create_authorization_code(request) self.save_authorization_code(request.client_id, grant) return add_params_to_uri(request.redirect_uri, grant.items())
def _non_compliant_param_name(url, headers, data): # If the user has already specified the token, either in the URL # or in a data dictionary, then there's nothing to do. # If the specified token is different from ``session.access_token``, # we assume the user intends to override the access token. url_query = dict(parse_qs(urlparse(url).query)) token = url_query.get("token") if not token and isinstance(data, dict): token = data.get("token") if token: # Nothing to do, just return. return url, headers, data if not data: data = {"token": session.access_token} elif isinstance(data, dict): data["token"] = session.access_token else: # ``data`` is something other than a dict: maybe a stream, # maybe a file object, maybe something else. We can't easily # modify it, so we'll set the token by modifying the URL instead. token = [('token', session.access_token)] url = add_params_to_uri(url, token) return url, headers, data
def confirm_authorization_request(self): """When consumer confirm the authorization.""" server = self.server scope = request.values.get('scope') or '' scopes = scope.split() credentials = dict( client_id=request.values.get('client_id'), redirect_uri=request.values.get('redirect_uri', None), response_type=request.values.get('response_type', None), state=request.values.get('state', None)) log.debug('Fetched credentials from request %r.', credentials) redirect_uri = credentials.get('redirect_uri') log.debug('Found redirect_uri %s.', redirect_uri) uri, http_method, body, headers = extract_params() try: ret = server.create_authorization_response(uri, http_method, body, headers, scopes, credentials) log.debug('Authorization successful.') return create_response(*ret) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) return redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.exception(e) return redirect( add_params_to_uri(self.error_uri, {'error': str(e)}))
def http_request(uri, headers=None, data=None, method=None): if headers is None: headers = {} if data and not method: method = 'POST' elif not method: method = 'GET' if method == 'GET' and data: uri = add_params_to_uri(uri, data) data = None log.debug('Request %r with %r method' % (uri, method)) req = http.Request(uri, headers=headers, data=data) req.get_method = lambda: method.upper() try: resp = http.urlopen(req) content = resp.read() resp.close() return resp, content except http.HTTPError as resp: content = resp.read() resp.close() return resp, content
def confirm_authorization_request(self, handler): """When consumer confirm the authorization.""" server = self.server scope = handler.get_argument('scope', '') scopes = scope.split() credentials = dict( client_id=handler.get_argument('client_id'), redirect_uri=handler.get_argument('redirect_uri', None), response_type=handler.get_argument('response_type', None), state=handler.get_argument('state', None), ) log.debug('Fetched credentials from request %r.', credentials) redirect_uri = credentials.get('redirect_uri') log.debug('Found redirect_uri %s.', redirect_uri) uri, http_method, body, headers = handler.request.uri,\ handler.request.method, arguments_to_dict(handler),\ handler.request.headers try: ret = server.create_authorization_response( uri, http_method, body, headers, scopes, credentials, handler) log.debug('Authorization successful.') create_response(handler, *ret) except FatalClientError as e: log.debug('Fatal client error %r', e) return handler.redirect(e.in_uri(self.error_uri)) except OAuth2Error as e: log.debug('OAuth2Error: %r', e) return handler.redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return handler.redirect(add_params_to_uri( self.error_uri, {'error': 'unknown'} ))
def confirm_authorization_request(self): """When consumer confirm the authorization.""" server = self.server scope = request.values.get('scope') or '' scopes = scope.split() credentials = dict( client_id=request.values.get('client_id'), redirect_uri=request.values.get('redirect_uri', None), response_type=request.values.get('response_type', None), state=request.values.get('state', None) ) log.debug('Fetched credentials from request %r.', credentials) redirect_uri = credentials.get('redirect_uri') log.debug('Found redirect_uri %s.', redirect_uri) uri, http_method, body, headers = extract_params() try: ret = server.create_authorization_response( uri, http_method, body, headers, scopes, credentials) log.debug('Authorization successful.') return create_response(*ret) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e) return redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return redirect(add_params_to_uri( self.error_uri, {'error': 'unknown'} ))
def authorized(self, request_token, request = None): """Create a verifier for an user authorized client""" verifier = generate_token(length=self.verifier_length[1]) self.save_verifier(request_token, verifier) #if request: # response = dict(request.args.items()) #else: response = {} # Alright, now for the fun part! # We need to retrieve the user's unique ID for the service # the app just authenticated with them through us. service = session['realm'] uid = APIS[service].get_uid(request) if uid: response.update({'uid': uid, 'service': service}) # Are we logged in? if current_user.is_authenticated(): response.update({'btid': current_user.get_id()}) response.update( {u'oauth_token': request_token, u'oauth_verifier': verifier}) callback = self.get_callback(request_token) return redirect(add_params_to_uri(callback, response.items()))
def _authorize(handler, *args, **kwargs): redirect_uri = handler.get_argument('redirect_uri', None) try: if handler.request.method == 'POST': rv = _post(handler, *args, **kwargs) else: rv = _get(handler, *args, **kwargs) except FatalClientError as e: log.debug('Fatal client error %r', e) return handler.redirect(e.in_uri(self.error_uri)) except OAuth2Error as e: log.debug('OAuth2Error: %r', e) return handler.redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return handler.redirect(add_params_to_uri( self.error_uri, {'error': 'unknown'} )) if not isinstance(rv, bool): # if is a response or redirect return rv if not rv: # denied by user e = AccessDeniedError() return handler.redirect(e.in_uri(redirect_uri)) return self.confirm_authorization_request(handler)
def get(handler, *args, **kwargs): server = self.server uri, http_method, body, headers = handler.request.uri,\ handler.request.method, arguments_to_dict(handler),\ handler.request.headers redirect_uri = handler.get_argument('redirect_uri', None) log.debug('Found redirect_uri %s.', redirect_uri) try: ret = server.validate_authorization_request( uri, http_method, body, headers ) scopes, credentials = ret kwargs['scopes'] = scopes kwargs.update(credentials) except FatalClientError as e: log.debug('Fatal client error %r', e) return handler.redirect(e.in_uri(self.error_uri)) except OAuth2Error as e: log.debug('OAuth2Error: %r', e) return handler.redirect(e.in_uri(redirect_uri or self.error_uri)) except Exception as e: log.warn('Exception: %r', e) return handler.redirect(add_params_to_uri( self.error_uri, {'error': 'unknown'} )) _authorize(handler, *args, **kwargs)
def create_token_response(self, request, token_handler): """Return token or error embedded in the URI fragment. If the resource owner grants the access request, the authorization server issues an access token and delivers it to the client by adding the following parameters to the fragment component of the redirection URI using the "application/x-www-form-urlencoded" format, per `Appendix B`_: access_token REQUIRED. The access token issued by the authorization server. token_type REQUIRED. The type of the token issued as described in `Section 7.1`_. Value is case insensitive. expires_in RECOMMENDED. The lifetime in seconds of the access token. For example, the value "3600" denotes that the access token will expire in one hour from the time the response was generated. If omitted, the authorization server SHOULD provide the expiration time via other means or document the default value. scope OPTIONAL, if identical to the scope requested by the client; otherwise, REQUIRED. The scope of the access token as described by `Section 3.3`_. state REQUIRED if the "state" parameter was present in the client authorization request. The exact value received from the client. The authorization server MUST NOT issue a refresh token. .. _`Appendix B`: http://tools.ietf.org/html/rfc6749#appendix-B .. _`Section 3.3`: http://tools.ietf.org/html/rfc6749#section-3.3 .. _`Section 7.2`: http://tools.ietf.org/html/rfc6749#section-7.2 """ try: self.request_validator.validate_request(request) except errors.OAuth2Error as e: return add_params_to_uri(request.redirect_uri, e.twotuples, fragment=True) token = token_handler(request, refresh_token=False) return add_params_to_uri(request.redirect_uri, token.items(), fragment=True), {}, None
def request(self, url, data=None, headers=None, format='urlencoded', method='GET', content_type=None, token=None): """ Sends a request to the remote server with OAuth tokens attached. :param data: the data to be sent to the server. :param headers: an optional dictionary of headers. :param format: the format for the `data`. Can be `urlencoded` for URL encoded data or `json` for JSON. :param method: the HTTP request method to use. :param content_type: an optional content type. If a content type is provided, the data is passed as it, and the `format` is ignored. :param token: an optional token to pass, if it is None, token will be generated by tokengetter. """ headers = dict(headers or {}) if token is None: token = self.get_request_token() client = self.make_client(token) url = self.expand_url(url) if method == 'GET': assert format == 'urlencoded' if data: url = add_params_to_uri(url, data) data = None else: if content_type is None: data, content_type = encode_request_data(data, format) if content_type is not None: headers['Content-Type'] = content_type if self.request_token_url: # oauth1 uri, headers, body = client.sign( url, http_method=method, body=data, headers=headers ) else: # oauth2 uri, headers, body = client.add_token( url, http_method=method, body=data, headers=headers ) if hasattr(self, 'pre_request'): # This is designed for some rubbish services like weibo. # Since they don't follow the standards, we need to # change the uri, headers, or body. uri, headers, body = self.pre_request(uri, headers, body) if body: data = to_bytes(body, self.encoding) else: data = None resp, content = self.http_request( uri, headers, data=to_bytes(body, self.encoding), method=method ) return OAuthResponse(resp, content, self.content_type)
def request(self, url, data=None, headers=None, format='urlencoded', method='GET', content_type=None, token=None): """ Sends a request to the remote server with OAuth tokens attached. :param data: the data to be sent to the server. :param headers: an optional dictionary of headers. :param format: the format for the `data`. Can be `urlencoded` for URL encoded data or `json` for JSON. :param method: the HTTP request method to use. :param content_type: an optional content type. If a content type is provided, the data is passed as it, and the `format` is ignored. :param token: an optional token to pass, if it is None, token will be generated by tokengetter. """ headers = dict(headers or {}) if token is None: token = self.get_request_token() client = self.make_client(token) url = self.expand_url(url) if method == 'GET': assert format == 'urlencoded' if data: url = add_params_to_uri(url, data) data = None else: if content_type is None: data, content_type = encode_request_data(data, format) if content_type is not None: headers['Content-Type'] = content_type if self.request_token_url: # oauth1 uri, headers, body = client.sign( url, http_method=method, body=data, headers=headers ) else: # oauth2 uri, headers, body = client.add_token( url, http_method=method, body=data, headers=headers ) if hasattr(self, 'pre_request'): # This is desgined for some rubbish service like weibo. # Since they don't follow the standards, we need to # change the uri, headers, or body. uri, headers, body = self.pre_request(uri, headers, body) if body: data = to_bytes(body, self.encoding) else: data = None resp, content = self.http_request( uri, headers, data=data, method=method ) return OAuthResponse(resp, content, self.content_type)
def create_authorization_response(self, uri, http_method='GET', body=None, headers=None, realms=None, credentials=None): """Create an authorization response, with a new request token if valid. :param uri: The full URI of the token request. :param http_method: A valid HTTP verb, i.e. GET, POST, PUT, HEAD, etc. :param body: The request body as a string. :param headers: The request headers as a dict. :param credentials: A list of credentials to include in the verifier. :returns: A tuple of 4 elements. 1. The URI to be used to redirect the user back to client. 2. A dict of headers to set on the response. 3. The response body as a string. 4. The response status code as an integer. An example of a valid request:: >>> from your_validator import your_validator >>> from oauthlib.oauth1 import RequestTokenEndpoint >>> endpoint = RequestTokenEndpoint(your_validator) >>> u, h, b, s = endpoint.create_request_token_response( ... 'https://your.provider/request_token?foo=bar', ... headers={ ... 'Authorization': 'OAuth realm=movies user, oauth_....' ... }, ... credentials={ ... 'extra': 'argument', ... }) >>> u 'https://the.client/callback?oauth_verifier=...&mextra=argument' >>> h {} >>> b '' >>> s 302 """ request = self._create_request(uri, http_method=http_method, body=body, headers=headers) if not request.resource_owner_key: raise errors.InvalidRequestError('request.resource_owner_key must be set after ' 'request token verification.') if not self.request_validator.verify_request_token( request.resource_owner_key, request): raise errors.InvalidClientError() request.realms = realms if (request.realms and not self.request_validator.verify_realms( request.resource_owner_key, request.realms, request)): raise errors.InvalidRequestError( description=('User granted access to realms outside of ' 'what the client may request.')) redirect_uri = self.request_validator.get_redirect_uri( request.resource_owner_key, request) verifier = self.create_verifier(request, credentials or {}) uri = add_params_to_uri(redirect_uri, verifier.items()) return uri, {}, None, 302
def get_authorization_url(self, request_token): """ Returns authorization url to redirect user to to obtain token Second step of OAuth1 """ return add_params_to_uri(self.authorization_url, params={"oauth_token": request_token.get('oauth_token')})
def authorized(self, request_token): """Create a verifier for an user authorized client""" verifier = generate_token(length=self.verifier_length[1]) self.save_verifier(request_token, verifier) response = [(u'oauth_token', request_token), (u'oauth_verifier', verifier)] callback = self.get_callback(request_token) return redirect(add_params_to_uri(callback, response))
def decorated(*args, **kwargs): # raise if server not implemented server = self.server uri, http_method, body, headers = extract_params() if request.method in ('GET', 'HEAD'): redirect_uri = request.args.get('redirect_uri', self.error_uri) log.debug('Found redirect_uri %s.', redirect_uri) try: ret = server.validate_authorization_request( uri, http_method, body, headers) scopes, credentials = ret kwargs['scopes'] = scopes kwargs.update(credentials) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return self._on_exception(e, e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) # on auth error, we should preserve state if it's present according to RFC 6749 state = request.values.get('state') if state and not e.state: e.state = state # set e.state so e.in_uri() can add the state query parameter to redirect uri return self._on_exception(e, e.in_uri(redirect_uri)) except Exception as e: log.exception(e) return self._on_exception( e, add_params_to_uri(self.error_uri, {'error': str(e)})) else: redirect_uri = request.values.get('redirect_uri', self.error_uri) try: rv = f(*args, **kwargs) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return self._on_exception(e, e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) # on auth error, we should preserve state if it's present according to RFC 6749 state = request.values.get('state') if state and not e.state: e.state = state # set e.state so e.in_uri() can add the state query parameter to redirect uri return self._on_exception(e, e.in_uri(redirect_uri)) if not isinstance(rv, bool): # if is a response or redirect return rv if not rv: # denied by user e = oauth2.AccessDeniedError(state=request.values.get('state')) return self._on_exception(e, e.in_uri(redirect_uri)) return self.confirm_authorization_request()
def prepare_authorization_response(self, request, token, headers, body, status): """Place token according to response mode. Base classes can define a default response mode for their authorization response by overriding the static `default_response_mode` member. :param request: OAuthlib request. :type request: oauthlib.common.Request :param token: :param headers: :param body: :param status: """ request.response_mode = request.response_mode or self.default_response_mode if request.response_mode not in ("query", "fragment"): log.debug( "Overriding invalid response mode %s with %s", request.response_mode, self.default_response_mode, ) request.response_mode = self.default_response_mode token_items = token.items() if request.response_type == "none": state = token.get("state", None) if state: token_items = [("state", state)] else: token_items = [] if request.response_mode == "query": headers["Location"] = add_params_to_uri( request.redirect_uri, token_items, fragment=False ) return headers, body, status if request.response_mode == "fragment": headers["Location"] = add_params_to_uri( request.redirect_uri, token_items, fragment=True ) return headers, body, status raise NotImplementedError("Subclasses must set a valid default_response_mode")
def prepare_grant_uri(uri, client_id, response_type, redirect_uri=None, scope=None, state=None, **kwargs): """Prepare the authorization grant request URI. The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the "application/x-www-form-urlencoded" format as defined by [W3C.REC-html401-19991224]: response_type REQUIRED. Value MUST be set to "code". client_id REQUIRED. The client identifier as described in `Section 2.2`_. redirect_uri OPTIONAL. As described in `Section 3.1.2`_. scope OPTIONAL. The scope of the access request as described by `Section 3.3`_. state RECOMMENDED. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery as described in `Section 10.12`_. GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com .. _`W3C.REC-html401-19991224`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#ref-W3C.REC-html401-19991224 .. _`Section 2.2`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-2.2 .. _`Section 3.1.2`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-3.1.2 .. _`Section 3.3`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-3.3 .. _`section 10.12`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-10.12 """ if not uri.startswith('https://'): raise InsecureTransportError() params = [(('response_type', response_type)), (('client_id', client_id))] if redirect_uri: params.append(('redirect_uri', redirect_uri)) if scope: params.append(('scope', list_to_scope(scope))) if state: params.append(('state', state)) for k in kwargs: if kwargs[k]: params.append((unicode_type(k), kwargs[k])) return add_params_to_uri(uri, params)
def prepare_grant_uri(uri, client_id, response_type, redirect_uri=None, scope=None, state=None, **kwargs): """Prepare the authorization grant request URI. The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the ``application/x-www-form-urlencoded`` format as defined by [`W3C.REC-html401-19991224`_]: :param response_type: To indicate which OAuth 2 grant/flow is required, "code" and "token". :param client_id: The client identifier as described in `Section 2.2`_. :param redirect_uri: The client provided URI to redirect back to after authorization as described in `Section 3.1.2`_. :param scope: The scope of the access request as described by `Section 3.3`_. :param state: An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery as described in `Section 10.12`_. :param kwargs: Extra arguments to embed in the grant/authorization URL. An example of an authorization code grant authorization URL: .. code-block:: http GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com .. _`W3C.REC-html401-19991224`: http://tools.ietf.org/html/rfc6749#ref-W3C.REC-html401-19991224 .. _`Section 2.2`: http://tools.ietf.org/html/rfc6749#section-2.2 .. _`Section 3.1.2`: http://tools.ietf.org/html/rfc6749#section-3.1.2 .. _`Section 3.3`: http://tools.ietf.org/html/rfc6749#section-3.3 .. _`section 10.12`: http://tools.ietf.org/html/rfc6749#section-10.12 """ if not uri.startswith('https://'): raise InsecureTransportError() params = [(('response_type', response_type)), (('client_id', client_id))] if redirect_uri: params.append(('redirect_uri', redirect_uri)) if scope: params.append(('scope', list_to_scope(scope))) if state: params.append(('state', state)) for k in kwargs: if kwargs[k]: params.append((unicode_type(k), kwargs[k])) return add_params_to_uri(uri, params)
def prepare_bearer_uri(token, uri): """Add a `Bearer Token`_ to the request URI. Not recommended, use only if client can't use authorization header or body. http://www.example.com/path?access_token=h480djs93hd8 .. _`Bearer Token`: http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-18 """ return add_params_to_uri(uri, [(('access_token', token))])
def prepare_bearer_uri(token, uri): """Add a `Bearer Token`_ to the request URI. Not recommended, use only if client can't use authorization header or body. http://www.example.com/path?access_token=h480djs93hd8 .. _`Bearer Token`: http://tools.ietf.org/html/rfc6750 """ return add_params_to_uri(uri, [(('access_token', token))])
def process_exception(self, request, exc, *args, **kwargs): if isinstance(exc, oauth2.FatalClientError): return redirect(exc.in_uri(self.error_uri)) elif isinstance(exc, oauth2.OAuth2Error): return redirect(exc.in_uri(self.redirect_uri or self.error_uri)) elif isinstance(exc, oauth2.AccessDeniedError): return redirect(exc.in_uri(self.redirect_uri)) return redirect( add_params_to_uri(self.error_uri, {'error': text_type(exc)}))
def decorated(*args, **kwargs): # raise if server not implemented server = self.server uri, http_method, body, headers = extract_params() if request.method in ('GET', 'HEAD'): redirect_uri = request.args.get('redirect_uri', self.error_uri) log.debug('Found redirect_uri %s.', redirect_uri) try: ret = server.validate_authorization_request( uri, http_method, body, headers) scopes, credentials = ret kwargs['scopes'] = scopes kwargs.update(credentials) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) return redirect(e.in_uri(redirect_uri)) except Exception as e: log.exception(e) return redirect( add_params_to_uri(self.error_uri, {'error': str(e)})) else: redirect_uri = request.values.get('redirect_uri', self.error_uri) try: rv = f(*args, **kwargs) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e, exc_info=True) return redirect(e.in_uri(self.error_uri)) except oauth2.OAuth2Error as e: log.debug('OAuth2Error: %r', e, exc_info=True) return redirect(e.in_uri(redirect_uri)) if not isinstance(rv, bool): # if is a response or redirect return rv if not rv: # denied by user e = oauth2.AccessDeniedError() return redirect(e.in_uri(redirect_uri)) # Pass the scopes list as a string to match the format of a URL request default_scopes = "" # default fallback if no scopes provided. try: default_scopes = " ".join(scopes) except UnboundLocalError: pass #Just use the default of empty scopes, which will likely return an error later #if 'request' in kwargs and hasattr(kwargs['request'], scopes): # default_scopes = " ".join(kwargs['request'].scopes) return self.confirm_authorization_request(default_scopes)
def prepare_token_revocation_request(url, token, token_type_hint="access_token", callback=None, body='', **kwargs): """Prepare a token revocation request. The client constructs the request by including the following parameters using the "application/x-www-form-urlencoded" format in the HTTP request entity-body: token REQUIRED. The token that the client wants to get revoked. token_type_hint OPTIONAL. A hint about the type of the token submitted for revocation. Clients MAY pass this parameter in order to help the authorization server to optimize the token lookup. If the server is unable to locate the token using the given hint, it MUST extend its search across all of its supported token types. An authorization server MAY ignore this parameter, particularly if it is able to detect the token type automatically. This specification defines two such values: * access_token: An access token as defined in [RFC6749], `Section 1.4`_ * refresh_token: A refresh token as defined in [RFC6749], `Section 1.5`_ Specific implementations, profiles, and extensions of this specification MAY define other values for this parameter using the registry defined in `Section 4.1.2`_. .. _`Section 1.4`: http://tools.ietf.org/html/rfc6749#section-1.4 .. _`Section 1.5`: http://tools.ietf.org/html/rfc6749#section-1.5 .. _`Section 4.1.2`: http://tools.ietf.org/html/rfc7009#section-4.1.2 """ if not is_secure_transport(url): raise InsecureTransportError() params = [('token', token)] if token_type_hint: params.append(('token_type_hint', token_type_hint)) for k in kwargs: if kwargs[k]: params.append((unicode_type(k), kwargs[k])) headers = {'Content-Type': 'application/x-www-form-urlencoded'} if callback: params.append(('callback', callback)) return add_params_to_uri(url, params), headers, body else: return url, headers, add_params_to_qs(body, params)
def prepare_token_revocation_request(url, token, token_type_hint="access_token", callback=None, body='', **kwargs): """Prepare a token revocation request. The client constructs the request by including the following parameters using the "application/x-www-form-urlencoded" format in the HTTP request entity-body: :param token: REQUIRED. The token that the client wants to get revoked. :param token_type_hint: OPTIONAL. A hint about the type of the token submitted for revocation. Clients MAY pass this parameter in order to help the authorization server to optimize the token lookup. If the server is unable to locate the token using the given hint, it MUST extend its search across all of its supported token types. An authorization server MAY ignore this parameter, particularly if it is able to detect the token type automatically. This specification defines two values for `token_type_hint`: * access_token: An access token as defined in [RFC6749], `Section 1.4`_ * refresh_token: A refresh token as defined in [RFC6749], `Section 1.5`_ Specific implementations, profiles, and extensions of this specification MAY define other values for this parameter using the registry defined in `Section 4.1.2`_. .. _`Section 1.4`: https://tools.ietf.org/html/rfc6749#section-1.4 .. _`Section 1.5`: https://tools.ietf.org/html/rfc6749#section-1.5 .. _`Section 4.1.2`: https://tools.ietf.org/html/rfc7009#section-4.1.2 """ if not is_secure_transport(url): raise InsecureTransportError() params = [('token', token)] if token_type_hint: params.append(('token_type_hint', token_type_hint)) for k in kwargs: if kwargs[k]: params.append((unicode_type(k), kwargs[k])) headers = {'Content-Type': 'application/x-www-form-urlencoded'} if callback: params.append(('callback', callback)) return add_params_to_uri(url, params), headers, body else: return url, headers, add_params_to_qs(body, params)
def decorated(*args, **kwargs): # raise if server not implemented server = self.server uri, http_method, body, headers = extract_params() if request.method == 'GET': redirect_uri = request.args.get('redirect_uri', None) log.debug('Found redirect_uri %s.', redirect_uri) try: ret = server.validate_authorization_request( uri, http_method, body, headers) scopes, credentials = ret kwargs['scopes'] = scopes kwargs.update(credentials) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e) return redirect(e.in_uri(self.error_uri)) except Exception as e: return redirect( add_params_to_uri(self.error_uri, {'error': e.message})) else: redirect_uri = request.values.get('redirect_uri', None) try: rv = f(*args, **kwargs) except oauth2.FatalClientError as e: log.debug('Fatal client error %r', e) return redirect(e.in_uri(self.error_uri)) except Exception as e: return redirect( add_params_to_uri(self.error_uri, {'error': e.message})) if not isinstance(rv, bool): # if is a response or redirect return rv if not rv: # denied by user e = oauth2.AccessDeniedError() return redirect(e.in_uri(redirect_uri)) return self.confirm_authorization_request()
def authorized(self, request_token): """Create a verifier for an user authorized client""" verifier = generate_token(length=self.verifier_length[1]) self.save_verifier(request_token, verifier) response = [ (u'oauth_token', request_token), (u'oauth_verifier', verifier) ] callback = self.get_callback(request_token) return redirect(add_params_to_uri(callback, response))
def valid_authentication(self, kwargs): user, auth = False, False credentials = self._get_credentials(kwargs) if kwargs.get('oauth_signature'): kwargs['for_request_data'] = True key, auth, invalid = self._check_credentials(kwargs) if invalid: return False, False, invalid user = auth.user_id elif credentials.get('access_token'): access_token = request.env['auth.access.token'].sudo().search([('access_token', '=', credentials['access_token'])]) if not access_token or datetime.strptime(access_token.access_token_validity ,DEFAULT_SERVER_DATETIME_FORMAT) < datetime.now(): return False, False, self.get_response(401, str(401), {'code': 401, 'message': 'Access Token Invalid'}) user, auth = access_token.auth_id.user_id, access_token.auth_id elif not request.httprequest.headers.get('Authorization') and request.env.user.id!=3: user = request.env.user elif not request.httprequest.headers.get('Authorization'): redirect_url = add_params_to_uri(request.httprequest.base_url, kwargs) return False, False, werkzeug.utils.redirect(add_params_to_uri('web/login', {'redirect': redirect_url})) return auth, user, False
def get_correlations(self, user, paths, group_by, start, thresholds = ['> 0.5', '< -0.5'], continuous = False): params = [ ('paths', json.dumps(paths)), ('minDate', start.isoformat()), ('thresholds', json.dumps(thresholds)), ('groupBy', json.dumps(group_by)), ('continuous', json.dumps(continuous))] return json.loads(self.get(add_params_to_uri( 'correlations.json', params), user = user).content)
def create_session(self, prompt: bool = False, params: Dict[str, str] = None): if params is None: params = dict() if 'http://' in self.redirect_url: os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = 'true' authorization_url, state = self._make_session().authorization_url(DISCORD_AUTHORIZATION_BASE_URL) session['DISCORD_OAUTH2_STATE'] = state # print(redirect(self.MyClient._make_session().authorization_url(DISCORD_AUTHORIZATION_BASE_URL))) prompt = 'consent' if prompt else 'none' params.update(prompt=prompt) authorization_url = add_params_to_uri(authorization_url, params) return redirect(authorization_url)
def prepare_grant_uri(uri, client_id, response_type, redirect_uri=None, scope=None, state=None, **kwargs): """Prepare the authorization grant request URI. The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the "application/x-www-form-urlencoded" format as defined by [W3C.REC-html401-19991224]: response_type REQUIRED. Value MUST be set to "code". client_id REQUIRED. The client identifier as described in `Section 2.2`_. redirect_uri OPTIONAL. As described in `Section 3.1.2`_. scope OPTIONAL. The scope of the access request as described by `Section 3.3`_. state RECOMMENDED. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery as described in `Section 10.12`_. GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz &redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1 Host: server.example.com .. _`W3C.REC-html401-19991224`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#ref-W3C.REC-html401-19991224 .. _`Section 2.2`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-2.2 .. _`Section 3.1.2`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-3.1.2 .. _`Section 3.3`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-3.3 .. _`section 10.12`: http://tools.ietf.org/html/draft-ietf-oauth-v2-28#section-10.12 """ if not uri.startswith('https://'): raise InsecureTransportError() params = [(('response_type', response_type)), (('client_id', client_id))] if redirect_uri: params.append(('redirect_uri', redirect_uri)) if scope: params.append(('scope', list_to_scope(scope))) if state: params.append(('state', state)) for k in kwargs: if kwargs[k]: params.append((unicode_type(k), kwargs[k])) return add_params_to_uri(uri, params)
def create_token_response(self, request, token_handler): try: if not request.scopes: raise ValueError('Scopes must be set on post auth.') self.validate_token_request(request) except errors.FatalClientError as e: # log raise except errors.OAuth2Error as e: # log return { 'Location': common.add_params_to_uri(request.redirect_uri, e.twotuples, fragment=True) }, None, 302 token = token_handler.create_token(request, refresh_token=False) return { 'Location': common.add_params_to_uri(request.redirect_uri, token.items(), fragment=True) }, None, 302
async def signed_request(self, method: str, endpoint: str, params: Optional[List[Tuple[str, str]]] = None, data: Optional[Dict[str, str]] = None, json: Optional[Any] = None, headers: Optional[Dict[str, str]] = None, **kwargs) -> aiohttp.ClientResponse: url = self.api_base_url + endpoint if data: _, signed_headers, _ = self.oauth_client.sign( add_params_to_uri(url, params), http_method=method, body=data, headers=headers ) return await self.session.request(method, url, params=params, data=data, headers=signed_headers) elif json: # Since it is JSON, body apparently doesn't matter when signing _, signed_headers, _ = self.oauth_client.sign( add_params_to_uri(url, params), http_method=method, headers=headers ) return await self.session.request(method, url, params=params, json=json, headers=signed_headers) else: _, signed_headers, _ = self.oauth_client.sign( add_params_to_uri(url, params), http_method=method, headers=headers ) return await self.session.request(method, url, params=params, headers=signed_headers)
def _non_compliant_param_name(url, headers, data): # If the user has already specified the token in the URL # then there's nothing to do. # If the specified token is different from ``session.access_token``, # we assume the user intends to override the access token. url_query = dict(parse_qs(urlparse(url).query)) token = url_query.get("access_token") if token: # Nothing to do, just return. return url, headers, data token = [('access_token', session.access_token)] url = add_params_to_uri(url, token) return url, headers, data
def prepare_authorization_response(self, request, token, headers, body, status): """Place token according to response mode. Base classes can define a default response mode for their authorization response by overriding the static `default_response_mode` member. """ request.response_mode = request.response_mode or self.default_response_mode if request.response_mode not in ('query', 'fragment'): log.debug('Overriding invalid response mode %s with %s', request.response_mode, self.default_response_mode) request.response_mode = self.default_response_mode token_items = token.items() if request.response_type == 'none': state = token.get('state', None) if state: token_items = [('state', state)] else: token_items = [] if request.response_mode == 'query': headers['Location'] = add_params_to_uri(request.redirect_uri, token_items, fragment=False) return headers, body, status if request.response_mode == 'fragment': headers['Location'] = add_params_to_uri(request.redirect_uri, token_items, fragment=True) return headers, body, status raise NotImplementedError( 'Subclasses must set a valid default_response_mode')
def endpoint__confirm_authorization_request(self): """ When consumer confirm the authorization after ``endpoint__validate_authorization_request`` These are being pulled from the `pyramid_request.params` multidict TODO: should these be POST only? The RFC states `endpoint__validate_authorization_request` must be GET, but is silent to this submission this can be toggled via `confirm_authorization_request__post_only` """ params_source = self.pyramid_request.params if self.confirm_authorization_request__post_only: params_source = self.pyramid_request.POST scope = params_source.get("scope") or "" scopes = scope.split() credentials = dict( client_id=params_source.get("client_id"), redirect_uri=params_source.get("redirect_uri", None), response_type=params_source.get("response_type", None), state=params_source.get("state", None), ) log.debug("Fetched credentials from request %r.", credentials) redirect_uri = credentials.get("redirect_uri") log.debug("Found redirect_uri %s.", redirect_uri) uri, http_method, body, headers = extract_params(self.pyramid_request) try: ret = self.server.create_authorization_response( uri, http_method, body, headers, scopes, credentials) log.debug("Authorization successful.") return create_response(*ret) except oauth2.FatalClientError as exc: log.debug("Fatal client error %r", exc, exc_info=True) # return redirect(exc.in_uri(self.error_uri)) return HTTPSeeOther(exc.in_uri(self.error_uri)) except oauth2.OAuth2Error as exc: log.debug("OAuth2Error: %r", exc, exc_info=True) # return redirect(exc.in_uri(redirect_uri or self.error_uri)) return HTTPSeeOther(exc.in_uri(redirect_uri or self.error_uri)) except Exception as exc: log.critical(exc) # return redirect(add_params_to_uri( # self.error_uri, {'error': str(exc)} # )) return HTTPSeeOther( add_params_to_uri(self.error_uri, {"error": str(exc)}))
def prepare_request(uri, headers=None, data=None, method=None): """Make request parameters right.""" if headers is None: headers = {} if data and not method: method = 'POST' elif not method: method = 'GET' if method == 'GET' and data: uri = add_params_to_uri(uri, data) data = None return uri, headers, data, method
def decorated(*args, **kwargs): if request.method == 'POST': if not f(*args, **kwargs): uri = add_params_to_uri(self.error_uri, [('error', 'denied')]) return redirect(uri) return self.confirm_authorization_request() server = self.server uri, http_method, body, headers = extract_params() try: realms, credentials = server.get_realms_and_credentials( uri, http_method=http_method, body=body, headers=headers) kwargs['realms'] = realms kwargs.update(credentials) return f(*args, **kwargs) except errors.OAuth1Error as e: return redirect(e.in_uri(self.error_uri)) except errors.InvalidClientError as e: return redirect(e.in_uri(self.error_uri)) except Exception as e: return redirect( add_params_to_uri(self.error_uri, {'error': e.message}))
def prepare_request(uri, headers=None, data=None, method=None): """Make request parameters right.""" if headers is None: headers = {} if data and not method: method = 'POST' elif not method: method = 'GET' if method == 'GET' and data: uri = add_params_to_uri(uri, data) data = None return uri, headers, data, method
def authorization_url(self, url, request_token=None, **kwargs): """Create an authorization URL by appending request_token and optional kwargs to url. This is the second step in the OAuth 1 workflow. The user should be redirected to this authorization URL, grant access to you, and then be redirected back to you. The redirection back can either be specified during client registration or by supplying a callback URI per request. :param url: The authorization endpoint URL. :param request_token: The previously obtained request token. :param kwargs: Optional parameters to append to the URL. :returns: The authorization URL with new parameters embedded. An example using a registered default callback URI. >>> request_token_url = 'https://api.twitter.com/oauth/request_token' >>> authorization_url = 'https://api.twitter.com/oauth/authorize' >>> oauth_session = OAuth1Session('client-key', client_secret='secret') >>> oauth_session.fetch_request_token(request_token_url) { 'oauth_token': 'sdf0o9823sjdfsdf', 'oauth_token_secret': '2kjshdfp92i34asdasd', } >>> oauth_session.authorization_url(authorization_url) 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf' >>> oauth_session.authorization_url(authorization_url, foo='bar') 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf&foo=bar' An example using an explicit callback URI. >>> request_token_url = 'https://api.twitter.com/oauth/request_token' >>> authorization_url = 'https://api.twitter.com/oauth/authorize' >>> oauth_session = OAuth1Session('client-key', client_secret='secret', callback_uri='https://127.0.0.1/callback') >>> oauth_session.fetch_request_token(request_token_url) { 'oauth_token': 'sdf0o9823sjdfsdf', 'oauth_token_secret': '2kjshdfp92i34asdasd', } >>> oauth_session.authorization_url(authorization_url) 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf&oauth_callback=https%3A%2F%2F127.0.0.1%2Fcallback' """ kwargs[ 'oauth_token'] = request_token or self._client.client.resource_owner_key log.debug('Adding parameters %s to url %s', kwargs, url) return add_params_to_uri(url, kwargs.items())
def get_chart_data(self, user, path, group_by, start = None, end = None, continuous = True): params = [ ('groupBy', json.dumps(group_by)) ] if start: params.append(('minDate', start)) if end: params.append(('maxDate', end)) if continuous: params.append(('continuous', 'true')) return self.get(add_params_to_uri( '%s.json' % path, params), user = user).content
def test_pre_auth_valid(self): """Ensure auth code and implicit grant can authorize. Will test both provided and default redirect uris and scopes. """ valid_params = ({ 'client_id': 'bar', 'response_type': 'token', }, { 'client_id': 'bar', 'response_type': 'token', 'redirect_uri': 'https://localhost/callback', }, { 'client_id': 'bar', 'response_type': 'token', 'redirect_uri': 'https://localhost/callback', 'scope': 'profile pictures', }, { 'client_id': 'bar', 'response_type': 'token', 'scope': 'profile pictures', }, { 'client_id': 'foo', 'response_type': 'code', }, { 'client_id': 'foo', 'response_type': 'code', 'redirect_uri': 'https://localhost/cb', }, { 'client_id': 'foo', 'response_type': 'code', 'redirect_uri': 'https://localhost/cb', 'scope': 'profile movies', }, { 'client_id': 'foo', 'response_type': 'code', 'scope': 'profile movies', }) for params in valid_params: c = Client() c.login(username='******', password='******') r = c.get(add_params_to_uri(self.auth, params.items()), follow=True) self.assertEqual(r.redirect_chain, []) self.assertEqual(r.status_code, 200)
def authorization_url(self, url, request_token=None, **kwargs): """Create an authorization URL by appending request_token and optional kwargs to url. This is the second step in the OAuth 1 workflow. The user should be redirected to this authorization URL, grant access to you, and then be redirected back to you. The redirection back can either be specified during client registration or by supplying a callback URI per request. :param url: The authorization endpoint URL. :param request_token: The previously obtained request token. :param kwargs: Optional parameters to append to the URL. :returns: The authorization URL with new parameters embedded. An example using a registered default callback URI. >>> request_token_url = 'https://api.twitter.com/oauth/request_token' >>> authorization_url = 'https://api.twitter.com/oauth/authorize' >>> oauth_session = OAuth1Session('client-key', client_secret='secret') >>> oauth_session.fetch_request_token(request_token_url) { 'oauth_token': 'sdf0o9823sjdfsdf', 'oauth_token_secret': '2kjshdfp92i34asdasd', } >>> oauth_session.authorization_url(authorization_url) 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf' >>> oauth_session.authorization_url(authorization_url, foo='bar') 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf&foo=bar' An example using an explicit callback URI. >>> request_token_url = 'https://api.twitter.com/oauth/request_token' >>> authorization_url = 'https://api.twitter.com/oauth/authorize' >>> oauth_session = OAuth1Session('client-key', client_secret='secret', callback_uri='https://127.0.0.1/callback') >>> oauth_session.fetch_request_token(request_token_url) { 'oauth_token': 'sdf0o9823sjdfsdf', 'oauth_token_secret': '2kjshdfp92i34asdasd', } >>> oauth_session.authorization_url(authorization_url) 'https://api.twitter.com/oauth/authorize?oauth_token=sdf0o9823sjdfsdf&oauth_callback=https%3A%2F%2F127.0.0.1%2Fcallback' """ kwargs["oauth_token"] = request_token or self._client.client.resource_owner_key log.debug("Adding parameters %s to url %s", kwargs, url) return add_params_to_uri(url, kwargs.items())
def exchange_token(self, token): """Authorizes user by exchanging short-lived token for long-lived.""" url = self.expand_url(self.access_token_url) data = dict(client_id=self.consumer_key, # XXX: Add appsecret_proof client_secret=self.consumer_secret, fb_exchange_token=token, grant_type='fb_exchange_token') url = oauth_common.add_params_to_uri(url, data) resp, content = self.http_request(url) data = f_oauth_client.parse_response(resp, content, self.content_type) if resp.code not in (200, 201): try: message = data['error']['message'] except (KeyError, TypeError): message = 'Failed to exchange token for {}'.format(self.name) raise f_oauth_client.OAuthException( message, type='token_exchange_failed', data=data) return data
def passthrough(user, apis, service, endpoint): if request.args: params = filter(lambda param: param[0] not in OAUTH_PARAMS, request.args.items()) endpoint = add_params_to_uri(endpoint, params) if request.method == 'GET': api_call = apis[service].get(endpoint, user=user) elif request.method == 'POST': api_call = apis[service].post( endpoint, user=user, data=filter(lambda param: param[0] not in OAUTH_PARAMS, request.form.items())) else: abort(400) return api_call.response.content
def endpoint__revoke_token(self): """ handle the token endpoint """ self._protected_https_only() self._protected_post_only() uri, http_method, body, headers = extract_params(self.pyramid_request) try: ret = self.server.create_revocation_response( uri, http_method, body, headers) log.debug("Revocation successful.") return create_response(*ret) except Exception as exc: print("Exception", exc) log.critical(exc) return HTTPSeeOther( add_params_to_uri(self.error_uri, {"error": str(exc)}))
def auth(self, **kwargs): """ Redirect to redirect uri attached with code and state, if request is valid. """ obj = request.env['auth.auth'].sudo() auth_code = obj.generate_token() kwargs.update(request.httprequest.data or {}) auth_auth = obj.search([('consumer_key', '=', kwargs.get('client_id'))]) if not auth_auth: return self.get_response(401, '401', {"code":401, "message": "Invalid Credentials."}) redirect_uri = urllib2.unquote(kwargs.get('redirect_uri')) if redirect_uri not in [uri.url for uri in auth_auth.redirect_uris]: return self.get_response(400, '400', {"code":400, "message": "redirect uri mismatch."}) if auth_auth.user_id.id != request.env.uid: return self.get_response(401, '401', {"code":401, "message": "Invalid User."}) auth_auth.auth_code_ids = [(0, 0, {'auth_code': auth_code, 'used': False})] return werkzeug.utils.redirect(add_params_to_uri(redirect_uri, {'code': auth_code, 'state': kwargs.get('state')}))
def auth_authorize(self, **kwargs): """ Redirect to redirect uri attached with code and state, if request is valid. """ auth_obj = request.env['auth.auth'] auth_request_token_obj = request.env['auth.request.token'] if kwargs.get('oauth_token'): user = auth_obj.get_authorize_user_request_token( kwargs.get('oauth_token')) if user: request_token = auth_request_token_obj.get_request_token( kwargs.get('oauth_token'), auth=user) request_token.token_verifier = auth_request_token_obj.generate_verifier( ) if request.uid != user.user_id.id and request.uid != 3: return self.get_response( 400, '400', { 'error': { 'code': '400', 'message': 'You are not authorized user for these credentials.' } }) if request_token.callback_uri: return werkzeug.utils.redirect( add_params_to_uri( urllib2.unquote(request_token.callback_uri), { 'oauth_verifier': request_token.token_verifier, 'oauth_token': request_token.request_token })) else: return self.get_response( 200, '200', { 'oauth_verifier': request_token.token_verifier, 'oauth_token': request_token.request_token }) return self.get_response( 400, '400', {'error': { 'code': '400', 'message': 'Insufficient Data' }})
def prepare_request_uri(self, uri, scope=None, **kwargs): if not is_secure_transport(uri): raise InsecureTransportError() scope = self.scope if scope is None else scope params = [(('client_id', self.client_id)), (('grant_type', self.grant_type))] if self.client_secret is not None: params.append(('client_secret', self.client_secret)) if scope: params.append(('scope', list_to_scope(scope))) for k in kwargs: if kwargs[k]: params.append((str(k), kwargs[k])) return add_params_to_uri(uri, params)
def confirm_authorization_request(self): """When consumer confirm the authrozation.""" server = self.server uri, http_method, body, headers = extract_params() try: realms, credentials = server.get_realms_and_credentials( uri, http_method=http_method, body=body, headers=headers) ret = server.create_authorization_response(uri, http_method, body, headers, realms, credentials) log.debug('Authorization successful.') return create_response(*ret) except errors.OAuth1Error as e: return redirect(e.in_uri(self.error_uri)) except errors.InvalidClientError as e: return redirect(e.in_uri(self.error_uri)) except Exception as e: return redirect( add_params_to_uri(self.error_uri, {'error': e.message}))
def confirm_authorization_request(self): """When consumer confirm the authrozation.""" server = self.server uri, http_method, body, headers = extract_params() try: realms, credentials = server.get_realms_and_credentials( uri, http_method=http_method, body=body, headers=headers ) ret = server.create_authorization_response( uri, http_method, body, headers, realms, credentials ) log.debug('Authorization successful.') return create_response(*ret) except errors.OAuth1Error as e: return redirect(e.in_uri(self.error_uri)) except errors.InvalidClientError as e: return redirect(e.in_uri(self.error_uri)) except Exception as e: return redirect(add_params_to_uri( self.error_uri, {'error': e.message} ))
def passthrough(user, apis, service, endpoint): if request.args: params = filter( lambda param: param[0] not in OAUTH_PARAMS, request.args.items()) endpoint = add_params_to_uri(endpoint, params) if request.method == 'GET': api_call = apis[service].get(endpoint, user = user) elif request.method == 'POST': api_call = apis[service].post( endpoint, user = user, data = filter( lambda param: param[0] not in OAUTH_PARAMS, request.form.items() ) ) else: abort(400) return api_call.response.content
def get_posts(self): all_posts = [] if self._latest_position: self.set_min_position_param(self._latest_position) i = 0 keep_requesting = True while keep_requesting and self.request_uri: posts = self.get_posts_content(self.api.get(add_params_to_uri( self.request_uri, self.params.items()), user = self.user)) if posts and not 'errors' in posts: self.set_max_position_param(self.get_position(posts[-1])) all_posts.extend(posts) i += 1 keep_requesting = i < self.max_requests else: keep_requesting = self.keep_requesting_when_no_posts_returned() return all_posts
def wrapper(*args, **kwargs): assert self._oauthlib, "BottleOAuth2 not initialized with OAuthLib" uri, http_method, body, headers = extract_params( bottle.request) scope = bottle.request.params.get('scope', '').split(' ') try: resp_headers, resp_body, resp_status = self._oauthlib.create_authorization_response( uri, http_method=http_method, body=body, headers=headers, scopes=scope) except FatalClientError as e: if self._error_uri: raise bottle.HTTPResponse( status=302, headers={ "Location": add_params_to_uri( self._error_uri, { 'error': e.error, 'error_description': e.description }) }) raise e except OAuth2Error as e: resp_headers, resp_body, resp_status = e.headers, e.json, e.status_code set_response(bottle.request, bottle.response, resp_status, resp_headers, resp_body) func_response = f(*args, **kwargs) if func_response: return func_response return bottle.response
def create_authorization_response(self, request, token_handler): """ The client constructs the request URI by adding the following parameters to the query component of the authorization endpoint URI using the "application/x-www-form-urlencoded" format, per `Appendix B`_: response_type REQUIRED. Value MUST be set to "code". client_id REQUIRED. The client identifier as described in `Section 2.2`_. redirect_uri OPTIONAL. As described in `Section 3.1.2`_. scope OPTIONAL. The scope of the access request as described by `Section 3.3`_. state RECOMMENDED. An opaque value used by the client to maintain state between the request and callback. The authorization server includes this value when redirecting the user-agent back to the client. The parameter SHOULD be used for preventing cross-site request forgery as described in `Section 10.12`_. The client directs the resource owner to the constructed URI using an HTTP redirection response, or by other means available to it via the user-agent. :param request: oauthlib.commong.Request :param token_handler: A token handler instace, for example of type oauthlib.oauth2.BearerToken. :returns: headers, body, status :raises: FatalClientError on invalid redirect URI or client id. ValueError if scopes are not set on the request object. A few examples:: >>> from your_validator import your_validator >>> request = Request('https://example.com/authorize?client_id=valid' ... '&redirect_uri=http%3A%2F%2Fclient.com%2F') >>> from oauthlib.common import Request >>> from oauthlib.oauth2 import AuthorizationCodeGrant, BearerToken >>> token = BearerToken(your_validator) >>> grant = AuthorizationCodeGrant(your_validator) >>> grant.create_authorization_response(request, token) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "oauthlib/oauth2/rfc6749/grant_types.py", line 513, in create_authorization_response raise ValueError('Scopes must be set on post auth.') ValueError: Scopes must be set on post auth. >>> request.scopes = ['authorized', 'in', 'some', 'form'] >>> grant.create_authorization_response(request, token) (u'http://client.com/?error=invalid_request&error_description=Missing+response_type+parameter.', None, None, 400) >>> request = Request('https://example.com/authorize?client_id=valid' ... '&redirect_uri=http%3A%2F%2Fclient.com%2F' ... '&response_type=code') >>> request.scopes = ['authorized', 'in', 'some', 'form'] >>> grant.create_authorization_response(request, token) (u'http://client.com/?code=u3F05aEObJuP2k7DordviIgW5wl52N', None, None, 200) >>> # If the client id or redirect uri fails validation >>> grant.create_authorization_response(request, token) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "oauthlib/oauth2/rfc6749/grant_types.py", line 515, in create_authorization_response >>> grant.create_authorization_response(request, token) File "oauthlib/oauth2/rfc6749/grant_types.py", line 591, in validate_authorization_request oauthlib.oauth2.rfc6749.errors.InvalidClientIdError .. _`Appendix B`: http://tools.ietf.org/html/rfc6749#appendix-B .. _`Section 2.2`: http://tools.ietf.org/html/rfc6749#section-2.2 .. _`Section 3.1.2`: http://tools.ietf.org/html/rfc6749#section-3.1.2 .. _`Section 3.3`: http://tools.ietf.org/html/rfc6749#section-3.3 .. _`Section 10.12`: http://tools.ietf.org/html/rfc6749#section-10.12 """ try: # request.scopes is only mandated in post auth and both pre and # post auth use validate_authorization_request if not request.scopes: raise ValueError('Scopes must be set on post auth.') self.validate_authorization_request(request) log.debug('Pre resource owner authorization validation ok for %r.', request) # If the request fails due to a missing, invalid, or mismatching # redirection URI, or if the client identifier is missing or invalid, # the authorization server SHOULD inform the resource owner of the # error and MUST NOT automatically redirect the user-agent to the # invalid redirection URI. except errors.FatalClientError as e: log.debug('Fatal client error during validation of %r. %r.', request, e) raise # If the resource owner denies the access request or if the request # fails for reasons other than a missing or invalid redirection URI, # the authorization server informs the client by adding the following # parameters to the query component of the redirection URI using the # "application/x-www-form-urlencoded" format, per Appendix B: # http://tools.ietf.org/html/rfc6749#appendix-B except errors.OAuth2Error as e: log.debug('Client error during validation of %r. %r.', request, e) request.redirect_uri = request.redirect_uri or self.error_uri return {'Location': common.add_params_to_uri(request.redirect_uri, e.twotuples)}, None, 302 grant = self.create_authorization_code(request) log.debug('Saving grant %r for %r.', grant, request) self.request_validator.save_authorization_code( request.client_id, grant, request) return {'Location': common.add_params_to_uri(request.redirect_uri, grant.items())}, None, 302