-
Notifications
You must be signed in to change notification settings - Fork 0
Rule Types
This page documents all 5 rule types in detail, including their configuration, behavior with different claim value types, and concrete examples.
Every rule has the same base structure:
{
"id": "my-rule",
"type": "direct",
"enabled": true,
"claimPath": "department",
"config": {}
}| Field | Type | Description |
|---|---|---|
id |
string | Unique identifier for the rule |
type |
string | One of: direct, prefix, map, conditional, template
|
enabled |
boolean | Whether the rule is evaluated during login |
claimPath |
string | Dot-notation path to the claim in the token (see Claim path resolution) |
config |
object | Type-specific configuration (see below) |
Behavior when the claim is missing: If the claim path resolves to null (claim not present in the token), the rule produces no groups and is marked as not matched. This is safe — a missing claim never causes an error.
Uses the claim value directly as a group name.
No configuration needed — pass an empty object {}.
| Claim value | Result |
|---|---|
"Engineering" (string) |
["Engineering"] |
["admin", "editor"] (array of strings) |
["admin", "editor"] |
"" (empty string) |
[] (no groups) |
["admin", 42, "editor"] (mixed array) |
["admin", "editor"] (non-strings filtered out) |
null / missing claim |
[] (no groups) |
Token:
{ "department": "Engineering" }Rule:
{
"id": "departments",
"type": "direct",
"enabled": true,
"claimPath": "department",
"config": {}
}Output: ["Engineering"]
Best for claims whose values are already valid group names — like department, team, or a groups claim from your IdP.
Prepends a prefix string to each claim value.
| Key | Type | Description |
|---|---|---|
prefix |
string | The prefix to prepend to each value |
| Claim value | Prefix | Result |
|---|---|---|
"admin" (string) |
role_ |
["role_admin"] |
["admin", "editor"] (array) |
role_ |
["role_admin", "role_editor"] |
"" (empty string) |
role_ |
[] (empty strings are skipped) |
["admin", 42] (mixed array) |
role_ |
["role_admin"] (non-strings skipped) |
null / missing claim |
role_ |
[] (no groups) |
Token:
{ "roles": ["admin", "editor"] }Rule:
{
"id": "user-roles",
"type": "prefix",
"enabled": true,
"claimPath": "roles",
"config": { "prefix": "role_" }
}Output: ["role_admin", "role_editor"]
Useful when you want to namespace groups from a specific claim to avoid collisions. For example, IdP roles like admin might conflict with existing Nextcloud groups, so prefixing with role_ keeps them distinct.
Maps claim values through a lookup table. Each value is replaced by its mapped counterpart.
| Key | Type | Description |
|---|---|---|
values |
object | Lookup table: { "claimValue": "groupName" } or { "claimValue": ["group1", "group2"] }
|
unmappedPolicy |
string | What to do when a value isn't in the table: "ignore" (default) or "passthrough"
|
| Claim value | Map | Policy | Result |
|---|---|---|---|
"corp.example.com" |
{ "corp.example.com": "Staff" } |
ignore | ["Staff"] |
"unknown.com" |
{ "corp.example.com": "Staff" } |
ignore |
[] (value not in map → skipped) |
"unknown.com" |
{ "corp.example.com": "Staff" } |
passthrough |
["unknown.com"] (original value kept) |
["corp.example.com", "partner.example.com"] |
{ "corp.example.com": "Staff", "partner.example.com": "Partners" } |
ignore | ["Staff", "Partners"] |
"corp.example.com" |
{ "corp.example.com": ["Staff", "FullTime"] } |
ignore |
["Staff", "FullTime"] (one-to-many mapping) |
null / missing claim |
any | any |
[] (no groups) |
Token:
{ "organization": "corp.example.com" }Rule:
{
"id": "org-mapping",
"type": "map",
"enabled": true,
"claimPath": "organization",
"config": {
"values": {
"corp.example.com": "Staff",
"partner.example.com": "Partners"
},
"unmappedPolicy": "ignore"
}
}Output: ["Staff"]
Ideal when IdP claim values don't match your desired Nextcloud group names — for example, mapping domain names to human-readable groups, or mapping opaque role IDs to meaningful names. Also supports one-to-many mapping (one claim value → multiple groups).
Evaluates a condition against the claim value. If the condition matches, assigns a fixed list of groups.
| Key | Type | Description |
|---|---|---|
operator |
string | One of: equals, contains, regex
|
value |
string | The value to compare against |
groups |
array | Groups to assign if the condition matches |
| Operator | What it does | Claim type |
|---|---|---|
equals |
Exact string match: claimValue === value
|
string |
contains |
Array contains value: in_array(value, claimValue)
|
array |
regex |
Regex match: preg_match(value, claimValue)
|
string |
| Operator | Claim value | Config value | Matches? |
|---|---|---|---|
equals |
"INTERNAL" |
"INTERNAL" |
Yes |
equals |
"EXTERNAL" |
"INTERNAL" |
No |
equals |
["INTERNAL"] (array) |
"INTERNAL" |
No (equals only works on strings) |
contains |
["admin", "editor"] |
"admin" |
Yes |
contains |
"admin" (string) |
"admin" |
No (contains only works on arrays) |
regex |
"jdoe@example.com" |
"/@example\\.com$/" |
Yes |
regex |
["jdoe@example.com"] (array) |
"/@example\\.com$/" |
No (regex only works on strings) |
| any |
null / missing claim |
any | No |
Important: For the
regexoperator, the pattern must include delimiters (e.g.,/.../). Invalid regex patterns are silently treated as non-matching.
Token:
{ "userType": "INTERNAL" }Rule:
{
"id": "internal-flag",
"type": "conditional",
"enabled": true,
"claimPath": "userType",
"config": {
"operator": "equals",
"value": "INTERNAL",
"groups": ["Internal-Users"]
}
}Output: ["Internal-Users"]
Perfect for flag-based logic: "if the user is internal, add them to these groups". Also useful for regex-based matching on email domains, organization patterns, etc.
Applies a string template to each claim value. The placeholder {value} is replaced with the actual claim value.
| Key | Type | Description |
|---|---|---|
template |
string | Template string containing {value} placeholder |
| Claim value | Template | Result |
|---|---|---|
"Engineering" |
dept_{value} |
["dept_Engineering"] |
["admin", "editor"] |
role-{value} |
["role-admin", "role-editor"] |
"" (empty string) |
dept_{value} |
[] (empty strings skipped) |
null / missing claim |
any |
[] (no groups) |
Token:
{ "department": "Engineering" }Rule:
{
"id": "dept-template",
"type": "template",
"enabled": true,
"claimPath": "department",
"config": { "template": "dept_{value}" }
}Output: ["dept_Engineering"]
More flexible than prefix — you can place the value anywhere in the string (e.g., team-{value}-members). Use when you need a consistent naming pattern but the prefix alone isn't enough.
The claimPath field uses dot-notation to navigate nested token structures.
| Path | Resolves to |
|---|---|
department |
token.department |
roles |
token.roles |
| Path | Resolves to |
|---|---|
extended_attributes.domain |
token.extended_attributes.domain |
extended_attributes.auth.permissions |
token.extended_attributes.auth.permissions |
Some identity providers use URL-style claim names (common with Azure AD and custom OIDC providers):
| Path | Resolves to |
|---|---|
https://idp.example.com/claims/domain |
token["https://idp.example.com/claims/domain"] |
The resolver handles ambiguous paths (where dots could be part of a key name or a separator) using a progressive split strategy:
- Try the full path as a direct property name (handles URL-style keys with dots)
- If not found, try splitting on each dot from left to right, looking for the deepest valid path
This means https://idp.example.com/claims/extended_attributes.auth.permissions correctly resolves the URL-part first, then navigates into the nested object.
Given this token:
{
"department": "Engineering",
"https://idp.example.com/claims/domain": "corp.example.com",
"extended_attributes": {
"auth": {
"permissions": ["read", "write"]
}
}
}| Claim path | Result |
|---|---|
department |
"Engineering" |
https://idp.example.com/claims/domain |
"corp.example.com" |
extended_attributes.auth.permissions |
["read", "write"] |
nonexistent.path |
null |
OIDC Groups Mapping | Report an issue | Security policy | License: AGPL-3.0-or-later
Getting Started
Configuration
Automation
Help
Development