Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using Assignment and Grades throws an error on Dark language middleware #218

Open
Alain1405 opened this issue Jan 12, 2022 · 14 comments
Open

Comments

@Alain1405
Copy link

Alain1405 commented Jan 12, 2022

Release: Maple
Relevant settings: ENABLE_COMPREHENSIVE_THEMING=True
LTI consumer settings:

  • LTI version: 1.3
  • Enable LTI NRPS: True
  • Deep linking: True
  • LTI Assignment and Grades Service: Programmatic
  • Everything else: True

We have configured an LTI 1.3 producer using PyLTI1p3 library (using the Django example).

The connection works fine, however when the tool uses the Assignment and Grades service or Names and Roles service, every time it sends a requests to our Maple instance, it triggers a 500 due to missing user at https://github.com/edx/edx-platform/blob/4f49475b94a61c3290c1813f5272277b7986b06c/openedx/core/djangoapps/dark_lang/middleware.py#L159

The error is:

AttributeError
'NoneType' object has no attribute 'is_authenticated'
openedx/core/djangoapps/dark_lang/middleware.py in _activate_preview_language at line 165
openedx/core/djangoapps/dark_lang/middleware.py in process_response at line 102
django/utils/deprecation.py in __call__ at line 119
django/core/handlers/exception.py in inner at line 47
@Alain1405
Copy link
Author

Alain1405 commented Jan 12, 2022

@giovannicimolin we are also facing this issue #217

@Alain1405
Copy link
Author

Alain1405 commented Jan 12, 2022

I have done more investigation.

  • The LTI tool is sending a POST to submit a grade to edxplatform.com/api/lti_consumer/v1/lti/4/lti-ags
  • The ViewSet LtiAgsLineItemViewset processes the request
    class LtiAgsLineItemViewset(viewsets.ModelViewSet):
  • As part of the authentication process, Lti1p3ApiAuthentication is called. In there, I found the note This doesn't return a user, but let's the external access and commit changes. TODO: Consider creating an user for LTI operations, both to keep track of changes and to use Django's authorization flow.
    TODO: Consider creating an user for LTI operations, both to keep track
  • Somewhere before a response is returned or even before the score is stored, edx tries to render a template but given that no Django user is in the request the rendering fail
Full error log below:

Jan 12 09:35:50 ip-10-121-9-198 [service_variant=lms][root][env:sandbox] ERROR [ip-10-121-9-198  19004] [user None] [ip 35.76.151.108] [signals.py:22] - Uncaught exception from None
Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 102, in process_response
    self._activate_preview_language(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 165, in _activate_preview_language
    auth_user = request.user.is_authenticated
AttributeError: 'NoneType' object has no attribute 'is_authenticated'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 244, in bind_template
    updates.update(processor(self.request))
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/courseware/context_processor.py", line 40, in user_timezone_locale_prefs
    if hasattr(request, 'user') and request.user.is_authenticated:
AttributeError: 'NoneType' object has no attribute 'is_authenticated'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 114, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 153, in handle_uncaught_exception
    return callback(request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/util/views.py", line 95, in wrapper
    return func(request, *args, **kwargs)
  File "/edx/app/edxapp/edx-platform/lms/djangoapps/static_template_view/views.py", line 125, in render_500
    return HttpResponseServerError(render_to_string('static_templates/server-error.html', {}, request=request))
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string
    return template.render(dictionary, request)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 66, in render
    context_dictionary = self._get_context_processors_output_dict(context_object)
  File "/edx/app/edxapp/edx-platform/common/djangoapps/edxmako/template.py", line 100, in _get_context_processors_output_dict
    with context_object.bind_template(self):
  File "/usr/lib/python3.8/contextlib.py", line 113, in __enter__
    return next(self.gen)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/template/context.py", line 236, in bind_template
    raise RuntimeError("Context is already bound to a template")
RuntimeError: Context is already bound to a template

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/sentry_sdk/integrations/django/middleware.py", line 175, in __call__
    return f(*args, **kwargs)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 117, in __call__
    response = response or self.get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 49, in inner
    response = response_for_exception(request, exc)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/co

@Alain1405
Copy link
Author

Alain1405 commented Jan 12, 2022

Additionally, maybe related, DeepLinking seems to work until after changing the configurations on the tool we return to edx, where we get the following message with a 403:

You don't have access to save LTI Content Items.

Please check that you have course staff permissions and double check this block's LTI settings.

Request URL: POST platform.url/api/lti_consumer/v1/lti/4/lti-dl/response

The response is triggered at

except (Lti1p3Exception, PermissionDenied) as exc:
potentially because the request doesn't have the right user data for user_has_staff_access to succeed
if not user_has_staff_access(request.user, course_key):

The weird part is that when we get redirect back to edx the user (superuser) gets logged out.

@giovannicimolin
Copy link
Contributor

giovannicimolin commented Jan 14, 2022

@Alain1405 I'm pretty sure I've bumped into this problem before.
Can you check if the cookies from you Open edX instance have SameSite=None?
If not, the cookies won't be sent when the page is redirected and the LMS will think it's an Unauthenticated request.

Let me do some testing on my end.


Edit:
Can you try setting DCS_SESSION_COOKIE_SAMESITE = 'None' and trying to run the launches again?
LTI launches, LTI-AGS and Deep Linking seem to be working properly for me.

Also, what's the permission level of your user? Is he superuser or just staff?

@Alain1405
Copy link
Author

Alain1405 commented Jan 17, 2022

@giovannicimolin

Also, what's the permission level of your user? Is he superuser or just staff?

is a superuser.

LTI launches, LTI-AGS and Deep Linking seem to be working properly for me.

Do you have comprehensive theming enabled?

Can you try setting DCS_SESSION_COOKIE_SAMESITE = 'None' and trying to run the launches again?

We will try and get back to you

@OlhaShyliaieva
Copy link

@giovannicimolin I tried setting DCS_SESSION_COOKIE_SAMESITE = 'None' and it doesn’t help.
I guess that the main problem is the Lti1p3ApiAuthentication authentication class of LtiAgsLineItemViewset which always sets user in request as None. DarkLangMiddleware at the edx-platform handles every response and tries to get a user from a request in a not intelligent way.

I think that this issue can be resolved in several ways.
The first one is to implement user authentication which was discussed at #105 (review).
Screenshot 2022-01-18 at 19 25 29
Another quick decision is to change user which Lti1p3ApiAuthentication returns from None to AnonymousUser().
The last one is to make _activate_preview_language at DarkLangMiddleware more clever and handle a user by way like this https://github.com/openedx/edx-platform/blob/open-release/maple.1/common/djangoapps/xblock_django/user_service.py#L77

For example:

def _activate_preview_language(self, request, response):
        """
        Check the user's dark language setting in the session and apply it
        """
        auth_user = request.user and request.user.is_authenticated
        preview_lang = None
        if auth_user:
            ....

@giovannicimolin
Copy link
Contributor

giovannicimolin commented Jan 19, 2022

@Alain1405 @Alain1405 I hear you on the user issue, and I agree with your suggestions, but there might be a underlying problem we're not seeing that is surfacing this error.

The LTI-AGS endpoints are purely for server-to-server communication and should never try to load a template, so I'm wondering why the DarkLang middleware is kicking in.

  • Are you actively using the DarkLang middleware on your instances? (is your site multi-language?)
  • Can you debug the request coming in your platform (by adding a breakpoint and pasting request data here)? I'd like to check if the request itself is triggering some code that shouldn't be triggered.

@Alain1405
Copy link
Author

Are you actively using the DarkLang middleware on your instances? (is your site multi-language?)

Yes we do.

Can you debug the request coming in your platform (by adding a breakpoint and pasting request data here)? I'd like to check if the request itself is triggering some code that shouldn't be triggered.

We'll send soon.

@OlhaShyliaieva
Copy link

@giovannicimolin I set the breakpoint in _activate_preview_language method at DarkLangMiddleware. Here is the traceback please take a look and let me know if you need more information.

> /edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py(167)_activate_preview_language()
-> auth_user = request.user.is_authenticated
(Pdb) request
<WSGIRequest: GET '/api/lti_consumer/v1/lti/3/lti-ags'>
(Pdb) request.headers
{'Content-Length': '', 'Content-Type': 'text/plain', 'Host': '88b4-91-193-174-13.ngrok.io', 'User-Agent': 'python-requests/2.27.1', 'Accept': 'application/vnd.ims.lis.v2.lineitemcontainer+json', 'Accept-Encoding': 'gzip, deflate', 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImQ2ODkwZTllLWE3NDAtNDFlOC05MjBlLWVlMDMzYjYyNWQ2NSJ9.eyJzdWIiOiJhYTNjNjFkMi0xNjdmLTRkN2MtOWYzMS03ZWU3N2JjYjk4MDMiLCJpc3MiOiJodHRwOi8vODhiNC05MS0xOTMtMTc0LTEzLm5ncm9rLmlvIiwic2NvcGVzIjoiaHR0cHM6Ly9wdXJsLmltc2dsb2JhbC5vcmcvc3BlYy9sdGktYWdzL3Njb3BlL2xpbmVpdGVtIGh0dHBzOi8vcHVybC5pbXNnbG9iYWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9yZXN1bHQucmVhZG9ubHkgaHR0cHM6Ly9wdXJsLmltc2dsb2JhbC5vcmcvc3BlYy9sdGktYWdzL3Njb3BlL3Njb3JlIiwiaWF0IjoxNjQzNjQ2NDMzLCJleHAiOjE2NDM2NTAwMzN9.qimmDWo-DX4ptvo09U2hKhM16y2ycdlvI-UyUgXyDE1AdDRLc4hnGyn414VnqfJcYv0LqEB-DcFTDsscF-llown9l2F44-KM14xKhQlOaR6q7JNQ2XPt2LV8W_qmaxqniKmxf_KO13atlXPPRntsYX_TfPDCoT7uwPdKHecz6nasjf9a_8ISxA9F6Dp3Zv85hRmhbCNfpUn2_lMYRmAikbdbkmaCXmovmvr_XVHQzzKQoVs_MSpcY2Z8VJoYTKMJJXhbBQr9nqr1X5IJcataWuEHIDB90VZyVKacyHFHPOGTCDew3SwDuBkhquMr818lS26aqVs-5MKcZgTQxPbapA', 'X-Forwarded-For': '91.193.174.13', 'X-Forwarded-Proto': 'http'}
(Pdb) request.path_info
'/api/lti_consumer/v1/lti/3/lti-ags'
(Pdb) request.view_name
'LtiAgsLineItemViewset'
(Pdb) request.method
'GET'
(Pdb) request.content_type
'text/plain'
(Pdb) request.user
(Pdb) print(request.user)
None
(Pdb) request.auth
(Pdb) print(request.auth)
None
(Pdb) request.accepted_types
[<MediaType: application/vnd.ims.lis.v2.lineitemcontainer+json>]
(Pdb) next
AttributeError: 'NoneType' object has no attribute 'is_authenticated'
> /edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py(167)_activate_preview_language()
-> auth_user = request.user.is_authenticated
(Pdb) continue
2022-01-31 16:35:00,518 ERROR 2154 [root] [user None] [ip 91.193.174.13] signals.py:22 - Uncaught exception from None
Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 102, in process_response
    self._activate_preview_language(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 167, in _activate_preview_language
    auth_user = request.user.is_authenticated
AttributeError: 'NoneType' object has no attribute 'is_authenticated'
Internal Server Error: /api/lti_consumer/v1/lti/3/lti-ags
Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 102, in process_response
    self._activate_preview_language(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 167, in _activate_preview_language
    auth_user = request.user.is_authenticated
AttributeError: 'NoneType' object has no attribute 'is_authenticated'
2022-01-31 16:35:00,562 ERROR 2154 [django.request] [user None] [ip 91.193.174.13] log.py:224 - Internal Server Error: /api/lti_consumer/v1/lti/3/lti-ags
Traceback (most recent call last):
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/edx/app/edxapp/venvs/edxapp/lib/python3.8/site-packages/django/utils/deprecation.py", line 119, in __call__
    response = self.process_response(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 102, in process_response
    self._activate_preview_language(request, response)
  File "/edx/app/edxapp/edx-platform/openedx/core/djangoapps/dark_lang/middleware.py", line 167, in _activate_preview_language
    auth_user = request.user.is_authenticated
AttributeError: 'NoneType' object has no attribute 'is_authenticated'
[31/Jan/2022 16:35:00] "GET /api/lti_consumer/v1/lti/3/lti-ags HTTP/1.1" 500 129768 

@regisb
Copy link

regisb commented Jan 31, 2022

Here is an example of a request that triggers the error:

ipdb> pp(request.__dict__)                                                                                                                                                                                         
{
    'COOKIES': {},                                                                                                                                                                                                    
    'GET': <QueryDict: {}>,                                                                                                                                                                                           
    'LANGUAGE_CODE': 'en',                                                                                                                                                                                            
    'META': {
        'CONTENT_LENGTH': '',                                                                                                                                                                                    
        'CONTENT_TYPE': 'text/plain',                                                                                                                                                                            
        'DEBIAN_FRONTEND': 'noninteractive',                                                                                                                                                                     
        'DJANGO_SETTINGS_MODULE': 'lms.envs.tutor.development',                                                                                                                                                  
        'GATEWAY_INTERFACE': 'CGI/1.1',                                                                                                                                                                          
        'HOME': '/openedx',                                                                                                                                                                                      
        'HOSTNAME': '678e52b7e5e1',                                                                                                                                                                              
        'HTTP_ACCEPT': 'application/vnd.ims.lis.v2.lineitemcontainer+json',                                                                                                                                      
        'HTTP_ACCEPT_ENCODING': 'gzip, deflate',                                                                                                                                                                 
        'HTTP_AUTHORIZATION': 'Bearer '                                                                                                                                                                          
                                'eyJhbGciOiJSUzI1NiIsImtpZCI6ImViN2MyYTJmLTExMzYtNGNiNi1iNGJhLTJiZjc5ZjA5M2Q0NCJ9.eyJzdWIiOiJmOTdjMmM3ZS0yZDUxLTRhM2YtYTUyMC05NzE4ZmJhN2U3ZDQiLCJpc3MiOiJodHRwOi8vbG9jYWwub3Zlcmhhb
mcuaW86ODAwMCIsInNjb3BlcyI6Imh0dHBzOi8vcHVybC5pbXNnbG9iYWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9saW5laXRlbSBodHRwczovL3B1cmwuaW1zZ2xvYmFsLm9yZy9zcGVjL2x0aS1hZ3Mvc2NvcGUvcmVzdWx0LnJlYWRvbmx5IGh0dHBzOi8vcHVybC5pbXNnbG9i
YWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9zY29yZSIsImlhdCI6MTY0MzY0MTUzNywiZXhwIjoxNjQzNjQ1MTM3fQ.LmnvKnitxpzdOk7MaFdafYFeQw_ujdQ-cuTe5TKcYeikClOEIrWhaCWE9itI9s_E1ZRxW2i0tFfOo7-h61e-JFs4Y_QOHsg41UI9Qavi5rat4LGDjrV1rCqF
w2UMbDimNtkojfMJKnYd02pAfFtqOb7CamIz6L-9P0O6iaYSnb-fSPVZZXyVRkK4SGtM_5QYgWraUzWmkxNPm0bdZu_nBm1OgekCAM16nlmjciCSDnB4q-OV9c0VmGHRcwvKB-1EYHz6sKKnw7TNwDggbgZ5uD_8Cf77f3CDgRL5kCn1wfIfzYtdsjuB2EjeMAVEsCYjg6yGZMPrzFa
qHoEmKwI-Ow',                                                                                                                                                                                                      
        'HTTP_CONNECTION': 'keep-alive',                                                                                                                                                                         
        'HTTP_HOST': 'local.overhang.io:8000',                                                                                                                                                                   
        'HTTP_USER_AGENT': 'python-requests/2.27.1',                                                                                                                                                             
        'LC_ALL': 'en_US.UTF-8',                                                                                                                                                                                 
        'LMS_CFG': '/openedx/config/lms.env.json',                                                                                                                                                               
        'NO_PREREQ_INSTALL': '1',                                                                                                                                                                                
        'NO_PYTHON_UNINSTALL': '1',                                                                                                                                                                              
        'PATH': '/openedx/bin:/openedx/venv/bin:./node_modules/.bin:/openedx/nodeenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',                                                          
        'PATH_INFO': '/api/lti_consumer/v1/lti/4/lti-ags',                                                                                                                                                       
        'PWD': '/openedx/edx-platform',                                                                                                                                                                          
        'QUERY_STRING': '',                                                                                                                                                                                      
        'REMOTE_ADDR': '172.25.0.1',                                                                                                                                                                             
        'REMOTE_HOST': '',                                                                                                                                                                                       
        'REQUEST_METHOD': 'GET',                                                                                                                                                                                 
        'REVISION_CFG': '/openedx/config/revisions.yml',                                                                                                                                                         
        'RUN_MAIN': 'true',                                                                                                                                                                                      
        'SCRIPT_NAME': '',                                                                                                                                                                                       
        'SERVER_NAME': 'local.overhang.io:8000',                                                                                                                                                                 
        'SERVER_PORT': '8000',                                                                                                                                                                                   
        'SERVER_PROTOCOL': 'HTTP/1.1',                                                                                                                                                                           
        'SERVER_SOFTWARE': 'WSGIServer/0.2',                                                                                                                                                                     
        'SERVICE_VARIANT': 'lms',                                                                                                                                                                                
        'SETTINGS': 'tutor.development',                                                                                                                                                                         
        'STUDIO_CFG': '/openedx/config/cms.env.json',                                                                                                                                                            
        'TERM': 'xterm',    
        'TZ': 'UTC',
        'UWSGI_WORKERS': '2',
        'VIRTUAL_ENV': '/openedx/venv/',
        'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>,
        'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>,
        'wsgi.input': <django.core.handlers.wsgi.LimitedStream object at 0x7f879a4250d0>,
        'wsgi.multiprocess': False,
        'wsgi.multithread': True,
        'wsgi.run_once': False,
        'wsgi.url_scheme': 'http',
        'wsgi.version': (1, 0)},
        '_body': b'',
        '_cached_user': <django.contrib.auth.models.AnonymousUser object at 0x7f879a4252e0>,
        '_cors_enabled': True,
        '_current_scheme_host': 'http://local.overhang.io:8000',
        '_files': <MultiValueDict: {}>,
        '_messages': <django.contrib.messages.storage.session.SessionStorage object at 0x7f879a425f10>,
        '_post': <QueryDict: {}>,
        '_read_started': True,
        '_stream': <_io.BytesIO object at 0x7f87826b12c0>,
        'auth': None,
        'content_params': {},
        'content_type': 'text/plain',
        'environ': {'CONTENT_LENGTH': '',
                    'CONTENT_TYPE': 'text/plain',
                    'DEBIAN_FRONTEND': 'noninteractive',
                    'DJANGO_SETTINGS_MODULE': 'lms.envs.tutor.development',
                    'GATEWAY_INTERFACE': 'CGI/1.1',
                    'HOME': '/openedx',
                    'HOSTNAME': '678e52b7e5e1',
                    'HTTP_ACCEPT': 'application/vnd.ims.lis.v2.lineitemcontainer+json',
                    'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
                    'HTTP_AUTHORIZATION': 'Bearer '
                                        'eyJhbGciOiJSUzI1NiIsImtpZCI6ImViN2MyYTJmLTExMzYtNGNiNi1iNGJhLTJiZjc5ZjA5M2Q0NCJ9.eyJzdWIiOiJmOTdjMmM3ZS0yZDUxLTRhM2YtYTUyMC05NzE4ZmJhN2U3ZDQiLCJpc3MiOiJodHRwOi8vbG9jYWwub3Zlcm
        hhbmcuaW86ODAwMCIsInNjb3BlcyI6Imh0dHBzOi8vcHVybC5pbXNnbG9iYWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9saW5laXRlbSBodHRwczovL3B1cmwuaW1zZ2xvYmFsLm9yZy9zcGVjL2x0aS1hZ3Mvc2NvcGUvcmVzdWx0LnJlYWRvbmx5IGh0dHBzOi8vcHVybC5pbXNnb
        G9iYWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9zY29yZSIsImlhdCI6MTY0MzY0MTUzNywiZXhwIjoxNjQzNjQ1MTM3fQ.LmnvKnitxpzdOk7MaFdafYFeQw_ujdQ-cuTe5TKcYeikClOEIrWhaCWE9itI9s_E1ZRxW2i0tFfOo7-h61e-JFs4Y_QOHsg41UI9Qavi5rat4LGDjrV1r
        CqFw2UMbDimNtkojfMJKnYd02pAfFtqOb7CamIz6L-9P0O6iaYSnb-fSPVZZXyVRkK4SGtM_5QYgWraUzWmkxNPm0bdZu_nBm1OgekCAM16nlmjciCSDnB4q-OV9c0VmGHRcwvKB-1EYHz6sKKnw7TNwDggbgZ5uD_8Cf77f3CDgRL5kCn1wfIfzYtdsjuB2EjeMAVEsCYjg6yGZMPr
        zFaqHoEmKwI-Ow',
        'HTTP_CONNECTION': 'keep-alive',
        'HTTP_HOST': 'local.overhang.io:8000',
        'HTTP_USER_AGENT': 'python-requests/2.27.1',
        'LC_ALL': 'en_US.UTF-8',
        'LMS_CFG': '/openedx/config/lms.env.json',
        'NO_PREREQ_INSTALL': '1',
        'NO_PYTHON_UNINSTALL': '1',
        'PATH': '/openedx/bin:/openedx/venv/bin:./node_modules/.bin:/openedx/nodeenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
        'PATH_INFO': '/api/lti_consumer/v1/lti/4/lti-ags',
        'PWD': '/openedx/edx-platform',
        'QUERY_STRING': '',
        'REMOTE_ADDR': '172.25.0.1',
        'REMOTE_HOST': '',
        'REQUEST_METHOD': 'GET',                                                                                                                                                                              
        'REVISION_CFG': '/openedx/config/revisions.yml',
        'RUN_MAIN': 'true',
        'SCRIPT_NAME': '',
        'SERVER_NAME': 'local.overhang.io:8000',
        'SERVER_PORT': '8000',
        'SERVER_PROTOCOL': 'HTTP/1.1',
        'SERVER_SOFTWARE': 'WSGIServer/0.2',
        'SERVICE_VARIANT': 'lms',
        'SETTINGS': 'tutor.development',
        'STUDIO_CFG': '/openedx/config/cms.env.json',
        'TERM': 'xterm',
        'TZ': 'UTC',
        'UWSGI_WORKERS': '2',
        'VIRTUAL_ENV': '/openedx/venv/',
        'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>,
        'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>,
        'wsgi.input': <django.core.handlers.wsgi.LimitedStream object at 0x7f879a4250d0>,
        'wsgi.multiprocess': False,
        'wsgi.multithread': True,
        'wsgi.run_once': False,
        'wsgi.url_scheme': 'http',
        'wsgi.version': (1, 0)
    },
    'headers': {'Content-Length': '', 'Content-Type': 'text/plain', 'Host': 'local.overhang.io:8000', 'User-Agent': 'python-requests/2.27.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': 'application/vnd.ims.lis.v
    2.lineitemcontainer+json', 'Connection': 'keep-alive', 'Authorization': 'Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImViN2MyYTJmLTExMzYtNGNiNi1iNGJhLTJiZjc5ZjA5M2Q0NCJ9.eyJzdWIiOiJmOTdjMmM3ZS0yZDUxLTRhM2YtYTUyMC05NzE4Zm
    JhN2U3ZDQiLCJpc3MiOiJodHRwOi8vbG9jYWwub3ZlcmhhbmcuaW86ODAwMCIsInNjb3BlcyI6Imh0dHBzOi8vcHVybC5pbXNnbG9iYWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9saW5laXRlbSBodHRwczovL3B1cmwuaW1zZ2xvYmFsLm9yZy9zcGVjL2x0aS1hZ3Mvc2NvcGUvc
    mVzdWx0LnJlYWRvbmx5IGh0dHBzOi8vcHVybC5pbXNnbG9iYWwub3JnL3NwZWMvbHRpLWFncy9zY29wZS9zY29yZSIsImlhdCI6MTY0MzY0MTUzNywiZXhwIjoxNjQzNjQ1MTM3fQ.LmnvKnitxpzdOk7MaFdafYFeQw_ujdQ-cuTe5TKcYeikClOEIrWhaCWE9itI9s_E1ZRxW2i0t
    FfOo7-h61e-JFs4Y_QOHsg41UI9Qavi5rat4LGDjrV1rCqFw2UMbDimNtkojfMJKnYd02pAfFtqOb7CamIz6L-9P0O6iaYSnb-fSPVZZXyVRkK4SGtM_5QYgWraUzWmkxNPm0bdZu_nBm1OgekCAM16nlmjciCSDnB4q-OV9c0VmGHRcwvKB-1EYHz6sKKnw7TNwDggbgZ5uD_8Cf77
    f3CDgRL5kCn1wfIfzYtdsjuB2EjeMAVEsCYjg6yGZMPrzFaqHoEmKwI-Ow'},
    'method': 'GET',
    'path': '/api/lti_consumer/v1/lti/4/lti-ags',
    'path_info': '/api/lti_consumer/v1/lti/4/lti-ags',
    'resolver_match': ResolverMatch(func=lti_consumer.plugin.views.LtiAgsLineItemViewset, args=(), kwargs={'lti_config_id': '4'}, url_name=lti-ags-view-list, app_names=['lti_consumer'], namespaces=['lti_consumer'],
    route=^api/lti_consumer/v1/lti/(?P<lti_config_id>[-\w]+)/lti-ags$),
    'session': <django.contrib.sessions.backends.cache.SessionStore object at 0x7f879a4253a0>,
    'site': <Site: local.overhang.io:8000>,
    'site_theme': None,
    'user': None,
    'view_name': 'LtiAgsLineItemViewset'
}

As far as I understand, this is not a bug in DarkLangMiddleware but in the Lti1p3ApiAuthentication authentication backend, as described by @Alain1405. Returning (None, None) in this backend has the effect of setting request.user to None:


The DarkLangMiddleware fails because it is next in line in processing the response. Modifying the Darklang middleware does allow us to bypass the issue, but there are many places in the code base that assume that request.user is not None, so my (not-very-well-informed) opinion is that we should default to an anonymous user instead.

EDIT: hey I didn't notice @OlhaShyliaieva comment before posting mine :-/ Looks like we were working on this simultaneously.

@giovannicimolin
Copy link
Contributor

giovannicimolin commented Jan 31, 2022

@Alain1405 @OlhaShyliaieva @regisb Makes sense! Awesome deep dive investigating the issue. I don't see any other things that might be causing the issue, the LTI request is well-formed and coming in as expected.

Can one of you make a PR to change return (None, None) to return (AnonymousUser, None) on this line then? I'm a Core Contributor here and I can review/approve/merge.

@besonn
Copy link

besonn commented Jun 19, 2024

@Alain1405 I'm pretty sure I've bumped into this problem before. Can you check if the cookies from you Open edX instance have SameSite=None? If not, the cookies won't be sent when the page is redirected and the LMS will think it's an Unauthenticated request.

Let me do some testing on my end.

Edit: Can you try setting DCS_SESSION_COOKIE_SAMESITE = 'None' and trying to run the launches again? LTI launches, LTI-AGS and Deep Linking seem to be working properly for me.

Also, what's the permission level of your user? Is he superuser or just staff?

@giovannicimolin Hi there, I am new to the openedx, and not that familiar with it, but the same error occurred to me too. I am using tutor 17 and edx-platform quince (development version). So the bugs in lti-xblock-consumer should already be fixed? However, I met the exactly same error in this issue. I wonder how to fix this.

Is it because the DCS_SESSION_COOKIE_SAMESITE DCS_SESSION_COOKIE_SAMESITE_FORCE_ALL and ENABLE_COMPREHENSIVE_THEMING ? If so, how do I modify these parameters in tutor or edu-platform? If not, what actions should I take? Hope you can help out, it trapped me for quite a while .TAT.

@besonn
Copy link

besonn commented Jun 19, 2024

@giovannicimolin I am pretty sure I have set DCS_SESSION_COOKIE_SAMESITE = 'None' in edx-plarform/lms/env/. And I run both edx and LTI tools on a local machine. Edx uses port 8000 and 8001, and lti tools uses 9001.

The LTI tools is https://github.com/dmitry-viskov/pylti1.3-flask-example

@besonn
Copy link

besonn commented Jun 19, 2024

The error log in edx is below:

lms-1            | 2024-06-19 17:10:13,641 WARNING 114 [lti_consumer.plugin.views] [user None] [ip 172.19.X.X] views.py:496 - Permission on LTI Config <LtiConfiguration: [CONFIG_ON_XBLOCK] lti_1p3 - block-v1:edX+DemoX+Demo_Course+type@lti_consumer+block@ba1ec764026346b39f2cb233dce4f01a> denied for user <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x7f270d1e75e0>>:
lms-1            | 2024-06-19 17:10:13,648 DEBUG 114 [django.db.backends] [user None] [ip 172.19.X.X] utils.py:161 - (0.000) COMMIT; args=None; alias=default
lms-1            | [19/Jun/2024 17:10:13] "POST /api/lti_consumer/v1/lti/8/lti-dl/response HTTP/1.1" 403 7093

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Enhancements and Fixes - In Progress
Development

No branches or pull requests

5 participants