{"record":{"id":"ff259eae6e2624b4","repo":"instructure/canvas-lms","slug":"authentication-required-to-view-other-users-module-progress","errorCode":null,"errorMessage":"Authentication required to view other users' module progress","messagePattern":"Authentication required to view other users' module progress","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"error","filePath":"app/graphql/types/course_type.rb","lineNumber":720,"sourceCode":"\n    field :settings, CourseSettingsType, \"Settings for the course\", null: true\n    def settings\n      preload_course_permissions.then do\n        next nil unless course.grants_right?(current_user, :read)\n\n        course\n      end\n    end\n\n    private\n\n    def apply_module_filters(scope, filter)\n      if filter[:completion_status]\n        # Handle unauthenticated users viewing public courses\n        if current_user.nil?\n          # Unauthenticated users cannot view other users' progress\n          if filter[:user_id]\n            raise GraphQL::ExecutionError, \"Authentication required to view other users' module progress\"\n          end\n\n          # For unauthenticated users, only \"incomplete\" filter returns modules\n          # All other filters return empty since they have no progress\n          case filter[:completion_status]\n          when \"incomplete\"\n            return scope # All modules are incomplete for unauthenticated users\n          else\n            return scope.none # No completed/in_progress/not_started modules\n          end\n        end\n\n        target_user = if filter[:user_id]\n                        User.find(filter[:user_id])\n                      else\n                        current_user\n                      end\n","sourceCodeStart":702,"sourceCodeEnd":738,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/types/course_type.rb#L702-L738","documentation":"In apply_module_filters, when a completion_status filter is requested on a public course by an unauthenticated user (current_user nil) and a user_id is also given, the type refuses to show another user's progress and raises 'Authentication required to view other users' module progress'.","triggerScenarios":"modules(filter: { completionStatus: ..., userId: ... }) on a public course while not logged in.","commonSituations":"Public course preview pages rendering module progress with a stale/other-user user_id; anonymous API crawlers passing userId; shared preview links carrying query params into the GraphQL call.","solutions":["Authenticate the request before passing user_id in the module filter","Omit user_id when unauthenticated (only completionStatus: \"incomplete\" will return modules)","Strip user_id from the filter for anonymous users in the UI layer"],"exampleFix":"// before\nmodules(filter: { completionStatus: \"complete\", userId: gid })  // anonymous\n// after\nconst filter = currentUser\n  ? { completionStatus: \"complete\", userId: gid }\n  : { completionStatus: \"incomplete\" }","handlingStrategy":"validation","validationCode":"const filter = isAuthenticated ? { completionStatus, userId } : { completionStatus: 'incomplete' }","typeGuard":"function canPassUserId(auth) { return !!auth?.current_user }","tryCatchPattern":"try { await query(MODULES_QUERY) } catch (e) { if (e.message.includes('Authentication required')) { redirectToLogin() } }","preventionTips":["Strip user_id from module filters for anonymous sessions","Only show progress filters to logged-in users on public courses","Remember anonymous users only get 'incomplete' results"],"tags":["graphql","authentication","modules"],"backgroundTag":"authentication-required","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}