Skip to main content

Auth & Permissions

Identity model

  • Google Workspace is the primary sign-in for staff, restricted to the company hosted domain. A valid Google identity is not enough on its own — the user must already be provisioned in IPFOS and be ACTIVE.
  • Local email/password exists only for the root/fallback admin (bootstrap and recovery).
  • The auth service issues JWT access tokens plus rotating refresh tokens. Required claims: sub, role, permissions, email, iat, exp (issuer os-auth-service, audience os-platform).

Where auth is enforced

Each service enforces JWT validation and permission checks itself — the NestJS services via src/auth/jwt-auth.guard.ts and permissions.guard.ts, the auth service via Spring Security. Gateway-level JWT validation at Traefik is planned but not implemented today; do not assume a request that reached a service was pre-authenticated.

On the frontend, the decoded role and permissions ride along in the session cookie, and AccessControlProvider gates routes and dashboard cards — but that is UX, not security. The backend check is the real one.

Roles and permissions

Permissions are resource:action strings, seeded by Flyway migrations in the auth service (V2, V4, V6, V11, V13). There is deliberately no admin UI for editing roles — the catalog is code-managed.

DomainPermissions
Usersusers:read, users:write, users:invite, users:offboard
Ticketstickets:read:self, tickets:read:department, tickets:read:all, tickets:create, tickets:update, tickets:assign, tickets:comment, tickets:transition
Mealsmeals:read, meals:write, meals:select

Seeded roles:

RoleIntent
ROOT_ADMINBootstrap/recovery superuser (local login)
ADMINFull user and ticket control + meals read
EMPLOYEEStandard staff: read users, read/select meals, create/comment/transition own and department tickets
MEALS_STAFFMeals read/write only

The frontend mirrors this catalog read-only at Users → Roles Management (roles-catalog.ts); keep it in sync when Flyway seeds change.

Ticket-level access

Beyond global permissions, ticket actions depend on the caller's participant role on the specific ticket (ASSIGNEE, MANAGER, PMO, PM, OBSERVER) — e.g. only the assignee can close from IN_PROGRESS, while oversight roles, admins, and the creator can cancel-close a still-open ticket. See the User Guide's ticketing chapter for the full rules expressed in user terms.