Skip to main content

User Scopes

AuthProxy uses a scope-based access control system to restrict which API routes a user can reach. A user's scopes field holds a space-separated list of route paths, and a route opts into the check with the ScopeCheck route flag.

How Scopes Work

User (apguser)                          Route (route_map)
┌────────────────────────────┐ ┌──────────────────────────────┐
│ scopes: "/admin/v1/ /pay/v1/"│ │ path: "/admin/v1/" │
└──────────────┬─────────────┘ │ flags: ScopeCheck (8) │
│ └──────────────┬───────────────┘
└──────── user.scopes CONTAINS route.path ┘ ✓ Access granted
  1. Each user has a scopes field — a space-separated list of tokens. Each token is a route path the user is allowed to reach.
  2. A route enables the check by setting the ScopeCheck flag (value 8) in its route_map.flags. There is no separate scope column on the route.
  3. When a request matches a ScopeCheck route and a session is present, AuthProxy checks whether user.scopes contains the route's path.
  4. If the path is missing, the request is rejected with 403 Forbidden (AccessDenied).

Routes without the ScopeCheck flag are not scope-gated. Pkey/DAV/private requests (no session) bypass the scope check; protect those with CheckPubKey, Dav, or InternalApi instead.

User Scopes

Scopes are stored on the user profile (apguser.scopes) as a space-separated list. An empty value means no scoped routes are granted. The tokens are the literal route paths the user may access (for example /admin/v1/), matched verbatim against route_map.path.

Route Scopes

A route participates in scope checking purely through its ScopeCheck flag. The admin panel shows the URL prefix (path), target backend (address), and the behavior flags.

Examples:

Route pathFlagsEffect
/api/v1/(no ScopeCheck)Any authenticated user
/admin/v1/ScopeCheckOnly users whose scopes contains /admin/v1/
/pay/v1/ScopeCheckOnly users whose scopes contains /pay/v1/
/private/v1/InternalApiInternal services only (X-API-Key, no user scope)

Scope Checking

In Reverse Proxy

AuthProxy checks scopes in the ReverseProxyMiddleware:

  1. Request matches a route in route_map.
  2. Route has the ScopeCheck flag and the request carries a session.
  3. user.scopes is checked for the route's path.
  4. If missing → 403 Forbidden.

In Backend Services

When AuthProxy proxies a request, it forwards security context headers to the backend:

X-Crm: 123456
X-Project: 1
X-KeyType: 1
X-Scopes: /admin/v1/ /pay/v1/

X-Scopes carries the user's raw scopes string. X-KeyType is the numeric LoginMethod value of the session (e.g. 1 for PassKey), not a name — see Reverse Proxy. Backend services can perform additional checks for operations where route-level access is not enough.

In Admin Pages (Razor)

Admin pages use the shared admin scope helper to deny access before rendering sensitive data or executing scoped mutations.

Managing Scopes

Via Admin Panel

Navigate to /ProxyAdmin/EditUser to modify a user's scopes:

  • View current scopes
  • Add or remove route-path tokens
  • Changes take effect on the user's next request

Design Guidelines

  • Scopes are route paths — grant access by adding the exact route_map.path to the user's scopes.
  • Gate routes deliberately — only routes with the ScopeCheck flag are scope-restricted.
  • Combine with backend logic — use scopes for coarse route access, implement fine-grained permissions in your Core module.
  • Empty scope = no scoped routes — non-ScopeCheck routes still allow any authenticated user.