示例#1
0
文件: common.py 项目: IMidULti/pylti
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
示例#2
0
 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])]
示例#3
0
    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)
示例#4
0
文件: common.py 项目: IMidULti/pylti
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
示例#5
0
    """

        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())
示例#6
0
 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
示例#7
0
    * 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())
示例#8
0
 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)