Skip to main content

Auth Service

The Auth service handles user authentication, session management, API tokens, and service account permissions. It is the single source of truth for identity and authorization across all services.

Features

  • User Management: Create, update, and delete users
  • Session Management: JWT-based authentication with configurable TTL
  • API Tokens: Scoped tokens for programmatic access (ecloud_ prefixed)
  • Service Accounts: Identity-based permission model with NATS-pushed scopes
  • Event Publishing: Publishes user and identity events to NATS
  • Token Validation: Service-to-service endpoint for token revocation and permission checks
  • Rate Limiting: IP-based and user-based rate limiting on login

Architecture

Access Control

Session Auth (website only)

Token and service account management requires a session JWT obtained by logging in through the web dashboard. API tokens cannot be used to create, modify, or delete tokens or service accounts.

Operations requiring session auth:

  • Create / list API tokens
  • Create / list / update / delete service accounts
  • Create / list service account tokens

Token Permission Reads

The auth service is the only service that can read permissions for a given token. Other services (compute, storage) validate API tokens by calling the auth service's /api/tokens/{id}/check endpoint with a service key. This ensures the auth service remains the single source of truth for revocation and scope changes.

Service-to-Service Auth

Internal endpoints use X-Service-Key header authentication. These are not accessible from the public internet.

API Endpoints

Base URL: https://auth.cloud.eddisonso.com

Authentication

MethodPathAuthDescription
POST/api/loginNoneAuthenticate user, returns JWT
POST/api/logoutSessionInvalidate session
GET/api/sessionSessionGet current session info

API Tokens

MethodPathAuthDescription
POST/api/tokensSessionCreate a new API token
GET/api/tokensSessionList user's API tokens

Service Accounts

MethodPathAuthDescription
POST/api/service-accountsSessionCreate a service account
GET/api/service-accountsSessionList user's service accounts
GET/api/service-accounts/{id}SessionGet service account details
PUT/api/service-accounts/{id}/scopesSessionUpdate service account scopes
DELETE/api/service-accounts/{id}SessionDelete a service account
POST/api/service-accounts/{id}/tokensSessionCreate a token for a service account
GET/api/service-accounts/{id}/tokensSessionList tokens for a service account

Service-to-Service (internal)

MethodPathAuthDescription
GET/api/tokens/{id}/checkService keyCheck token validity and get scopes
GET/api/usersService keyList all users
GET/api/identity-permissionsService keyList all service account permissions

Admin (requires admin role)

MethodPathAuthDescription
GET/admin/usersAdmin sessionList all users
POST/admin/usersAdmin sessionCreate new user
DELETE/admin/usersAdmin sessionDelete user
GET/admin/sessionsAdmin sessionList active sessions

Token Types

Session JWT

Issued on login, stored as a cookie. Used for web dashboard access.

{
"user_id": "abc123",
"username": "eddison",
"display_name": "Eddison",
"exp": 1707436800,
"iat": 1707350400
}

API Token

Prefixed with ecloud_, contains scoped permissions. Used for programmatic API access.

{
"user_id": "abc123",
"token_id": "tok_xyz",
"type": "api_token",
"scopes": {
"compute.abc123.containers": ["create", "read", "delete"],
"storage.abc123.files": ["read"]
}
}

Scope Format

Scopes follow the pattern: <root>.<user_id>[.<resource>[.<id>]]

RootResources
computecontainers, keys
storagenamespaces, files

Actions: create, read, update, delete

Scopes cascade — compute.uid.containers with read grants read access to all containers, while compute.uid.containers.abc with read grants access to only that container.

Database Schema

CREATE TABLE users (
id SERIAL PRIMARY KEY,
public_id TEXT UNIQUE NOT NULL,
username TEXT UNIQUE NOT NULL,
display_name TEXT,
password_hash TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE sessions (
id TEXT PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
expires_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE api_tokens (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
name TEXT NOT NULL,
token_hash TEXT NOT NULL,
scopes JSONB NOT NULL DEFAULT '{}',
expires_at BIGINT DEFAULT 0,
last_used_at BIGINT DEFAULT 0,
service_account_id TEXT REFERENCES service_accounts(id),
created_at BIGINT NOT NULL
);

CREATE TABLE service_accounts (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
name TEXT NOT NULL,
scopes JSONB NOT NULL DEFAULT '{}',
version BIGINT DEFAULT 1,
created_at BIGINT NOT NULL
);

Events Published

SubjectDescription
auth.user.{id}.createdNew user registered
auth.user.{id}.deletedUser deleted
auth.user.{id}.updatedUser profile updated
auth.session.{id}.createdUser logged in
auth.session.{id}.invalidatedUser logged out
auth.identity.{sa_id}.updatedService account permissions changed
auth.identity.{sa_id}.deletedService account deleted

Configuration

FlagDescriptionDefault
-addrHTTP listen address:8080
-session-ttlSession lifetime24h
-log-serviceLog service gRPC address(disabled)
Env VariableDescription
DATABASE_URLPostgreSQL connection string
JWT_SECRETSecret for signing JWTs
ADMIN_USERNAMEAdmin user identifier
DEFAULT_USERNAMEDefault user to create on startup
DEFAULT_PASSWORDPassword for default user
NATS_URLNATS server URL
SERVICE_API_KEYShared key for service-to-service auth

Health Check

GET /healthz → 200 OK