def lti_tool(request): key = request.POST['oauth_consumer_key'] if key: secret = oauth_creds[key] if secret: tp = DjangoToolProvider(key, secret, request.POST) else: tp = DjangoToolProvider(None, None, request.POST) tp.lti_msg = "Your consumer didn't used a recognized key" tp.lti_errorlog = "You did it wrong!" error_temp = get_template("error.html") context_data = Context({'message': 'Consumer key not recognized', 'params': request.POST}) error_html = error_temp.render(context_data) return HttpResponse(error_html) else: key_error_temp = get_template("error.html") key_error_html = key_error_temp.render(Context({'message': 'Consumer key not recognized'})) return HttpResponse(key_error_html) if not tp.is_valid_request(request): sigerror_temp = get_template("error.html") context_data = Context({'message': 'The OAuth signature is invalid', 'params': request.POST}) sigerror_html = sigerror_temp.render(context_data) return HttpResponse(sigerror_html) request.session['launch_params'] = tp.to_params() userid = request.POST['user_id'] temp = get_template('assessment.html') html = temp.render(Context({'userid': userid})) return HttpResponse(html)
def lti_init(request, course_id=None, unit_id=None): """LTI init view Analyze LTI POST request to start LTI session. :param course_id: course id from launch url :param unit_id: unit id from lunch url """ if settings.LTI_DEBUG: LOGGER.info(request.META) LOGGER.info(request.POST) session = request.session # Code from ims_lti_py_django example session.clear() try: consumer_key = settings.CONSUMER_KEY secret = settings.LTI_SECRET tool = DjangoToolProvider(consumer_key, secret, request.POST) is_valid = tool.is_valid_request(request) session['target'] = '_blank' except (oauth2.MissingSignature, oauth2.Error, KeyError, AttributeError) as err: is_valid = False session['message'] = "{}".format(err) session['is_valid'] = is_valid session['LTI_POST'] = {k: v for (k, v) in request.POST.iteritems()} if settings.LTI_DEBUG: msg = 'session: is_valid = {}'.format(session.get('is_valid')) LOGGER.info(msg) if session.get('message'): msg = 'session: message = {}'.format(session.get('message')) LOGGER.info(msg) if not is_valid: return render_to_response( 'lti/error.html', {'message': 'LTI request is not valid'}, RequestContext(request) ) return lti_redirect(request, course_id, unit_id)
def index(request): if settings.LTI_DEBUG: print "META" print request.META print "PARAMS" print request.POST session = request.session session.clear() try: consumer_key = settings.CONSUMER_KEY secret = settings.LTI_SECRET tool = DjangoToolProvider(consumer_key, secret, request.POST) is_valid = tool.is_valid_request(request) session['message'] = "We are cool!" except oauth2.MissingSignature, e: is_valid = False session['message'] = "{}".format(e) pass
def index(request): if settings.LTI_DEBUG: print "META" print request.META print "PARAMS" print request.POST session = request.session session.clear() try: consumer_key = settings.CONSUMER_KEY secret = settings.LTI_SECRET tool = DjangoToolProvider(consumer_key, secret, request.POST) is_valid = tool.is_valid_request(request) session['message'] = "We are cool!" except oauth2.MissingSignature,e: is_valid = False session['message'] = "{}".format(e) pass
def lti_init(request, course_id=None, unit_id=None): """LTI init view Analyze LTI POST request to start LTI session. :param course_id: course id from launch url :param unit_id: unit id from lunch url """ if settings.LTI_DEBUG: LOGGER.info(request.META) LOGGER.info(request.POST) session = request.session # Code from ims_lti_py_django example session.clear() try: consumer_key = settings.CONSUMER_KEY secret = settings.LTI_SECRET tool = DjangoToolProvider(consumer_key, secret, request.POST) is_valid = tool.is_valid_request(request) session['target'] = '_blank' except (oauth2.MissingSignature, oauth2.Error, KeyError, AttributeError) as err: is_valid = False session['message'] = "{}".format(err) session['is_valid'] = is_valid session['LTI_POST'] = {k: v for (k, v) in request.POST.iteritems()} if settings.LTI_DEBUG: msg = 'session: is_valid = {}'.format(session.get('is_valid')) LOGGER.info(msg) if session.get('message'): msg = 'session: message = {}'.format(session.get('message')) LOGGER.info(msg) if not is_valid: return render_to_response('lti/error.html', {'message': 'LTI request is not valid'}, RequestContext(request)) return lti_redirect(request, course_id, unit_id)
def authenticate(self, request): logger.info("about to begin authentication process") request_key = request.POST.get('oauth_consumer_key', None) if request_key is None: logger.error("Request doesn't contain an oauth_consumer_key; can't continue.") return None secret = oauth_creds.get(request_key, None) if secret is None: logger.error("Could not get a secret for key %s" % request_key) raise PermissionDenied logger.debug('using key/secret %s/%s' % (request_key, secret)) tool_provider = DjangoToolProvider(request_key, secret, request.POST.dict()) postparams = request.POST.dict() logger.debug('request is secure: %s' % request.is_secure()) for key in postparams: logger.debug('POST %s: %s' % (key, postparams.get(key))) logger.debug('request abs url is %s' % request.build_absolute_uri()) for key in request.META: logger.debug('META %s: %s' % (key, request.META.get(key))) logger.info("about to check the signature") if not tool_provider.is_valid_request(request): logger.error("Invalid request: signature check failed.") raise PermissionDenied logger.info("done checking the signature") print tool_provider.oauth_timestamp logger.info("about to check the timestamp: %d" % int(tool_provider.oauth_timestamp)) if time() - int(tool_provider.oauth_timestamp) > 60 * 60: logger.error("OAuth timestamp is too old.") #raise PermissionDenied else: logger.info("timestamp looks good") logger.info("done checking the timestamp") # (this is where we should check the nonce) # if we got this far, the user is good user = None if request.POST.get('lis_person_sourcedid'): username = self.clean_username(request.POST.get('lis_person_sourcedid')) elif request.POST.get('custom_canvas_user_login_id'): username = self.clean_username(request.POST.get('custom_canvas_user_login_id')) else: username = self.clean_username(request.POST.get('user_id')) email = request.POST.get('lis_person_contact_email_primary') first_name = request.POST.get('lis_person_name_given') last_name = request.POST.get('lis_person_name_family') logger.info("We have a valid username: %s" % username) UserModel = get_user_model() # Note that this could be accomplished in one try-except clause, but # instead we use get_or_create when creating unknown users since it has # built-in safeguards for multiple threads. if self.create_unknown_user: user, created = UserModel.objects.get_or_create(**{ UserModel.USERNAME_FIELD: username, }) if created: logger.debug('authenticate created a new user for %s' % username) else: logger.debug('authenticate found an existing user for %s' % username) else: logger.debug('automatic new user creation is turned OFF! just try to find and existing record') try: user = UserModel.objects.get_by_natural_key(username) except UserModel.DoesNotExist: logger.debug('authenticate could not find user %s' % username) # should return some kind of error here? pass # update the user if email: user.email = email if first_name: user.first_name = first_name if last_name: user.last_name = last_name user.save() logger.debug("updated the user record in the database") return user
def _validate_request(self, request): ''' Validates an LTI launch request. ''' consumer_key = getattr(settings, 'CONSUMER_KEY', None) try: secret = settings.LTI_SECRET_DICT[request.POST.get('context_id')] except: secret = settings.LTI_SECRET if consumer_key is None or secret is None: self.logger.error("missing consumer key/secret: %s/%s" % (consumer_key, secret)) raise ImproperlyConfigured("Unable to validate LTI launch. Missing setting: CONSUMER_KEY or LTI_SECRET") request_key = request.POST.get('oauth_consumer_key', None) if request_key is None: self.logger.error("request doesn't contain an oauth_consumer_key; can't continue.") raise LTILaunchError if request_key != consumer_key: self.logger.error("could not get a secret for requested key: %s" % request_key) raise LTILaunchError self.logger.debug('using key/secret %s/%s' % (request_key, secret)) tool_provider = DjangoToolProvider(request_key, secret, request.POST) postparams = request.POST.dict() self.logger.debug('request is secure: %s' % request.is_secure()) for key in postparams: self.logger.debug('POST %s: %s' % (key, postparams.get(key))) self.logger.debug('request abs url is %s' % request.build_absolute_uri()) for key in request.META: self.logger.debug('META %s: %s' % (key, request.META.get(key))) self.logger.debug("about to check the signature") try: # NOTE: before validating the request, temporarily remove the # QUERY_STRING to work around an issue with how Canvas signs requests # that contain GET parameters. Before Canvas launches the tool, it duplicates the GET # parameters as POST parameters, and signs the POST parameters (*not* the GET parameters). # However, the oauth2 library that validates the request generates # the oauth signature based on the combination of POST+GET parameters together, # resulting in a signature mismatch. By removing the QUERY_STRING before # validating the request, the library will generate the signature based only on # the POST parameters like Canvas. qs = request.META.pop('QUERY_STRING', '') self.logger.debug('removed query string temporarily: %s' % qs) request_is_valid = tool_provider.is_valid_request(request, parameters={}, handle_error=False) request.META['QUERY_STRING'] = qs # restore the query string self.logger.debug('restored query string: %s' % request.META['QUERY_STRING']) except oauth2.Error as e: self.logger.error("signature check failed") self.logger.exception(e) raise LTILaunchError self.logger.info("signature verified") self.logger.debug("about to check the timestamp: %d" % int(tool_provider.oauth_timestamp)) if time.time() - int(tool_provider.oauth_timestamp) > 60 * 60: self.logger.warning("OAuth timestamp is too old.") # raise PermissionDenied else: self.logger.info("OAuth timestamp looks good") for required_param in ('resource_link_id', 'context_id', 'user_id'): if required_param not in request.POST: self.logger.error("Required LTI param '%s' was not present in request" % required_param) raise LTILaunchError if ('lis_person_sourcedid' not in request.POST and 'lis_person_name_full' not in request.POST and request.POST['user_id'] != "student"): self.logger.error('person identifier (i.e. username) or full name was not present in request') raise LTILaunchError
def authenticate(self, request): logger.info("about to begin authentication process") request_key = request.POST.get('oauth_consumer_key', None) if request_key is None: logger.error( "Request doesn't contain an oauth_consumer_key; can't continue." ) return None if not settings.LTI_OAUTH_CREDENTIALS: logger.error("Missing LTI_OAUTH_CREDENTIALS in settings") raise PermissionDenied secret = settings.LTI_OAUTH_CREDENTIALS.get(request_key) if secret is None: logger.error("Could not get a secret for key %s" % request_key) raise PermissionDenied logger.debug('using key/secret %s/%s' % (request_key, secret)) tool_provider = DjangoToolProvider(request_key, secret, request.POST.dict()) postparams = request.POST.dict() logger.debug('request is secure: %s' % request.is_secure()) for key in postparams: logger.debug('POST %s: %s' % (key, postparams.get(key))) logger.debug('request abs url is %s' % request.build_absolute_uri()) for key in request.META: logger.debug('META %s: %s' % (key, request.META.get(key))) logger.info("about to check the signature") try: request_is_valid = tool_provider.is_valid_request(request) except oauth2.Error: logger.exception(u'error attempting to validate LTI launch %s', postparams) request_is_valid = False if not request_is_valid: logger.error("Invalid request: signature check failed.") raise PermissionDenied logger.info("done checking the signature") logger.info("about to check the timestamp: %d" % int(tool_provider.oauth_timestamp)) if time() - int(tool_provider.oauth_timestamp) > 60 * 60: logger.error("OAuth timestamp is too old.") #raise PermissionDenied else: logger.info("timestamp looks good") logger.info("done checking the timestamp") # (this is where we should check the nonce) # if we got this far, the user is good user = None # Retrieve username from LTI parameter or default to an overridable function return value username = tool_provider.lis_person_sourcedid or self.get_default_username( tool_provider, prefix=self.unknown_user_prefix) username = self.clean_username(username) # Clean it email = tool_provider.lis_person_contact_email_primary first_name = tool_provider.lis_person_name_given last_name = tool_provider.lis_person_name_family # Check that we have an email field at least if not email: logger.error("Invalid request: Invalid email.") raise PermissionDenied logger.info("We have a valid username: %s" % username) UserModel = get_user_model() # Note that this could be accomplished in one try-except clause, but # instead we use get_or_create when creating unknown users since it has # built-in safeguards for multiple threads. if self.create_unknown_user: user, created = UserModel.objects.get_or_create(**{ # UserModel.USERNAME_FIELD: username, 'email': email, }) if created: logger.debug('authenticate created a new user for %s' % username) else: logger.debug('authenticate found an existing user for %s' % username) else: logger.debug( 'automatic new user creation is turned OFF! just try to find and existing record' ) try: user = UserModel.objects.get_by_natural_key(username) except UserModel.DoesNotExist: logger.debug('authenticate could not find user %s' % username) # should return some kind of error here? pass # update the user if email: user.email = email if username: user.name = username if first_name: user.first_name = first_name if last_name: user.last_name = last_name user.save() logger.debug("updated the user record in the database") return user
def _validate_request(self, request): ''' Validates an LTI launch request. ''' consumer_key = getattr(settings, 'CONSUMER_KEY', None) try: secret = settings.LTI_SECRET_DICT[request.POST.get('context_id')] except: secret = settings.LTI_SECRET if consumer_key is None or secret is None: self.logger.error("missing consumer key/secret: %s/%s" % (consumer_key, secret)) raise ImproperlyConfigured( "Unable to validate LTI launch. Missing setting: CONSUMER_KEY or LTI_SECRET" ) request_key = request.POST.get('oauth_consumer_key', None) if request_key is None: self.logger.error( "request doesn't contain an oauth_consumer_key; can't continue." ) raise LTILaunchError if request_key != consumer_key: self.logger.error("could not get a secret for requested key: %s" % request_key) raise LTILaunchError self.logger.debug('using key/secret %s/%s' % (request_key, secret)) tool_provider = DjangoToolProvider(request_key, secret, request.POST) postparams = request.POST.dict() self.logger.debug('request is secure: %s' % request.is_secure()) for key in postparams: self.logger.debug('POST %s: %s' % (key, postparams.get(key))) self.logger.debug('request abs url is %s' % request.build_absolute_uri()) for key in request.META: self.logger.debug('META %s: %s' % (key, request.META.get(key))) self.logger.debug("about to check the signature") try: # NOTE: before validating the request, temporarily remove the # QUERY_STRING to work around an issue with how Canvas signs requests # that contain GET parameters. Before Canvas launches the tool, it duplicates the GET # parameters as POST parameters, and signs the POST parameters (*not* the GET parameters). # However, the oauth2 library that validates the request generates # the oauth signature based on the combination of POST+GET parameters together, # resulting in a signature mismatch. By removing the QUERY_STRING before # validating the request, the library will generate the signature based only on # the POST parameters like Canvas. qs = request.META.pop('QUERY_STRING', '') self.logger.debug('removed query string temporarily: %s' % qs) request_is_valid = tool_provider.is_valid_request( request, parameters={}, handle_error=False) request.META['QUERY_STRING'] = qs # restore the query string self.logger.debug('restored query string: %s' % request.META['QUERY_STRING']) except oauth2.Error as e: self.logger.error("signature check failed") self.logger.exception(e) raise LTILaunchError self.logger.info("signature verified") self.logger.debug("about to check the timestamp: %d" % int(tool_provider.oauth_timestamp)) if time.time() - int(tool_provider.oauth_timestamp) > 60 * 60: self.logger.warning("OAuth timestamp is too old.") # raise PermissionDenied else: self.logger.info("OAuth timestamp looks good") for required_param in ('resource_link_id', 'context_id', 'user_id'): if required_param not in request.POST: self.logger.error( "Required LTI param '%s' was not present in request" % required_param) raise LTILaunchError if ('lis_person_sourcedid' not in request.POST and 'lis_person_name_full' not in request.POST and request.POST['user_id'] != "student"): self.logger.error( 'person identifier (i.e. username) or full name was not present in request' ) raise LTILaunchError
def authenticate(self, request): logger.info("about to begin authentication process") request_key = request.POST.get('oauth_consumer_key', None) if request_key is None: logger.error("Request doesn't contain an oauth_consumer_key; can't continue.") return None oauth_credentials = getattr(settings, 'LTI_OAUTH_CREDENTIALS', {}) cohorts = Cohort.objects.filter(oauth_key=request_key).all() cohort = None if cohorts: cohort = cohorts[0] # Let settings.LTI_OAUTH_CREDENTIALS secret override the database cohort secret secret = oauth_credentials.get(request_key) if secret is None and cohort: secret = cohort.oauth_secret if secret is None: logger.error("Could not get a secret for key %s" % request_key) raise PermissionDenied logger.debug('using key/secret %s/%s' % (request_key, secret)) tool_provider = DjangoToolProvider(request_key, secret, request.POST.dict()) postparams = request.POST.dict() logger.debug('request is secure: %s' % request.is_secure()) for key in postparams: logger.debug('POST %s: %s' % (key, postparams.get(key))) logger.debug('request abs url is %s' % request.build_absolute_uri()) for key in request.META: logger.debug('META %s: %s' % (key, request.META.get(key))) logger.info("about to check the signature") valid = False try: valid = tool_provider.is_valid_request(request) except: logger.error(str(sys.exc_info()[0])) valid = False finally: if not valid: logger.error("Invalid request: signature check failed.") raise PermissionDenied logger.info("done checking the signature") logger.info("about to check the timestamp: %d" % int(tool_provider.oauth_timestamp)) if time() - int(tool_provider.oauth_timestamp) > 60 * 60: logger.error("OAuth timestamp is too old.") #raise PermissionDenied else: logger.info("timestamp looks good") logger.info("done checking the timestamp") # (this is where we should check the nonce) # if we got this far, the user is good user = None # Retrieve username from LTI parameter or default to an overridable function return value username = tool_provider.lis_person_sourcedid or self.get_default_username( tool_provider, prefix=self.unknown_user_prefix) username = self.clean_username(username) # Clean it email = tool_provider.lis_person_contact_email_primary first_name = tool_provider.lis_person_name_given last_name = tool_provider.lis_person_name_family logger.info("We have a valid username: %s" % username) UserModel = get_user_model() # Note that this could be accomplished in one try-except clause, but # instead we use get_or_create when creating unknown users since it has # built-in safeguards for multiple threads. if self.create_unknown_user: user, created = UserModel.objects.get_or_create(**{ UserModel.USERNAME_FIELD: username, }) if created: logger.debug('authenticate created a new user for %s' % username) else: logger.debug('authenticate found an existing user for %s' % username) else: logger.debug( 'automatic new user creation is turned OFF! just try to find and existing record') try: user = UserModel.objects.get_by_natural_key(username) except UserModel.DoesNotExist: logger.debug('authenticate could not find user %s' % username) # should return some kind of error here? pass # update the user if cohort: user.cohort = cohort if email: user.email = email # FIXME ADX-192: should really be using our own nickname field, instead # of requiring first_name to be unique. #if first_name: # user.first_name = first_name if last_name: user.last_name = last_name user.save() logger.debug("updated the user record in the database") return user
def lti_init(request, course_id=None, unit_id=None): """LTI init view Analyze LTI POST request to start LTI session. :param course_id: course id from launch url :param unit_id: unit id from lunch url """ if settings.LTI_DEBUG: LOGGER.debug(request.META) LOGGER.debug(request.POST) session = request.session # Code from ims_lti_py_django example session.clear() short_term_lti = request.POST.get('custom_short_term') instance_guid = request.POST.get('tool_consumer_instance_guid') consumer_key = request.POST.get('oauth_consumer_key') if short_term_lti: lti_consumer = LtiConsumer.objects.filter( consumer_key=consumer_key).first() else: lti_consumer = LtiConsumer.get_or_combine(instance_guid, consumer_key) if not lti_consumer: LOGGER.error( 'Consumer with key {} was not found.'.format(consumer_key)) return render(request, 'lti/error.html', {'message': 'LTI request is not valid'}) try: if lti_consumer.expiration_date and lti_consumer.expiration_date < date.today( ): raise oauth2.Error('Consumer Key has expired.') if lti_consumer.consumer_key != consumer_key: raise oauth2.Error('Wrong Consumer Key: {}'.format(consumer_key)) consumer_key = lti_consumer.consumer_key secret = lti_consumer.consumer_secret tool = DjangoToolProvider(consumer_key, secret, request.POST) is_valid = tool.is_valid_request(request) session['target'] = '_blank' except (oauth2.MissingSignature, oauth2.Error, KeyError, AttributeError) as err: is_valid = False session['message'] = "{}".format(err) LOGGER.error("Error during processing LTI request: {}".format( err.__str__())) session['is_valid'] = is_valid session['LTI_POST'] = {k: v for (k, v) in list(request.POST.items())} if settings.LTI_DEBUG: msg = 'session: is_valid = {}'.format(session.get('is_valid')) LOGGER.debug(msg) if session.get('message'): msg = 'session: message = {}'.format(session.get('message')) LOGGER.debug(msg) if not is_valid: return render(request, 'lti/error.html', {'message': 'LTI request is not valid'}) return lti_redirect(request, lti_consumer, course_id, unit_id)