⚠️ Porta is in beta — APIs and features may change before v1.0
Skip to content

Authentication Modes

Porta supports multiple authentication methods that can be configured per organization and per client. This page covers all login methods, two-factor authentication options, and how they're configured and enforced.

Overview

Porta provides a layered authentication system:

LayerMethodsDescription
Primary authenticationPassword, Magic LinkHow users prove their identity
Second factor (2FA)Email OTP, TOTP, Recovery CodesAdditional verification after primary auth

These layers combine to create flexible, secure authentication flows tailored to each organization's needs.

Login Method Matrix

ConfigurationLogin Page ShowsUse Case
[password, magic_link]Password form + magic link button + forgot passwordDefault — maximum flexibility
[password]Password form + forgot password onlyTraditional enterprise apps
[magic_link]Email input + magic link button onlyPasswordless-first experience

Password Authentication

Traditional email + password authentication with enterprise-grade security.

How It Works

Password Security

FeatureImplementation
Hashing algorithmArgon2id (winner of the Password Hashing Competition)
Password validationNIST SP 800-63B compliant
Minimum length8 characters (configurable)
Breach detectionChecks against known breached passwords
Timing-safe comparisonPrevents timing attacks on credential verification
Rate limitingRedis-backed per-email rate limiting on login attempts

Password Reset Flow

When password login is enabled, users can reset forgotten passwords:


Passwordless authentication via secure one-time email links. Users click a link in their email to log in — no password needed.

How It Works

FeatureImplementation
Token generationCryptographically secure random tokens
Token expiryConfigurable (default: 15 minutes)
Single useTokens are invalidated after first use
Rate limitingPrevents email flooding attacks
User enumeration protectionSame response regardless of whether email exists
Session bindingMagic link is bound to the OIDC interaction session

Magic link is ideal for:

  • Consumer applications where users dislike remembering passwords
  • Internal tools where email access implies authorization
  • Mobile-first experiences where typing passwords is cumbersome
  • Low-friction onboarding where you want to minimize signup steps

Two-Factor Authentication (2FA)

After successful primary authentication (password or magic link), Porta can require a second factor for additional security.

Email OTP

A 6-digit one-time password sent to the user's email.

FeatureDetail
Code format6 numeric digits
DeliveryEmail via configured SMTP
ExpiryConfigurable (default: 10 minutes)
Max active codes3 per user (prevents flooding)
TemplateCustomizable via emails/otp-code.hbs

User flow:

  1. User completes primary login (password or magic link)
  2. Porta generates a 6-digit code and stores it in the database
  3. Code is emailed to the user
  4. User enters the code on the verification page
  5. Porta validates the code (not expired, not used)
  6. Authentication is complete

TOTP (Authenticator Apps)

Time-based One-Time Password using authenticator apps like Google Authenticator, Authy, Microsoft Authenticator, or any TOTP-compatible app.

FeatureDetail
AlgorithmTOTP (RFC 6238)
Code format6 numeric digits, 30-second window
SetupQR code scanning or manual secret entry
Secret storageAES-256-GCM encrypted in PostgreSQL
VerificationTime-window tolerance (±1 step)

Setup flow:

  1. User navigates to 2FA setup
  2. Porta generates a TOTP secret and encrypts it with AES-256-GCM
  3. QR code is displayed for scanning with an authenticator app
  4. User enters a verification code from their app to confirm setup
  5. Recovery codes are generated and displayed (one-time view)

Login flow:

  1. User completes primary login
  2. Porta detects TOTP is configured for this user
  3. User enters the current 6-digit code from their authenticator app
  4. Porta verifies the code against the encrypted secret
  5. Authentication is complete

Recovery Codes

One-time backup codes for account recovery when the primary 2FA method is unavailable (lost phone, no email access).

FeatureDetail
Format8-character alphanumeric codes with dash (e.g., A1B2-C3D4)
Count10 codes generated per setup
StorageArgon2id hashed (not stored in plain text)
UsageEach code can be used exactly once
Case-insensitivea1b2-c3d4 matches A1B2-C3D4
Dash-insensitiveA1B2C3D4 matches A1B2-C3D4

Important

Recovery codes are shown only once during 2FA setup. Users should save them in a secure location. If all recovery codes are used and the primary 2FA method is lost, an admin must manually disable 2FA for the user.


Per-Organization Configuration

Each organization has a default_login_methods setting that controls which primary authentication methods are available to all clients in that organization.

Setting Organization Login Methods

Via CLI:

bash
# Enable both password and magic link (default)
porta org update <org-id> --login-methods password,magic_link

# Password only
porta org update <org-id> --login-methods password

# Magic link only
porta org update <org-id> --login-methods magic_link

Via Admin API:

bash
curl -X PUT http://localhost:3000/api/admin/organizations/<org-id> \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "defaultLoginMethods": ["password", "magic_link"] }'

2FA Organization Policy

2FA enforcement is configured per organization:

PolicyBehavior
optionalUsers can optionally enable 2FA in their account settings
encouragedUsers are prompted to set up 2FA but can skip
requiredAll users must configure 2FA before accessing applications

Per-Client Overrides

Individual clients can override the organization's default login methods. This allows different applications within the same organization to offer different login experiences.

Setting Client Login Methods

Via CLI:

bash
# Override to password only for this client
porta client update <client-id> --login-methods password

# Override to magic link only
porta client update <client-id> --login-methods magic_link

# Clear override (inherit from organization)
porta client update <client-id> --clear-login-methods

Via Admin API:

bash
# Set override
curl -X PUT http://localhost:3000/api/admin/clients/<client-id>/login-methods \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "loginMethods": ["password"] }'

# Clear override (inherit from org)
curl -X DELETE http://localhost:3000/api/admin/clients/<client-id>/login-methods \
  -H "Authorization: Bearer $TOKEN"

Resolution Logic

When a user initiates a login, Porta determines the available login methods using this resolution logic:

Enforcement Points

Login methods are enforced at five endpoints, before any user lookup or CSRF validation:

  1. GET /interaction/:uid — Login page rendering
  2. POST /interaction/:uid/magic-link — Magic link request
  3. GET /interaction/:uid/forgot-password — Password reset form
  4. POST /interaction/:uid/forgot-password — Password reset submission
  5. POST /interaction/:uid/reset-password — New password submission

If a user attempts to use a disabled login method, Porta responds with:

  • HTTP 403 status code
  • Audit event: security.login_method_disabled
  • Error message explaining the method is not available

Security Considerations

Rate Limiting

All authentication endpoints are rate-limited to prevent brute-force attacks:

EndpointLimitWindow
Password loginConfigurablePer email + org
Magic link requestConfigurablePer email + org
2FA code verificationConfigurablePer user
Password reset requestConfigurablePer email

Audit Logging

Every authentication event is logged for security monitoring:

EventLogged Data
auth.login.successUser ID, method, client, org, IP
auth.login.failureEmail attempted, failure reason, org, IP
auth.magic_link.sentEmail, org, IP
auth.magic_link.verifiedUser ID, org
auth.2fa.verifiedUser ID, method (otp/totp/recovery)
auth.2fa.failedUser ID, method, failure reason
auth.password_reset.requestedEmail, org
auth.password_reset.completedUser ID, org
security.login_method_disabledAttempted method, client, org

Timing-Safe Operations

Porta uses constant-time comparisons for all credential verification to prevent timing side-channel attacks:

  • Password verification via Argon2id (inherently timing-safe)
  • Magic link token comparison
  • TOTP code verification
  • Recovery code verification

Next Steps

Released under the MIT License.