Security Model

Overview

Atlas Auth Guard implements a multi-layered security model combining:

  • Authentication: Verify user identity (Google OAuth, JWT, API Keys)

  • Authorization: Verify user has permission to access resources

  • Tenant Isolation: Ensure users only access resources within their organization

Hierarchy

Organization
  └── Team (service access policies)
        └── Project (data isolation)
              └── User (membership)

Key Principles

  1. Users belong to Teams: A user must be a team member before accessing team resources

  2. Projects belong to Teams: A user must be a team member before joining a project

  3. Teams have Service Policies: Teams define which backend services they can access

  4. Projects provide Data Isolation: Each project has isolated data within a service

Authentication Methods

1. JWT Token (User Authentication)

JWT tokens are issued after Google OAuth login and contain:

  • User identity (sub, email, name)

  • Organization context (org_id, org_name)

  • Team context (team_id, team_name)

  • Project context (project_id, project_name)

  • Roles (global_role, team_role, project_role)

  • Permissions (list of allowed actions)

2. API Key (Service/CLI Authentication)

API keys are scoped to a team and optionally a project:

  • Created by team/project admins

  • Bound to team_id at creation time

  • Can be further scoped to project_id

  • Have expiration dates

3. Service Account (S2S Authentication)

Google Cloud service accounts for service-to-service communication:

  • Uses Google OIDC tokens

  • Authorized via service policies in database

  • Endpoint-level access control

Role Hierarchy

Role Groups & Levels

Role-Permission Matrix

Global Scope Roles

Role
read
write
delete
manage_users
execute_services
api_keys
bypass_checks

super_admin

Organization Scope Roles

Role
read
write
delete
manage_users
execute_services
api_keys
bypass_checks

org_admin

member

Team Scope Roles

Role
read
write
delete
manage_users
execute_services
api_keys
bypass_checks

team_admin

team_member

Project Scope Roles

Role
read
write
delete
manage_users
execute_services
api_keys
bypass_checks

project_admin

editor

viewer

Access Rules

Security Check Bypass

global_role
Bypass Team Policy
Bypass Membership
Reason

super_admin

✅ Yes

✅ Yes

Platform-wide access

org_admin

✅ Yes

✅ Yes

Organization-wide access

member

❌ No

❌ No

Must have team context

Resource Visibility (/me/teams and /me/projects)

global_role

team_role

/me/teams

/me/projects

super_admin

-

ALL teams in org

ALL projects in org

org_admin

-

ALL teams in org

ALL projects in org

member

team_admin

Own teams

ALL projects in own teams

member

team_member

Own teams

ALL projects in own teams

member

-

Own teams

Only explicit memberships

Effective Role Calculation

When a user accesses a resource, their effective role determines permissions. The principle is most specific wins.

Precedence Order (Most Specific Wins)

Key Distinction: Access Checks vs Effective Role

Concept
What It Does
Who Bypasses

Access Checks

Team policy, membership verification

super_admin, org_admin

Effective Role

Determines permissions for a resource

Nobody - most specific wins

Global roles bypass ACCESS CHECKS but do NOT override explicit role assignments.

Decision Flow

Precedence Examples

Scenario
global_role
team_role
project_role
Effective Role
Why?

Super admin, no team/project role

super_admin

-

-

super_admin

Global fallback

Super admin, team member

super_admin

team_member

-

team_member

Team role wins

Super admin, explicit viewer

super_admin

team_admin

viewer

viewer

Project role wins

Org admin, no explicit roles

org_admin

-

-

org_admin

Global fallback

Team admin, no project role

member

team_admin

-

team_admin

Team role wins

Team admin, explicit viewer

member

team_admin

viewer

viewer

Project role wins

Team member, explicit editor

member

team_member

editor

editor

Project role wins

Only org member

member

-

-

member

Global fallback

Real-World Scenario

You are:

  • Global role: super_admin

  • Team X role: team_member

  • Project Y role: project_admin

What happens:

Accessing
Your Effective Role
Why

Project Y (explicit role)

project_admin

Explicit project role wins

Project Z (in Team X, no explicit role)

team_member

Team role applies

Project W (in Team B, no membership)

super_admin

No explicit role, global fallback + bypasses access checks

Important Notes

  1. Explicit project roles ALWAYS win for that specific project

    • Even super_admin can be restricted to viewer on sensitive projects

  2. Global roles bypass ACCESS CHECKS, not role assignments

    • super_admin can access any resource (bypasses team policy, membership checks)

    • But if they have explicit team/project roles, those determine permissions

  3. Team roles apply to ALL projects in that team

    • Unless overridden by explicit project role

  4. This follows industry standards:

    • AWS IAM: Resource policy > Identity policy

    • Kubernetes: RoleBinding > ClusterRoleBinding

    • Google Cloud: Resource-level > Folder > Org

Authorization Flow

Request Flow

Security Checks (in order)

  1. Authentication (401 if fails)

    • Validate JWT signature and expiration

    • Or validate API key hash and status

  2. User Status Check (403 if fails)

    • User must be active (not suspended, disabled, etc.)

  3. Team Policy Enforcement (403 if fails)

    • Bypassed for: super_admin, org_admin

    • Team must have access to the requested service

    • Configured via team_policies table

  4. Team/Project Membership Verification (403 if fails)

    • Bypassed for: super_admin, org_admin

    • User must be a member of the team in their JWT

    • If project_id in JWT, user must be a member (or team_admin/team_member in that team)

    • Prevents token manipulation attacks

  5. S2S Authorization (for service accounts)

    • Service account must be authorized for target service

    • Endpoint-level access control

  6. Rate Limiting

    • Applied after authorization

    • Per-user or per-API-key limits

Team Policies

Team policies control which services a team can access.

Database Schema

Example

Behavior

Team Policy
Service Request
Result

["atlas-ai-oss-svc"]

/v1/atlas-ai-oss-svc/...

✅ Allowed

["atlas-ai-oss-svc"]

/v1/cli-eval/...

❌ 403 Forbidden

enabled: false

Any service

❌ 403 Forbidden

No policy exists

Any service

❌ 403 Forbidden

Project Isolation

Projects provide data isolation within a service.

How It Works

  1. Auth Guard verifies user is a project member

  2. Auth Guard injects X-Project-ID header

  3. Backend Service filters data by X-Project-ID

Backend Responsibility

Backend services MUST filter data by X-Project-ID:

Access Scenarios

User Membership
Action
Result

User in Team A, Project X

Access Project X data

✅ Allowed

User in Team A, Project X

Access Project Y data

❌ 403 (not member)

User in Team A only (no project)

Access team-level API

✅ Allowed

User in Team A only (no project)

Access Project X data

❌ 403 (not member)

Membership Rules

Adding Users to Teams

Any user can be added to a team within their organization.

Adding Users to Projects

Security Rule: A user MUST be a team member before being added to a project.

If user is not a team member, the API returns:

Removing Users

  • Removing a user from a team automatically removes them from all projects in that team

  • Removing a user from a project does not affect team membership

Role-Based Access Control (RBAC)

Roles Hierarchy

Role Permissions

Role
Permissions

super_admin

All permissions

org_admin

Manage org, teams, users

team_admin

Manage team members, projects

project_admin

Manage project members, settings

editor

Read/write project data

viewer

Read-only access

Headers Injected by Auth Guard

The following headers are added to every request forwarded to backend services:

Core Headers

Header
Description
Example

X-User-ID

User's unique ID

google-oauth2|123456789

X-User-Email

User's email

X-User-Name

User's display name

John Doe

X-Org-ID

Organization ID

uuid

X-Org-Name

Organization name

Turing

X-Team-ID

Team ID

uuid

X-Team-Name

Team name

Engineering

X-Project-ID

Project ID (if applicable)

uuid

X-Project-Name

Project name (if applicable)

Alpha

X-Request-ID

Unique request ID for tracing

uuid

Role Headers

Header
Description
Example

X-Effective-Role

Calculated role based on precedence

team_admin

X-Global-Role

User's global role (raw)

member

X-Team-Role

User's role in team (raw)

team_admin

X-Project-Role

User's role in project (raw)

editor

X-Permissions

Permissions for effective role

["read:project", "write:project"]

Understanding X-Effective-Role

X-Effective-Role is the calculated role based on the precedence order:

Example scenarios:

X-Global-Role
X-Team-Role
X-Project-Role
X-Effective-Role
X-Permissions

super_admin

-

-

super_admin

ALL permissions

member

team_admin

-

team_admin

team_admin permissions

member

team_admin

viewer

viewer

viewer permissions

member

team_member

editor

editor

editor permissions

Backend services should use X-Effective-Role and X-Permissions for authorization decisions, not the raw role headers.

Security Best Practices

For Consumer Applications

  1. Always validate origin in postMessage handlers

  2. Store tokens securely (httpOnly cookies preferred over localStorage)

  3. Handle token expiration gracefully

  4. Use specific team/project context when available

For Backend Services

  1. Always filter by X-Project-ID for project-scoped data

  2. Validate X-Team-ID matches expected team for team-scoped operations

  3. Log X-Request-ID for audit trails

  4. Don't trust client-provided IDs - use header values from Auth Guard

For Administrators

  1. Regularly audit team policies to ensure least privilege

  2. Review API key usage and rotate expired keys

  3. Monitor failed authentication attempts

  4. Keep team/project membership up to date

Troubleshooting

403 Forbidden: Team Policy

Fix: Add the service to the team's policy via admin API.

403 Forbidden: Not Team Member

Fix: User needs to be added to the team, or re-login with correct team context.

403 Forbidden: Not Project Member

Fix: User needs to be added to the project by a team/project admin.

Last updated