OJS 3.5.0-4: Site admin gets 401 on userRoleAssignment API — "not authorized" on Users & Roles, 500 on Edit Profile

OJS version: 3.5.0-4
Server: Hostinger shared hosting (LiteSpeed), PHP 8.3, MySQL/MariaDB

Problem:
As the Site Administrator (user_id 1, also holds Journal Manager role in the
only journal), two admin pages fail:

  1. /management/settings/access (Users & Roles)
    → “You are not authorized to access the requested resource.”

  2. /management/settings/user/1 (Edit My Profile)
    → HTTP 500 (blank page)

Browser console shows the underlying cause on both pages:
Failed to load resource: 401 (userRoleAssignment)

So the page loads and then its background API call to userRoleAssignment
returns 401.

What I have already checked and ruled out:

  • Account is NOT disabled (users.disabled = 0)
  • Account holds role_id 1 (Site Admin) at context NULL, and role_id 16
    (Manager) in the journal context — verified in user_user_groups
  • config: installed = On
  • Cleared cache/t_compile, cache/_db, cache/*.php — no change
  • Fresh login / incognito / full cookie clear — no change
  • Found and removed TWO duplicate rows in user_user_groups for user_id 1
    (user_group_id 14 and 16 each appeared twice, one with NULL date_start
    and one with a timestamp). Removing duplicates did NOT fix the pages.
  • No orphaned role rows: every user_user_groups row for user 1 points to a
    valid existing user_group.
  • The failing request runs CLEAN via PHP CLI (bootstrapping index.php with
    the same REQUEST_URI produces no error) — it only 500s / 401s through the
    web server.

Because it works via CLI but fails via web, and the failing call is an API
endpoint returning 401, I suspect either an OJS authorization policy issue on
the userRoleAssignment handler, or the web server (LiteSpeed/mod_security)
stripping an auth/CSRF header on AJAX/API requests.

Questions:

  1. What authorization policy governs the userRoleAssignment API endpoint, and
    what would make it return 401 for a valid site admin?
  2. Could a stripped Authorization/CSRF header cause this, and how can I confirm
    it server-side?
  3. Any known issues with duplicate/expired role rows affecting this endpoint
    in 3.5.0-4?

Context: this journal recently went through a migration and a security cleanup,
so I’m open to it being residual data or a server-config issue.

I also encountered this issue yesterday. here also journal managers got the not authorized error. The only change we had is our custom built docker image - the one built on 2026-06-29 shows this issue, the one from 2026-06-22 did not show this issue.

I think I have a lead, it appears for some reason the forwarded IP is now no longer picked up. might be related with us changing the webserver.