Commit a1d3899a by David Baumgold

Use oauthlib directly for LTI module

parent 45f38ddf
""" """
Module that allows to insert LTI tools to page. Module that allows to insert LTI tools to page.
Module uses current edx-platform 0.14.2 version of requests (oauth part).
Please update code when upgrading requests.
Protocol is oauth1, LTI version is 1.1.1: Protocol is oauth1, LTI version is 1.1.1:
http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html http://www.imsglobal.org/LTI/v1p1p1/ltiIMGv1p1p1.html
""" """
import logging import logging
import requests import oauthlib
import urllib import urllib
from xmodule.editing_module import MetadataOnlyEditingDescriptor from xmodule.editing_module import MetadataOnlyEditingDescriptor
...@@ -192,7 +189,7 @@ class LTIModule(LTIFields, XModule): ...@@ -192,7 +189,7 @@ class LTIModule(LTIFields, XModule):
Also *anonymous student id* is passed to template and therefore to LTI provider. Also *anonymous student id* is passed to template and therefore to LTI provider.
""" """
client = requests.auth.Client( client = oauthlib.oauth1.Client(
client_key=unicode(client_key), client_key=unicode(client_key),
client_secret=unicode(client_secret) client_secret=unicode(client_secret)
) )
...@@ -230,8 +227,8 @@ class LTIModule(LTIFields, XModule): ...@@ -230,8 +227,8 @@ class LTIModule(LTIFields, XModule):
params[u'oauth_nonce'] = params[u'OAuth oauth_nonce'] params[u'oauth_nonce'] = params[u'OAuth oauth_nonce']
del params[u'OAuth oauth_nonce'] del params[u'OAuth oauth_nonce']
# 0.14.2 (current) version of requests oauth library encodes signature, # oauthlib encodes signature with
# with 'Content-Type': 'application/x-www-form-urlencoded' # 'Content-Type': 'application/x-www-form-urlencoded'
# so '='' becomes '%3D'. # so '='' becomes '%3D'.
# We send form via browser, so browser will encode it again, # We send form via browser, so browser will encode it again,
# So we need to decode signature back: # So we need to decode signature back:
......
...@@ -36,6 +36,7 @@ mako==0.7.3 ...@@ -36,6 +36,7 @@ mako==0.7.3
Markdown==2.2.1 Markdown==2.2.1
networkx==1.7 networkx==1.7
nltk==2.0.4 nltk==2.0.4
oauthlib==0.5.1
paramiko==1.9.0 paramiko==1.9.0
path.py==3.0.1 path.py==3.0.1
Pillow==1.7.8 Pillow==1.7.8
......
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
import urlparse import urlparse
from requests.packages.oauthlib.oauth1.rfc5849 import signature from oauthlib.oauth1.rfc5849 import signature
import mock import mock
from logging import getLogger from logging import getLogger
logger = getLogger(__name__) logger = getLogger(__name__)
......
"""LTI integration tests""" """LTI integration tests"""
import requests import oauthlib
from . import BaseTestXmodule from . import BaseTestXmodule
from collections import OrderedDict from collections import OrderedDict
import mock import mock
...@@ -11,7 +11,8 @@ class TestLTI(BaseTestXmodule): ...@@ -11,7 +11,8 @@ class TestLTI(BaseTestXmodule):
Integration test for lti xmodule. Integration test for lti xmodule.
It checks overall code, by assuring that context that goes to template is correct. It checks overall code, by assuring that context that goes to template is correct.
As part of that, checks oauth signature generation by mocking signing function of `requests` library. As part of that, checks oauth signature generation by mocking signing function
of `oauthlib` library.
""" """
CATEGORY = "lti" CATEGORY = "lti"
...@@ -43,7 +44,7 @@ class TestLTI(BaseTestXmodule): ...@@ -43,7 +44,7 @@ class TestLTI(BaseTestXmodule):
u'oauth_signature': mocked_decoded_signature u'oauth_signature': mocked_decoded_signature
} }
saved_sign = requests.auth.Client.sign saved_sign = oauthlib.oauth1.Client.sign
def mocked_sign(self, *args, **kwargs): def mocked_sign(self, *args, **kwargs):
""" """
...@@ -60,7 +61,7 @@ class TestLTI(BaseTestXmodule): ...@@ -60,7 +61,7 @@ class TestLTI(BaseTestXmodule):
headers[u'Authorization'] = ', '.join([k+'="'+v+'"' for k, v in old_parsed.items()]) headers[u'Authorization'] = ', '.join([k+'="'+v+'"' for k, v in old_parsed.items()])
return None, headers, None return None, headers, None
patcher = mock.patch.object(requests.auth.Client, "sign", mocked_sign) patcher = mock.patch.object(oauthlib.oauth1.Client, "sign", mocked_sign)
patcher.start() patcher.start()
self.addCleanup(patcher.stop) self.addCleanup(patcher.stop)
......
...@@ -39,6 +39,7 @@ mako==0.7.3 ...@@ -39,6 +39,7 @@ mako==0.7.3
Markdown==2.2.1 Markdown==2.2.1
networkx==1.7 networkx==1.7
nltk==2.0.4 nltk==2.0.4
oauthlib==0.5.1
paramiko==1.9.0 paramiko==1.9.0
path.py==3.0.1 path.py==3.0.1
Pillow==1.7.8 Pillow==1.7.8
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment