Your question
Environment:
Stalwart, edition: community
Identity Provider: Authentik (OIDC)
Directory type: OpenID Connect
What I’m trying to do:
I want user roles/permissions in Stalwart to be driven dynamically by group membership in my IdP (Authentik), so that when a user is added to a group like devops on the IdP side, they automatically get the corresponding Stalwart role/permissions — without manual per-user configuration in Stalwart after every login.
Current config:
Directory (OIDC):
Type: OpenID Connect
Provider
Issuer URL: https://sso.example.com/application/o/stalwart-webui/
Required Scopes: openid, email
Claims
Username Claim: email
Groups Claim: groups
Group principal devops (id 2):
Type: Group account
Roles & Permissions
Roles:
Type: Custom role
Roles: DevOps Engineer (id: b3)
Permissions:
Type: Inherited permissions
Role DevOps Engineer (b3) — custom role with sysAccountGet, sysDirectoryGet, sysDomainGet and ~150 other sys*/action* permissions enabled.
Account (user):
Type: User account
Groups & Roles
Groups: m, 2
Roles:
Type: User role
Permissions:
Type: Inherited permissions
Decoded access token payload confirms the group claim is present and correctly received:
json
{
“groups”: [“users”, “devops”],
…
}
What happens:
GET /api/account with this user’s bearer token returns only the baseline consumer permission set (jmap*, imap*, emailReceive, authenticate, etc.) — none of the sys*/action* permissions from the DevOps Engineer role assigned to the devops group. Cache invalidation and a fresh authorization_code login didn’t change the result.
Questions:
- What is the correct/supported way to have a user’s roles/permissions be granted dynamically through an OIDC directory — i.e. without manually calling update Account --roles […] after every login? Is defaultGroupRoleIds on the Authentication singleton meant to cover this, and if so, what’s missing in the config above to make it apply?
- If a user is a member of a group (memberOf) and that group has a role with permissions attached — why doesn’t this merge/inherit into the effective permissions returned for the user itself? Per the docs (/docs/auth/authorization/permissions/), effective permissions are computed by “starting from the enabled permissions of any assigned roles” — is this scoped strictly to Account.roles, or does it also walk through Account.memberOf → Group.roles? Current behavior suggests the former, but it’s not stated explicitly either way in the docs.
- What’s the recommended pattern for keeping group-based permissions in sync dynamically in an SSO context — i.e. when group membership can change on the IdP side at any time, and I want Stalwart-side effective permissions to reflect that without manual intervention on every login? Is there a supported hook/sync mechanism, or does this require external automation reading OIDC claims and calling the management API to update Account.roles directly on each login?
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on