Porta v1.11.0
Skip to content

Capabilities ​

Porta is a full-featured, multi-tenant OpenID Connect (OIDC) provider designed for organizations that need enterprise-grade identity management with complete control over the authentication experience.

Multi-Tenant OIDC ​

Porta is multi-tenant from the ground up. Every organization gets its own isolated OIDC endpoints, user pool, and configuration — all from a single deployment.

CapabilityDescription
Path-based tenancyEach org gets its own OIDC namespace: /{orgSlug}/.well-known/openid-configuration
Per-org user poolsUsers belong to a specific organization; the same email can exist in different orgs
Per-org brandingLogo, favicon, primary color, company name, and custom CSS — all configurable via API
Per-org login methodsChoose which authentication methods are available per organization
Per-org 2FA policyEnforce two-factor authentication with configurable policies
Organization lifecycleActive or suspended for temporary control; permanent deletion is separately confirmed and audited

OIDC Standards Compliance ​

Built on the battle-tested node-oidc-provider library, Porta supports:

  • Authorization Code + PKCE — The recommended flow for all client types
  • Client Credentials — Machine-to-machine authentication
  • Refresh Tokens — Long-lived sessions with configurable TTLs
  • Discovery — Standard /.well-known/openid-configuration per organization
  • JWKS — Public key endpoint for token verification
  • UserInfo — Standard claims endpoint
  • Token Revocation and Introspection
  • End Session — RP-initiated logout

Intentional Omission

Porta does not support the Implicit flow. This is by design — the Authorization Code + PKCE flow is more secure and recommended by current OAuth 2.0 best practices.


Flexible Authentication ​

Porta supports multiple authentication methods that can be mixed and matched per organization and even per client.

Login Methods ​

MethodDescription
PasswordTraditional email + password with Argon2id hashing and NIST SP 800-63B compliant validation
Magic LinkPasswordless email-based authentication with secure one-time tokens

Login methods are configured at two levels:

  1. Organization default — Sets the baseline for all clients in the organization
  2. Per-client override — Individual clients can restrict or expand available methods
Organization default: [password, magic_link]
├── Client A: inherits → [password, magic_link]
├── Client B: override → [password]           # password only
└── Client C: override → [magic_link]         # magic link only

Two-Factor Authentication (2FA) ​

Porta provides three 2FA methods that can be combined:

MethodDescription
Email OTP6-digit code sent via email, configurable expiry
TOTPAuthenticator app support (Google Authenticator, Authy, etc.) with QR code setup
Recovery CodesOne-time backup codes for account recovery, Argon2id hashed

2FA can be enforced per-organization with policies:

  • Optional — Users choose whether to enable 2FA
  • Encouraged — Users are prompted but not required
  • Required — All users must configure 2FA

See Authentication Modes for the full deep dive.


Customizable Login UI ​

Every user-facing page in Porta — login, consent, password reset, magic link, 2FA, invitations, and all emails — is fully customizable.

Zero-Code Branding (API-Driven) ​

Without touching any templates, you can customize per organization via the Admin API or CLI:

SettingEffect
Logo URLDisplayed in page headers and email headers
Favicon URLBrowser tab icon
Primary ColorButtons, links, and accent colors (CSS --primary variable)
Company NamePage titles, headers, footers, and email signatures
Custom CSSUp to 10KB of raw CSS injected into every page (full style override)
bash
# Set branding via CLI
porta org branding <org-id> \
  --logo-url "https://example.com/logo.png" \
  --primary-color "#E11D48" \
  --company-name "Acme Corp"

Full Template Override ​

For complete UI control, Porta uses Handlebars templates with a clear structure:

templates/default/
├── layouts/main.hbs          # Base HTML layout (head, body wrapper)
├── pages/                     # Login, consent, password reset, 2FA, etc.
│   ├── login.hbs
│   ├── consent.hbs
│   ├── forgot-password.hbs
│   ├── reset-password.hbs
│   ├── magic-link-sent.hbs
│   ├── two-factor-verify.hbs
│   └── ... (12 pages total)
├── partials/                  # Reusable components (header, footer, flash)
├── emails/                    # HTML + plain-text email templates
│   ├── magic-link.hbs
│   ├── password-reset.hbs
│   ├── invitation.hbs
│   ├── otp-code.hbs
│   └── ... (6 email types × 2 formats)

Mount your own templates via Docker volume and override any or all pages:

yaml
# docker-compose.yml
services:
  porta:
    image: blendsdk/porta:latest
    volumes:
      - ./my-templates:/app/templates/default

See the Custom UI Tutorial for a complete step-by-step guide.


RBAC & Custom Claims ​

Role-Based Access Control ​

Porta provides a full RBAC system scoped per application:

  • Roles — Named collections of permissions (e.g., admin, editor, viewer)
  • Permissions — Granular actions (e.g., users:read, users:write, reports:export)
  • Role-Permission Mappings — Assign permissions to roles
  • User-Role Assignments — Assign roles to users per organization

Roles and permissions are included in OIDC tokens, so your applications can make authorization decisions without additional API calls:

json
{
  "sub": "user-uuid",
  "roles": ["admin", "editor"],
  "permissions": ["users:read", "users:write", "reports:export"]
}

Custom Claims ​

Define application-specific claims with type validation:

Claim TypeExample
stringdepartment: "Engineering"
numberemployee_id: 42
booleanis_manager: true
string[]teams: ["frontend", "platform"]

Custom claims are injected into OIDC tokens alongside standard claims, giving your applications rich user context without extra API calls.


Admin Tooling ​

CLI (porta) ​

A comprehensive command-line tool for managing every aspect of Porta:

CommandDescription
porta initBootstrap the admin system (first-time setup)
porta login / logout / whoamiOIDC-based CLI authentication
porta orgCreate, list, update, suspend, delete organizations + branding
porta appManage applications, modules, roles, permissions, claims
porta clientCreate clients, manage secrets, configure login methods
porta userFull user lifecycle, roles, claims, 2FA management
porta keysES256 signing key management (list, generate, rotate)
porta configClosed global operational catalog with native values and restart guidance
porta auditView audit logs with filtering
porta migrateDatabase migration management

REST Admin API ​

Deployment-global configuration exposes exactly 18 editable keys with server-owned defaults, inclusive bounds and modes; administrators cannot create, rename or delete keys. Bootstrap settings, internal identities and secrets remain outside this API. See the editable catalog. Reads require admin:config:read, writes admin:config:update. The conventional CLI reads metadata before a write and therefore needs both. The embedded Admin UI offers System Configuration… with four full-page tabs and one changed-key atomic Save. Runtime values are visible immediately to local post-save reads and converge on other healthy instances within the existing 60-second cache lifetime. Changing the five provider-startup lifetime values requires restarting every server instance; Porta does not restart them automatically.

Authenticated CLI operations use the Bearer-token-protected REST API at /api/admin/*. Bootstrap database commands such as init and migrate connect directly to PostgreSQL:

  • 10 Organization endpoints — CRUD, status transitions, branding
  • 11 Application endpoints — CRUD, modules
  • 10 Client endpoints — CRUD, secrets, login methods
  • 13 User endpoints — CRUD, status transitions, passwords, 2FA
  • 9 Role endpoints — CRUD, permission assignment
  • 6 Permission endpoints — CRUD
  • 9 Custom Claim endpoints — Definitions and user values
  • Plus: config, keys, audit log endpoints

Security & Compliance ​

FeatureImplementation
Token SigningES256 (ECDSA P-256) — keys auto-generated, stored as PEM in database
Password HashingArgon2id with NIST SP 800-63B compliant validation
Client SecretsArgon2id hashed with SHA-256 pre-hash for length normalization
PKCERequired for public clients, supported for all
CSRF ProtectionToken-based CSRF on all form submissions
Rate LimitingRedis-backed per-IP limiting: token (30/5min), admin API (60/60s), introspection (100/60s), login interactions
Account LockoutAuto-lock after N failed logins (default: 5), auto-unlock after cooldown (default: 15 min)
Audit LoggingEvery admin operation and security event logged with actor, target, metadata
Audit RetentionConfigurable audit_retention_days with CLI/API cleanup command
CORSConfigurable per OIDC endpoint
Session SecurityShort-lived sessions in Redis with signed cookies
Key RotationActive/retired/revoked key lifecycle with JWKS endpoint
2FA Secret EncryptionAES-256-GCM for TOTP secrets at rest
Recovery Code HashingArgon2id for recovery codes
Secure HeadersCSP, X-Frame-Options, X-Content-Type-Options on all responses
No Information LeakageRoot page returns neutral content; no product/vendor identification
PII RedactionSensitive fields (password, token, cookie, client_secret) redacted from all log output
Config SafetyProduction startup validation — rejects dev placeholders, weak keys, insecure URLs (9 rules)
Body Size Limits100 KB limit on JSON, form, and text request bodies
Graceful ShutdownSIGTERM/SIGINT → drain connections → close DB/Redis → 10s kill switch
User Data ControlData export and physical user deletion via API and CLI
Prometheus MetricsOptional GET /metrics endpoint with prom-client (counter, default Node.js metrics)
Readiness ProbeGET /ready with DB + Redis connectivity check (2s timeout)

Infrastructure ​

ComponentTechnology
RuntimeNode.js ≥ 22
FrameworkKoa (required for node-oidc-provider compatibility)
LanguageTypeScript (strict mode)
DatabasePostgreSQL 16
Cache/SessionsRedis 7
OIDC Enginenode-oidc-provider 9.x
DeploymentDocker image, Docker Compose, or standalone

Hybrid Storage Architecture ​

Porta uses a hybrid adapter strategy for optimal performance:

Data TypeStorageReason
Sessions, Interactions, Auth CodesRedisEphemeral, high-speed, auto-expiry
Access Tokens, Refresh Tokens, GrantsPostgreSQLDurable, queryable, audit trail
Organizations, Users, Clients, RolesPostgreSQLPrimary data store
Tenant resolution, RBAC lookupsRedis cachePerformance with graceful degradation

At a Glance ​

CapabilityPorta
Multi-tenant✅ Path-based org isolation
OIDC compliant✅ Authorization Code + PKCE, Client Credentials, Refresh
Password login✅ Argon2id + NIST validation
Magic link login✅ Secure one-time email tokens
2FA — Email OTP✅ Configurable expiry
2FA — TOTP✅ Authenticator app with QR setup
2FA — Recovery codes✅ Argon2id hashed backup codes
Per-org login methods✅ Default + override per client
Account lockout✅ Auto-lock/unlock with configurable thresholds
Custom login UI✅ Handlebars templates + Docker volume mount
Per-org branding (API)✅ Logo, colors, CSS, company name
Custom email templates✅ HTML + plain text
RBAC✅ Roles + permissions per application
Custom claims✅ Type-validated, injected into tokens
Admin CLI✅ 14+ commands
Admin REST API✅ Bearer-token-authenticated, 70+ endpoints
Audit logging✅ All operations logged with configurable retention
Rate limiting✅ Per-IP on token, admin API, introspection, login
Key rotation✅ ES256 with lifecycle management
User data control✅ Data export + physical deletion
Prometheus metrics✅ Optional /metrics endpoint
Readiness probe✅ GET /ready with DB + Redis check
Config safety✅ Production startup validation (9 rules)
PII redaction✅ Sensitive fields redacted from logs
Graceful shutdown✅ SIGTERM drain with 10s kill switch
i18n✅ Locale-based translations
Docker support✅ Production-ready image

Released under the MIT License.