Skip to content

Fix OIDC login role downgrading for users without claims#3103

Merged
gantoine merged 3 commits intorommapp:masterfrom
pacnpal:master
Mar 9, 2026
Merged

Fix OIDC login role downgrading for users without claims#3103
gantoine merged 3 commits intorommapp:masterfrom
pacnpal:master

Conversation

@pacnpal
Copy link
Copy Markdown
Contributor

@pacnpal pacnpal commented Mar 9, 2026

Description
This pull request makes improvements to the OpenID Connect (OIDC) authentication flow, specifically around how user roles are updated based on OIDC claims. The main change is to ensure that a user's role is only updated if the OIDC provider actually supplies the relevant role claim, preventing unintended role changes when the claim is absent. Additionally, new tests have been added to verify this behavior.

OIDC role claim handling improvements:

  • The logic in get_current_active_user_from_openid_token (base_handler.py) now checks whether the OIDC role claim is present in userinfo before attempting to update a user's role, using a new claims_provided flag.
  • Role updates for existing users are now only performed if the OIDC role claim was actually provided, preventing accidental overwrites when the claim is missing.

Testing enhancements:

  • Added a new test test_oidc_valid_no_edit_user_role_if_claim_not_in_userinfo to ensure that user roles are not changed when the OIDC role claim is configured but not provided by the OIDC provider.

Checklist
Please check all that apply.

  • [ x] I've tested the changes locally
  • [x ] I've updated relevant comments
  • I've assigned reviewers for this PR
  • [ x] I've added unit tests that cover the changes

Copilot AI and others added 3 commits March 9, 2026 18:19
Copilot AI review requested due to automatic review settings March 9, 2026 18:41
@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Mar 9, 2026

Greptile Summary

This PR fixes a bug in the OIDC authentication flow where an existing user's role could be unintentionally overwritten (typically downgraded to VIEWER) when the OIDC provider was configured to supply role claims but omitted the claim from a particular userinfo response. The fix is minimal and surgical: a claims_provided boolean gate is introduced so that db_user_handler.update_user is only called when the role claim was genuinely present in the token, not merely when the claim key is configured. A corresponding test was added and follows the project's asyncio_mode = auto pattern correctly.

Key changes:

  • base_handler.py: Replaces the OIDC_CLAIM_ROLES and user.role != role guard with claims_provided and user.role != role, where claims_provided is only True when OIDC_CLAIM_ROLES is configured and present in userinfo.
  • test_oidc.py: New test test_oidc_valid_no_edit_user_role_if_claim_not_in_userinfo patches OIDC_CLAIM_ROLES/OIDC_ROLE_ADMIN, ensures "roles" is absent from the token's userinfo, and asserts that update_user is never called and the user's ADMIN role is preserved.

One note worth considering: When a new user (not yet in the database) logs in and the role claim is absent from userinfo, they are still created with the default Role.VIEWER. This is an asymmetry — existing users retain their current role, new users receive VIEWER. This pre-existing behaviour is unchanged by this PR and is arguably a safe default, but could be surprising in deployments where role claims are intermittently absent.

Confidence Score: 5/5

  • This PR is safe to merge — the change is minimal, targeted, and correctly fixes the role-downgrade bug without affecting any other code paths.
  • The fix is a one-line guard change backed by a well-structured new test. The logic is straightforward, the pre-existing test suite still covers all prior scenarios, and no regressions are introduced. The asyncio_mode = auto pytest config is already in place so the new async test will run correctly without any decorator changes.
  • No files require special attention.

Important Files Changed

Filename Overview
backend/handler/auth/base_handler.py Introduces a claims_provided flag to guard role updates for existing users — only updates the role when the OIDC role claim was actually present in userinfo, correctly fixing the role-downgrade bug.
backend/tests/handler/auth/test_oidc.py Adds test_oidc_valid_no_edit_user_role_if_claim_not_in_userinfo which verifies that an existing user's role is preserved when the configured OIDC role claim is absent from userinfo; test is well-structured and follows established project patterns.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Receive OIDC token] --> B{userinfo present?}
    B -- No --> ERR1[400 Bad Request]
    B -- Yes --> C{email present?}
    C -- No --> ERR2[400 Bad Request]
    C -- Yes --> D{email_verified check}
    D -- Fail --> ERR3[400 Bad Request]
    D -- Pass --> E["role = VIEWER\nclaims_provided = False"]
    E --> F{"OIDC_CLAIM_ROLES configured\nAND present in userinfo?"}
    F -- Yes --> G["claims_provided = True\nResolve role from claim"]
    G --> H{Role matched?}
    H -- No match --> ERR4[403 Forbidden]
    H -- Match --> I{User in DB?}
    F -- No --> I
    I -- "No (new user)" --> J["Create user with current role\n(VIEWER if claims_provided=False)"]
    I -- "Yes (existing user)" --> K{"claims_provided AND\nuser.role != resolved role?"}
    K -- No --> L[Preserve existing role]
    K -- Yes --> M[Update user role in DB]
    J --> N{user.enabled?}
    L --> N
    M --> N
    N -- No --> ERR5[UserDisabledException]
    N -- Yes --> Z[Return user, userinfo]
Loading

Last reviewed commit: cf6f69b

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts OIDC role-sync behavior so existing users’ roles are only updated when the OIDC provider actually supplies the configured roles claim, preventing unintended downgrades when the claim is absent.

Changes:

  • Gate role updates for existing users behind a new “roles claim present in userinfo” condition.
  • Add a regression test ensuring no role update occurs when the roles claim is configured but missing from userinfo.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
backend/handler/auth/base_handler.py Tracks whether the roles claim is present and only updates an existing user’s role when it is.
backend/tests/handler/auth/test_oidc.py Adds a test to prevent role downgrades when userinfo omits the configured roles claim.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@gantoine gantoine merged commit fe0191d into rommapp:master Mar 9, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants