Skip to content

User Groups

Groups allow you to organize users and include group membership information in access tokens and userinfo responses. Groups are managed via the admin API and can be used for role-based access control in your applications.

When the groups scope is requested and granted, the user’s group names are included as a groups claim in:

  • Access tokens – as an array of group name strings
  • ID tokens – as an array of group name strings
  • Userinfo responses – as a groups field

Example token claims:

{
"sub": "user-123",
"groups": ["admins", "developers", "team-alpha"],
"scope": "openid profile groups"
}

In Admin → Groups, choose Manage claims to add, replace, or remove a custom string claim. Members receive each claim under a literal group.claim key when the custom_claims scope is granted. For example, role=user on group app1 produces:

{ "app1.role": "user" }

Group app2 can independently define role=editor, producing app2.role. These are top-level keys, not nested objects. An individual claim named app1.role overrides that inherited value. An administrator can also assign that individual claim without adding the user to app1.

Group-local names may include role, email, or sub: they are always prefixed and cannot replace Autentico’s built-in claims. Names follow the existing bare custom-claim pattern and are limited to 128 characters; values are strings of up to 4096 characters, including empty strings.

The custom_claims scope controls inherited custom claims independently of the groups scope. See Custom Claims for individual overrides.

All group endpoints require admin authentication.

Method Endpoint Description
GET /admin/api/groups List all groups (paginated)
POST /admin/api/groups Create a new group
GET /admin/api/groups/{id} Get a group by ID
PUT /admin/api/groups/{id} Update a group
DELETE /admin/api/groups/{id} Delete a group
GET /admin/api/groups/{id}/members List members of a group
POST /admin/api/groups/{id}/members Add a user to a group
DELETE /admin/api/groups/{id}/members/{user_id} Remove a user from a group
GET /admin/api/groups/{id}/claims List group-local custom claims
POST /admin/api/groups/{id}/claims Create or update a group-local claim
DELETE /admin/api/groups/{id}/claims/{name...} Remove a group-local claim
GET /admin/api/users/{id}/groups Get groups for a specific user
Terminal window
curl https://auth.example.com/admin/api/groups \
-H "Authorization: Bearer $ADMIN_TOKEN"

Supports query parameters:

Parameter Description
sort Sort field: name, created_at, updated_at
order Sort order: asc (default), desc
search Search across name and description
limit Max results per page (1–100, default 100)
offset Number of results to skip (default 0)

Response:

{
"items": [
{
"id": "cq1abc123",
"name": "developers",
"description": "Engineering team",
"member_count": 5,
"created_at": "2026-01-15T10:00:00Z",
"updated_at": "2026-01-15T10:00:00Z"
}
],
"total": 1
}
Terminal window
curl -X POST https://auth.example.com/admin/api/groups \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "developers", "description": "Engineering team"}'
Field Required Validation
name Yes 1–100 characters, alphanumeric plus - and _ only
description No Up to 500 characters

Group names must be unique. Attempting to create a group with a duplicate name returns a 409 Conflict error.

Terminal window
curl -X POST https://auth.example.com/admin/api/groups/$GROUP_ID/members \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id": "user-123"}'

Returns 201 Created on success. Returns 409 Conflict if the user is already a member.

Terminal window
curl -X DELETE https://auth.example.com/admin/api/groups/$GROUP_ID/members/$USER_ID \
-H "Authorization: Bearer $ADMIN_TOKEN"
Terminal window
curl https://auth.example.com/admin/api/users/$USER_ID/groups \
-H "Authorization: Bearer $ADMIN_TOKEN"
Terminal window
curl -X POST https://auth.example.com/admin/api/groups/$GROUP_ID/claims \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"role","value":"user"}'

Posting an existing local name replaces its value. Lists return the local name (role), string value, and update timestamp in the same data envelope as user claims. Deletion uses the local name; percent-encode names containing slashes. Unknown groups return 404 on list/upsert; missing claims return 404 on deletion.

Column Type Description
id TEXT Primary key (xid)
name TEXT Unique group name
description TEXT Optional description
created_at DATETIME Creation timestamp
updated_at DATETIME Last update timestamp
Column Type Description
user_id TEXT Foreign key to users.id
group_id TEXT Foreign key to groups.id
created_at DATETIME When the membership was created

A unique constraint on (user_id, group_id) prevents duplicate memberships. Deleting a group cascades to remove all memberships.

Migration 23 adds group_id, claim_name, claim_value, created_at, and updated_at. The primary key is (group_id, claim_name). Deleting a group cascades to its claims. Inherited values are resolved through membership rather than copied into user_claims.