def verify_request_common(consumers, url, method, headers, params): """ Verifies that request is valid :param consumers: consumers from config file :param url: request url :param method: request method :param headers: request headers :param params: request params :return: is request valid """ log.debug("consumers {}".format(consumers)) log.debug("url {}".format(url)) log.debug("method {}".format(method)) log.debug("headers {}".format(headers)) log.debug("params {}".format(params)) oauth_store = LTIOAuthDataStore(consumers) oauth_server = oauth.OAuthServer(oauth_store) oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT()) oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1()) # Check header for SSL before selecting the url if headers.get('X-Forwarded-Proto', 'http') == 'https': url = url.replace('http', 'https', 1) oauth_request = oauth.OAuthRequest.from_request(method, url, headers=dict(headers), parameters=params) if not oauth_request: log.info('Received non oauth request on oauth protected page') raise LTIException('This page requires a valid oauth session ' 'or request') try: # pylint: disable=protected-access consumer = oauth_server._get_consumer(oauth_request) oauth_server._check_signature(oauth_request, consumer, None) except oauth.OAuthError: # Rethrow our own for nice error handling (don't print # error message as it will contain the key raise LTIException("OAuth error: Please check your key and secret") return True
def app(self, environ, start_response): if environ['PATH_INFO'].endswith('echo'): start_response("200 OK", [('Content-Type', 'application/json')]) ret = {} for name in ('REQUEST_METHOD', 'PATH_INFO', 'QUERY_STRING'): ret[name] = environ[name] if environ['REQUEST_METHOD'] in ('PUT', 'POST'): ret['CONTENT_TYPE'] = environ['CONTENT_TYPE'] content_length = int(environ['CONTENT_LENGTH']) ret['body'] = environ['wsgi.input'].read(content_length) return [json.dumps(ret)] elif environ['PATH_INFO'].endswith('error_then_accept'): if self.errors >= 3: start_response("200 OK", [('Content-Type', 'application/json')]) ret = {} for name in ('REQUEST_METHOD', 'PATH_INFO', 'QUERY_STRING'): ret[name] = environ[name] if environ['REQUEST_METHOD'] in ('PUT', 'POST'): ret['CONTENT_TYPE'] = environ['CONTENT_TYPE'] content_length = int(environ['CONTENT_LENGTH']) ret['body'] = '{"oki": "doki"}' return [json.dumps(ret)] self.errors += 1 content_length = int(environ['CONTENT_LENGTH']) error = json.loads(environ['wsgi.input'].read(content_length)) response = error['response'] # In debug mode, wsgiref has an assertion that the status parameter # is a 'str' object. However error['status'] returns a unicode # object. status = str(error['status']) if isinstance(response, unicode): response = str(response) if isinstance(response, str): start_response(status, [('Content-Type', 'text/plain')]) return [str(response)] else: start_response(status, [('Content-Type', 'application/json')]) return [json.dumps(response)] elif environ['PATH_INFO'].endswith('error'): self.errors += 1 content_length = int(environ['CONTENT_LENGTH']) error = json.loads(environ['wsgi.input'].read(content_length)) response = error['response'] # In debug mode, wsgiref has an assertion that the status parameter # is a 'str' object. However error['status'] returns a unicode # object. status = str(error['status']) if isinstance(response, unicode): response = str(response) if isinstance(response, str): start_response(status, [('Content-Type', 'text/plain')]) return [str(response)] else: start_response(status, [('Content-Type', 'application/json')]) return [json.dumps(response)] elif '/oauth' in environ['PATH_INFO']: base_url = self.getURL('').rstrip('/') oauth_req = oauth.OAuthRequest.from_request( http_method=environ['REQUEST_METHOD'], http_url=base_url + environ['PATH_INFO'], headers={'Authorization': environ['HTTP_AUTHORIZATION']}, query_string=environ['QUERY_STRING']) oauth_server = oauth.OAuthServer(tests.testingOAuthStore) oauth_server.add_signature_method(tests.sign_meth_HMAC_SHA1) try: consumer, token, params = oauth_server.verify_request( oauth_req) except oauth.OAuthError, e: start_response("401 Unauthorized", [('Content-Type', 'application/json')]) return [ json.dumps({ "error": "unauthorized", "message": e.message }) ] start_response("200 OK", [('Content-Type', 'application/json')]) return [json.dumps([environ['PATH_INFO'], token.key, params])]
def decorator(*args, **kwargs): """ Actual wrapper to handle LTI/OAuth """ # pylint: disable=W0212 # Get lti GET or POST params as dict if request.method == 'POST': params = request.form.to_dict() else: params = request.args.to_dict() log.debug(params) # If we are already authenticated and not requesting oauth, return if (session.get(LTI_SESSION_KEY, False) and not params.get('oauth_consumer_key', None)): return func(*args, **kwargs) # Clear session to ensure authorization is happening fresh for # each lti instance. for prop in LTI_PROPERTY_LIST: if session.get(prop, None): del session[prop] # Try and authentication if session is being initiated oauth_server = oauth.OAuthServer(LTIOAuthDataStore()) oauth_server.add_signature_method( oauth.OAuthSignatureMethod_PLAINTEXT()) oauth_server.add_signature_method( oauth.OAuthSignatureMethod_HMAC_SHA1()) # Check header for SSL before selecting the url url = request.url if request.headers.get('X-Forwarded-Proto', 'http') == 'https': url = request.url.replace('http', 'https', 1) oauth_request = oauth.OAuthRequest.from_request( request.method, url, headers=dict(request.headers), parameters=params ) if not oauth_request: log.info('Received non oauth request on oauth protected page') raise LTIException('This page requires a valid oauth session ' 'or request') try: consumer = oauth_server._get_consumer(oauth_request) oauth_server._check_signature(oauth_request, consumer, None) except oauth.OAuthError as err: # Rethrow our own for nice error handling (don't print # error message as it will contain the key log.info(err.message) raise LTIException("OAuth error: Please check your key and secret") # All good to go, store all of the LTI params into a # session dict for use in views for prop in LTI_PROPERTY_LIST: if params.get(prop, None): session[prop] = params[prop] # Set logged in session key session[LTI_SESSION_KEY] = True return func(*args, **kwargs)
def _post_patched_request(consumers, lti_key, body, url, method, content_type): """ Authorization header needs to be capitalized for some LTI clients this function ensures that header is capitalized :param body: body of the call :param client: OAuth Client :param url: outcome url :return: response """ oauth_store = LTIOAuthDataStore(consumers) oauth_server = oauth.OAuthServer(oauth_store) oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1()) lti_consumer = oauth_store.lookup_consumer(lti_key) lti_cert = oauth_store.lookup_cert(lti_key) secret = lti_consumer.secret consumer = oauth2.Consumer(key=lti_key, secret=secret) client = oauth2.Client(consumer) if lti_cert: client.add_certificate(key=lti_cert, cert=lti_cert, domain='') log.debug("cert {}".format(lti_cert)) import httplib2 http = httplib2.Http # pylint: disable=protected-access normalize = http._normalize_headers def my_normalize(self, headers): """ This function patches Authorization header """ ret = normalize(self, headers) if 'authorization' in ret: ret['Authorization'] = ret.pop('authorization') log.debug("headers") log.debug(headers) return ret http._normalize_headers = my_normalize monkey_patch_function = normalize # pylint: disable=unused-variable response, content = client.request(url, method, body=body, headers={'Content-Type': content_type}) http = httplib2.Http # pylint: disable=protected-access http._normalize_headers = monkey_patch_function log.debug("key {}".format(lti_key)) log.debug("secret {}".format(secret)) log.debug("url {}".format(url)) log.debug("response {}".format(response)) log.debug("content {}".format(content)) return response, content
""" token = models.SessionToken.objects.create(token=access_token_str, secret=access_token_secret, user=request_token.user) return token def lookup_access_token(self, consumer, access_token_str): """ token is the token string returns a OAuthAccessToken """ return self.__get_token(access_token_str) def check_and_store_nonce(self, nonce_str): """ store the given nonce in some form to check for later duplicates IMPORTANT: raises an exception if the nonce has already been stored """ nonce, created = models.Nonce.objects.get_or_create( nonce=nonce_str, oauth_type=self.__class__.__name__) if not created: raise oauth.OAuthError("Nonce already exists") ADMIN_OAUTH_SERVER = oauth.OAuthServer(store=MachineDataStore()) SESSION_OAUTH_SERVER = oauth.OAuthServer(store=SessionDataStore()) OAUTH_SERVER = oauth.OAuthServer(store=UserDataStore())
def oauth_server(self): if not hasattr(self, '_oauth_server'): self._oauth_server = oauth.OAuthServer(OAuthDataStore()) self._oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT()) self._oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1()) return self._oauth_server
* a chrome app consumer * a smart connect access token. """ def _get_chrome_app(self, consumer_key): try: return models.MachineApp.objects.get(consumer_key=consumer_key, app_type='chrome') except models.MachineApp.DoesNotExist: return None def _get_token(self, token_str, app=None): kwargs = {'token': token_str} print "evaluating as SC, lookin gor", token_str try: ret = models.AccessToken.objects.get(**kwargs) if ret.smart_connect_p == False: oauth.report_error( "Not a SMArt Connect Request -- don't treat as one!") return ret except models.AccessToken.DoesNotExist: oauth.report_error( "No token means this isn't a SMArt Connect Request!") ADMIN_OAUTH_SERVER = oauth.OAuthServer(store=MachineDataStore()) SESSION_OAUTH_SERVER = oauth.OAuthServer(store=SessionDataStore()) OAUTH_SERVER = oauth.OAuthServer(store=UserDataStore()) SMART_CONNECT_OAUTH_SERVER = oauth.OAuthServer(store=SMArtConnectDataStore()) HELPER_APP_SERVER = oauth.OAuthServer(store=HelperAppDataStore())
def __init__(self, *args, **kwargs): self.oauth_server = oauth.OAuthServer(MockOAuthDataStore()) self.oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT()) self.oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1()) BaseHTTPRequestHandler.__init__(self, *args, **kwargs)