Skip to content

Add OIDC claim-based role mapping for auto-created users - #3233

Open
lby912 wants to merge 7 commits into
knadh:masterfrom
lby912:feature/oidc-role-mapping
Open

lby912 wants to merge 7 commits into
knadh:masterfrom
lby912:feature/oidc-role-mapping

Conversation

@lby912

@lby912 lby912 commented Sep 18, 2026

Copy link
Copy Markdown

Summary

This PR adds configurable OIDC claim-based role mapping for newly auto-created users.

It allows listmonk to assign user_role_id and/or list_role_id based on top-level claims present in the verified OIDC ID token.

The existing default OIDC roles remain the fallback when no mapping matches.

Motivation

OIDC auto-created users currently receive only the configured default user and list roles.

In environments where the identity provider already exposes authorization-related attributes, such as groups or departments, administrators may need newly created users to receive different listmonk roles based on those claims.

This PR adds a generic provider-independent mapping mechanism without introducing provider-specific logic.

Behavior

Mappings are evaluated in declaration order.

The first matching mapping wins.

Supported claim value types are:

  • string
  • array of strings

Matching is exact and case-sensitive.

Example:

[
  {
    "claim": "groups",
    "match": "listmonk-admin",
    "user_role_id": 1
  },
  {
    "claim": "department",
    "match": "AN",
    "user_role_id": 5,
    "list_role_id": 6
  }
]

For an ID token containing:

{
  "groups": [
    "users",
    "listmonk-admin"
  ],
  "department": "AN"
}

the first mapping matches and wins.

If a mapping defines only one role type, the configured default is preserved for the other role.

If no mapping matches, the existing OIDC default user and list roles are used.

Scope

Mappings are applied only when an unknown OIDC user is automatically created.

Existing users are not resynchronized on subsequent logins, even if their OIDC claims change.

This preserves the current behavior for existing accounts.

API

Two authenticated endpoints are added:

GET /api/settings/oidc/role-mappings
PUT /api/settings/oidc/role-mappings

The GET endpoint requires:

settings:get

The PUT endpoint requires:

settings:manage

The PUT endpoint validates:

  • non-empty claim
  • non-empty match
  • at least one of user_role_id or list_role_id
  • referenced user roles exist
  • referenced list roles exist

Invalid mappings return HTTP 400 and do not modify the current configuration.

The generic settings update path also preserves mappings when older clients do not send the role_mappings field, and validates mappings when they are present.

Backward compatibility

Existing installations without a role_mappings property continue to work unchanged.

For new installations, the default OIDC settings include:

"role_mappings": []

When no mappings are configured, OIDC auto-creation behaves exactly as before.

Implementation

The change:

  • preserves generic top-level claims from the verified OIDC ID token
  • adds a small claim matching and role resolving layer
  • applies mappings only from the OIDC auto-create path
  • adds validation and management endpoints
  • documents the feature in the OIDC documentation

No frontend changes are included.

Testing

Tested against the current master after rebasing.

Automated tests cover:

  • exact string matches
  • non-matching strings
  • case-sensitive matching
  • no substring matching
  • string-array claims
  • empty arrays
  • unsupported claim types
  • missing claims
  • default role fallback
  • user-role-only mappings
  • list-role-only mappings
  • first-match-wins behavior
  • mapping priority
  • validation of missing claim/match
  • validation of missing target roles
  • validation of unknown role IDs

Manual end-to-end testing covered:

  • existing OIDC user login
  • OIDC user auto-creation
  • default-role fallback
  • string claim mapping
  • group-array mapping
  • mapping priority
  • partial user/list role mappings
  • existing-user roles remaining unchanged
  • GET/PUT mapping API
  • rejected invalid mappings
  • mappings preserved after normal settings updates

Build and targeted tests pass on the rebased branch.

@knadh knadh added the hodor-review Automated AI code review label Sep 24, 2026

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Issues Found

No issues found.

Summary

Total issues: 0 critical, 0 important, 0 minor.

Overall Verdict

Status: Patch is correct

Explanation: Reviewed the PR diff for OIDC claim-based role mapping: role resolution, settings validation, schema default, and new settings endpoints are internally consistent and do not introduce obvious runtime errors or security regressions. The new mapping evaluation and validation logic appears safe for nil/empty cases and preserves existing default-role behavior when no mapping matches.


Review generated by Hodor (model: gpt-5.2)

Review Metrics — 17 turns, 16 tool calls, 2m 45s

  • Tokens: in 24.6K | cached 310.8K | out 12.2K (total 347.5K)
  • Cost: $0.2676

@knadh knadh self-assigned this Sep 24, 2026
@knadh knadh removed the hodor-review Automated AI code review label Sep 24, 2026

This branch has not been deployed

No deployments
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.

2 participants