def test_valid_nonce(self): """ Verify that check_nonce succeeds with a key of maximum length """ nonce = '0123456789012345678901234567890123456789012345678901234567890123' self.assertTrue( SignatureValidator(self.lti_consumer).check_nonce(nonce))
def test_valid_client_key(self): """ Verify that check_client_key succeeds with a valid key """ key = self.lti_consumer.consumer_key self.assertTrue( SignatureValidator(self.lti_consumer).check_client_key(key))
def lti_launch(request, course_id, usage_id): """ Endpoint for all requests to embed edX content via the LTI protocol. This endpoint will be called by a POST message that contains the parameters for an LTI launch (we support version 1.2 of the LTI specification): http://www.imsglobal.org/lti/ltiv1p2/ltiIMGv1p2.html An LTI launch is successful if: - The launch contains all the required parameters - The launch data is correctly signed using a known client key/secret pair """ if not settings.FEATURES['ENABLE_LTI_PROVIDER']: return HttpResponseForbidden() # Check the LTI parameters, and return 400 if any required parameters are # missing params = get_required_parameters(request.POST) if not params: return HttpResponseBadRequest() params.update(get_optional_parameters(request.POST)) # Get the consumer information from either the instance GUID or the consumer # key try: lti_consumer = LtiConsumer.get_or_supplement( params.get('tool_consumer_instance_guid', None), params['oauth_consumer_key'] ) except LtiConsumer.DoesNotExist: return HttpResponseForbidden() # Check the OAuth signature on the message if not SignatureValidator(lti_consumer).verify(request): return HttpResponseForbidden() # Add the course and usage keys to the parameters array try: course_key, usage_key = parse_course_and_usage_keys(course_id, usage_id) except InvalidKeyError: log.error( u'Invalid course key %s or usage key %s from request %s', course_id, usage_id, request ) raise Http404() # lint-amnesty, pylint: disable=raise-missing-from params['course_key'] = course_key params['usage_key'] = usage_key # Create an edX account if the user identifed by the LTI launch doesn't have # one already, and log the edX account into the platform. authenticate_lti_user(request, params['user_id'], lti_consumer) # Store any parameters required by the outcome service in order to report # scores back later. We know that the consumer exists, since the record was # used earlier to verify the oauth signature. store_outcome_parameters(params, request.user, lti_consumer) return render_courseware(request, params['usage_key'])
def test_get_existing_client_secret(self): """ Verify that get_client_secret returns the right value for the correct key """ key = self.lti_consumer.consumer_key secret = SignatureValidator(self.lti_consumer).get_client_secret( key, None) assert secret == self.lti_consumer.consumer_secret
def test_verification_parameters(self, verify_mock): """ Verify that the signature validaton library method is called using the correct parameters derived from the HttpRequest. """ body = 'oauth_signature_method=HMAC-SHA1&oauth_version=1.0' content_type = 'application/x-www-form-urlencoded' request = RequestFactory().post('/url', body, content_type=content_type) headers = {'Content-Type': content_type} SignatureValidator(self.lti_consumer).verify(request) verify_mock.assert_called_once_with(request.build_absolute_uri(), 'POST', body.encode('utf-8'), headers)
def test_invalid_nonce(self, nonce): """ Verify that check_nonce fails with badly formatted nonce """ assert not SignatureValidator(self.lti_consumer).check_nonce(nonce)
def test_invalid_client_key(self, key): """ Verify that check_client_key fails with a disallowed key """ assert not SignatureValidator(self.lti_consumer).check_client_key(key)