go-auth
Routes

App authorization

Optional app role, business permission, assignment and library catalog routes.

App authorization

WithAppPermissions(AppPermissionsConfig{Enable:true}) exposes self access. EnableManagementHTTP:true additionally exposes the management routes below. All require a valid session. Management writes also use the configured CSRF token and origin checks. Every route is wrapped with rate limiting.

Account, role and permission IDs supplied to app authorization operations must be lowercase, hyphenated UUIDs, exactly as returned by the API. Uppercase, compact, brace-wrapped and urn:uuid: forms return 400 invalid_input. The same rule applies to administrative appRoleId bodies and filters, and to direct Go service inputs.

Method and pathAccessRequest
GET /auth/accessAuthenticated account with an enabled current roleNone
GET /admin/authorization/library-permissionsProtected admin plus required MFANone; fixed {permissions:[{key,name,description}]} without installation status
PATCH /admin/authorization/library-permissionsProtected admin plus required MFA{create:[keys],delete:[keys]}; 1–100 total, atomic
GET /admin/authorization/permissionsgoauth.app.permissions.readOptional limit, offset query; {permissions:[...]}
POST /admin/authorization/permissionsgoauth.app.permissions.create{key,name,description}; returns definition, 201
PATCH /admin/authorization/permissions/{permissionID}goauth.app.permissions.updateIf-Match header; {name?,description?,isEnabled?}; business only
DELETE /admin/authorization/permissions/{permissionID}goauth.app.permissions.deleteRequired If-Match header; 204
GET /admin/authorization/rolesgoauth.app.roles.readOptional limit, offset query; {roles:[...]} with explicit keys
POST /admin/authorization/rolesgoauth.app.roles.create{slug,name,description?,permissionKeys?}; returns role, 201
PATCH /admin/authorization/roles/{roleID}goauth.app.roles.updateIf-Match header; {name?,description?,isEnabled?}
PUT /admin/authorization/roles/{roleID}/permissionsgoauth.app.roles.updateIf-Match header; {permissionKeys:[...]}; replaces entire grant set
DELETE /admin/authorization/roles/{roleID}goauth.app.roles.deleteRequired If-Match header; 204
GET /admin/authorization/users/{id}/rolegoauth.app.roles.readNone; {role,assignmentRevision}
GET /admin/authorization/users/{id}/accessgoauth.app.roles.readNone; target account's {role,isFullAccess,permissionKeys,assignmentRevision,revision}
PUT /admin/authorization/users/{id}/rolegoauth.app.roles.assign{roleId,expectedRoleRevision,expectedAssignmentRevision}; returns assignment

Guarded permission/role PATCH, grant-replacement PUT and DELETE requests all require one strong revision tag in If-Match, for example If-Match: "3", from that resource's revision. Do not send expectedRevision in JSON or the query string; these former transports are rejected. Missing/malformed headers return 400 invalid_input; weak tags, wildcards and tag lists are unsupported. Stale preconditions return 412 with the existing authorization conflict code. Other business conflicts still return 409. Role assignment retains the two JSON fields expectedRoleRevision and expectedAssignmentRevision, because it checks two separate records. Direct Go service inputs retain ExpectedRevision.

All other successful reads/updates return 200. Optional description defaults to empty. Management JSON rejects unknown fields and trailing documents and is limited to 64 KiB. Actor identity comes from the session. Lists default to 20, accept limits 1–100 (0 selects default), and require nonnegative offsets.

Permission and role responses contain IDs, metadata, enabled state, revision and timestamps. Definitions also contain key and isSystem. Roles contain slug, optional systemKey and explicit permissionKeys. Protected admin's unrestricted policy is reported through access responses' isFullAccess, rather than an invented wildcard grant.

{
  "role": {"id":"ROLE_ID","slug":"support","name":"Support","description":"","isEnabled":true,"revision":2,"permissionKeys":[],"createdAt":"2026-10-07T12:00:00Z","updatedAt":"2026-10-07T12:00:00Z"},
  "isFullAccess": false,
  "permissionKeys": ["goauth.app.sessions.revoke"],
  "assignmentRevision": 2,
  "revision": 4
}

Both access routes use this response shape. The role field supplies identity metadata; effective keys are in the top-level permissionKeys and exclude disabled definitions. These responses describe application access; organization membership and roles remain separate. Treat them as UI information. Use server-side RequirePermission or RequireAppPermission for enforcement.

GET /auth/access is the canonical self-service route, alongside /auth/me and /auth/sessions. The target-access route belongs to authorization management and is exposed only with EnableManagementHTTP:true. It requires the current goauth.app.roles.read grant or protected-admin access, plus required MFA, even when {id} is the caller's own ID. The caller's session supplies actor identity; {id} selects only the account being inspected. It does not impersonate that account or check assurance against that account's sessions.

Malformed target IDs return 400. A missing, banned, unassigned, or disabled-role target returns 403; inspecting it does not return an effective access snapshot. Backend failures remain errors. All access checks still reload current state.

Permission-key checks, ownership protection, delegation limits and revision checks also run inside the services. Installation/removal of library keys never becomes a delegable permission. See the implementation and usage guide.

Assigning the user's current role returns 200 without changing the assignment or global revision or recording a role-change audit event. The actor must still pass authorization and required MFA, and both expected revisions must be current.

On this page