diff --git a/lms/djangoapps/courseware/testutils.py b/lms/djangoapps/courseware/testutils.py
index 91e8cf89e5a89c1ddfda48341943c3ba2d580ee0..35a44d7e9f1ffccf9600199cee229e58927e3201 100644
--- a/lms/djangoapps/courseware/testutils.py
+++ b/lms/djangoapps/courseware/testutils.py
@@ -10,7 +10,6 @@ from urllib.parse import urlencode
 
 import ddt
 
-from lms.djangoapps.courseware.field_overrides import OverrideModulestoreFieldData
 from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
 from openedx.features.course_experience.url_helpers import get_legacy_courseware_url
 from common.djangoapps.student.tests.factories import AdminFactory, CourseEnrollmentFactory, UserFactory
@@ -18,9 +17,12 @@ from xmodule.modulestore import ModuleStoreEnum
 from xmodule.modulestore.django import modulestore
 from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory, check_mongo_calls
 
+from .field_overrides import OverrideModulestoreFieldData
+from .tests.helpers import MasqueradeMixin
+
 
 @ddt.ddt
-class RenderXBlockTestMixin(metaclass=ABCMeta):
+class RenderXBlockTestMixin(MasqueradeMixin, metaclass=ABCMeta):
     """
     Mixin for testing the courseware.render_xblock function.
     It can be used for testing any higher-level endpoint that calls this method.
@@ -220,6 +222,12 @@ class RenderXBlockTestMixin(metaclass=ABCMeta):
         self.setup_user(admin=True, enroll=False, login=True)
         self.verify_response()
 
+    def test_success_unenrolled_staff_masquerading_as_student(self):
+        self.setup_course()
+        self.setup_user(admin=True, enroll=False, login=True)
+        self.update_masquerade(role='student')
+        self.verify_response()
+
     def test_success_enrolled_student(self):
         self.setup_course()
         self.setup_user(admin=False, enroll=True, login=True)
diff --git a/lms/djangoapps/courseware/views/views.py b/lms/djangoapps/courseware/views/views.py
index 895c74253cc934a1c8df55d41360a5e5aaf8ff0b..4e3ebeab7180321eee7ec816565aab20fc5fe48c 100644
--- a/lms/djangoapps/courseware/views/views.py
+++ b/lms/djangoapps/courseware/views/views.py
@@ -1700,7 +1700,6 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
         )
 
     staff_access = has_access(request.user, 'staff', course_key)
-    _course_masquerade, request.user = setup_masquerade(request, course_key, staff_access)
 
     with modulestore().bulk_operations(course_key):
         # verify the user has access to the course, including enrollment check
@@ -1709,6 +1708,18 @@ def render_xblock(request, usage_key_string, check_if_enrolled=True):
         except CourseAccessRedirect:
             raise Http404("Course not found.")  # lint-amnesty, pylint: disable=raise-missing-from
 
+        # with course access now verified:
+        # assume masquerading role, if applicable.
+        # (if we did this *before* the course access check, then course staff
+        #  masquerading as learners would often be denied access, since course
+        #  staff are generally not enrolled, and viewing a course generally
+        #  requires enrollment.)
+        _course_masquerade, request.user = setup_masquerade(
+            request,
+            course_key,
+            staff_access,
+        )
+
         # get the block, which verifies whether the user has access to the block.
         recheck_access = request.GET.get('recheck_access') == '1'
         block, _ = get_module_by_usage_id(