def test_sign_raises_error(self, mock_client_sign): """ Test that the correct Authorization header is returned """ mock_client_sign.side_effect = ValueError with self.assertRaises(LtiError): __ = get_oauth_request_signature('test', 'secret', '', {}, '')
def test_auth_header_returned(self, mock_client_sign): """ Test that the correct Authorization header is returned """ mock_client_sign.return_value = '', {'Authorization': ''}, '' signature = get_oauth_request_signature('test', 'secret', '', {}, '') mock_client_sign.assert_called_with('', http_method=u'POST', body='', headers={}) self.assertEqual(signature, '')
def get_signed_lti_parameters(self): """ Signs LTI launch request and returns signature and OAuth parameters. Arguments: None Returns: dict: LTI launch parameters """ # Must have parameters for correct signing from LTI: lti_parameters = { u'user_id': self.xblock.user_id, u'oauth_callback': u'about:blank', u'launch_presentation_return_url': '', u'lti_message_type': u'basic-lti-launch-request', u'lti_version': 'LTI-1p0', u'roles': self.xblock.role, # Parameters required for grading: u'resource_link_id': self.xblock.resource_link_id, u'lis_result_sourcedid': self.xblock.lis_result_sourcedid, u'context_id': self.xblock.context_id, u'custom_component_display_name': self.xblock.display_name, } if self.xblock.due: lti_parameters[ 'custom_component_due_date'] = self.xblock.due.strftime( '%Y-%m-%d %H:%M:%S') if self.xblock.graceperiod: lti_parameters['custom_component_graceperiod'] = str( self.xblock.graceperiod.total_seconds()) if self.xblock.has_score: lti_parameters.update( {u'lis_outcome_service_url': self.xblock.outcome_service_url}) # Username, email, and language can't be sent in studio mode, because the user object is not defined. # To test functionality test in LMS if callable(self.xblock.runtime.get_real_user): real_user_object = self.xblock.runtime.get_real_user( self.xblock.runtime.anonymous_student_id) lti_parameters[ "lis_person_sourcedid"] = real_user_object.username if self.xblock.send_username else 'private' user_firstname = real_user_object.first_name if self.xblock.send_firstname else 'private' user_lastname = real_user_object.last_name if self.xblock.send_lastname else 'private' lti_parameters[ "lis_person_name_full"] = user_firstname + ' ' + user_lastname lti_parameters[ "lis_person_contact_email_primary"] = real_user_object.email if self.xblock.send_email else 'private' # Appending custom parameter for signing. lti_parameters.update(self.xblock.prefixed_custom_parameters) headers = { # This is needed for body encoding: 'Content-Type': 'application/x-www-form-urlencoded', } key, secret = self.xblock.lti_provider_key_secret oauth_signature = get_oauth_request_signature(key, secret, self.xblock.launch_url, headers, lti_parameters) # Parse headers to pass to template as part of context: oauth_signature = dict([ param.strip().replace('"', '').split('=') for param in oauth_signature.split(',') ]) oauth_signature[u'oauth_nonce'] = oauth_signature.pop( u'OAuth oauth_nonce') # oauthlib encodes signature with # 'Content-Type': 'application/x-www-form-urlencoded' # so '='' becomes '%3D'. # We send form via browser, so browser will encode it again, # So we need to decode signature back: oauth_signature[u'oauth_signature'] = urllib.unquote( oauth_signature[u'oauth_signature']).decode('utf8') # Add LTI parameters to OAuth parameters for sending in form. lti_parameters.update(oauth_signature) return lti_parameters