Security Features
Defence-in-depth capabilities of the Orion Identity Platform
FIDO2 / WebAuthn
Orion supports passwordless and second-factor authentication via the WebAuthn standard using the Fido2NetLib library.
Registration
- Users navigate to Account Manager → Edit Account
- Click "Register Security Key" to initiate a WebAuthn credential creation ceremony
- The browser prompts for a hardware security key (USB, NFC) or platform authenticator (Touch ID, Windows Hello)
- The public key credential is stored in the Orion database, linked to the user
- An initial verification challenge confirms the key works before activation
Authentication
- During login, if the user has an active FIDO2 authenticator, they are prompted after password entry
- The server generates a challenge, the browser signs it with the registered credential
- The server verifies the assertion against the stored public key
Configuration
# Set the Relying Party domain (must match the login domain) ORION_FIDO2_DOMAIN="login.yourdomain.com" # Set allowed origins (space or comma-separated absolute URIs) ORION_FIDO2_ORIGINS="https://login.yourdomain.com"
TOTP (Time-Based One-Time Passwords)
Orion supports TOTP-based two-factor authentication compatible with apps like Google Authenticator, Authy, and 1Password.
Setup
- Users navigate to Account Manager → Edit Account
- Click "Register OTP" to generate a new TOTP secret
- A QR code is displayed containing the
otpauth://URI - Scan the QR code with an authenticator app
- Enter the current 6-digit code to verify and activate
During Login
If TOTP is active, after entering email and password, the user is prompted for a 6-digit code. The code is validated using a standard time-window tolerance (30-second steps with one step grace period).
Account Lockout
Orion protects against brute-force password attacks with configurable account lockout.
| ORION_LOCKOUT_MAX_ATTEMPTS | Maximum failed attempts before lockout. Default: 5 |
| ORION_LOCKOUT_WINDOW_MINUTES | Window in which attempts are counted. Default: 15 minutes |
| ORION_LOCKOUT_DURATION_MINUTES | How long the account is locked. Default: 30 minutes |
How it works:
- Each failed login attempt increments a counter for the user
- Only attempts within the configured window are counted
- When the maximum is reached, the account is locked for the configured duration
- Successful login resets the counter
- Locked accounts receive a generic error message (no information leakage about lockout state)
PKCE (Proof Key for Code Exchange)
PKCE prevents authorization code interception attacks and is required by default for all OAuth clients in Orion. This follows the current best practice recommendation from RFC 7636 and the OAuth 2.1 draft specification.
How PKCE Works
// 1. Client generates a random code_verifier code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" // 2. Client computes code_challenge = BASE64URL(SHA256(code_verifier)) code_challenge = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM" // 3. Authorization request includes code_challenge + method GET /oauth/{org}/authorize?...&code_challenge=E9Mel...&code_challenge_method=S256 // 4. Token exchange includes code_verifier POST /oauth/{org}/token grant_type=authorization_code&code=...&code_verifier=dBjft... // 5. Server verifies: SHA256(code_verifier) == stored code_challenge
The RequirePkce setting on each application
controls whether PKCE is mandatory. It defaults to true.
Only disable it for legacy clients that cannot support PKCE.
Client Secret Rotation
Orion supports multiple active client secrets per application, enabling zero-downtime rotation:
Create a new secret
In the Application Manager, generate a new client secret with an optional label and expiry date.
Deploy the new secret
Update your application's configuration to use the new secret. Both old and new secrets are valid simultaneously.
Revoke the old secret
Once all instances are using the new secret, revoke the old one via the Management UI.
Security properties:
- Secrets are stored as SHA-256 hashes — the plaintext is shown exactly once at creation
- Expired secrets are automatically rejected during authentication
- Revoked secrets are immediately invalidated
- Each secret has a creation timestamp, optional expiry, and optional label for auditing
Token Signing & Key Management
All JWTs (access tokens and ID tokens) are signed using RS256 (RSA with SHA-256). Orion supports three key provider backends:
EnvironmentVariable
RSA key provided as a Base64 environment variable. Simplest option for single-server deployments.
Database
RSA key stored encrypted in PostgreSQL using an AES-256 Key Encryption Key (KEK). Supports key rotation.
AzureKeyVault
RSA key managed by Azure Key Vault. HSM-backed, supports automatic rotation, best for cloud deployments.
The JWKS endpoint (/oauth/{org}/.well-known/jwks.json)
publishes the public key(s) so relying parties can validate tokens without calling Orion.
Redirect URI Validation
Redirect URI validation prevents open-redirect attacks during the OAuth flow.
- Exact match: The
redirect_uriin the authorization request must exactly match one of the registered URIs for the application. - Wildcard domains: The
ORION_ALLOWED_REDIRECT_DOMAINSenvironment variable allows server-wide wildcard patterns (e.g.*.example.com). - No query strings: Redirect URIs must not contain query parameters in the registration.
- HTTPS required: Production redirect URIs must use HTTPS.
http://localhostis allowed for development.
Sovereign Signing
Sovereign Signing provides the highest level of token security by keeping JWT signing keys on external servers completely disconnected from Orion's HTTP traffic. Even with full database and server compromise, an attacker cannot forge tokens.
- Private key isolation: The Orion server never possesses signing key material. Tokens are signed out-of-band by external agents.
- Complete trust separation: Pool-specific JWKS endpoints serve only agent keys — server signing keys are never mixed in.
- Cert chain validation: The SDK validates X.509 cert chains in JWKS against a trusted root held on an HSM. A compromised server cannot inject rogue keys without HSM access.
- Thumbprint pinning: SHA-256 thumbprints of trusted key material prevent JWKS poisoning even without PKI infrastructure.
- Embedded key mode: For air-gapped environments, the SDK can be configured with PEM public keys directly — no JWKS fetch, zero server trust.
- Payload integrity: The server validates that the signed JWT payload is byte-identical to the unsigned payload it sent to the agent.
- Agent challenges: Agents can issue interactive challenges to users before signing, enabling additional policy enforcement.
See the SDK Integration page for validation mode configuration.
Device Identity & TPM Attestation
Device Identity replaces static API keys with X.509 certificate-based authentication. Each organisation has its own CA; device certificates are issued via a one-time enrollment code.
- Per-org Certificate Authority: CA private key encrypted at rest (AES-256-GCM under
ORION_CA_KEK), separate from the OAuth signing KEK and the sovereign signing trust root. - Signed assertions: Devices authenticate via a short-lived JWT (
private_key_jwtstyle) with the cert chain inx5c. Assertions carryjtifor replay protection and a tight expiry (default 120s). - TPM attestation: Configurable at org/pool/enrollment level. When required, the device must prove (via
MakeCredential/ActivateCredential/Certify) that its key is generated in and non-exportable from a genuine TPM. The EK certificate must chain to a trusted vendor root. - Instant revocation: Every assertion is validated against the database revocation denylist. No CRL/OCSP needed — Orion is the sole relying party.
- PKI separation: The device CA is for transport auth only. It is never used or trusted for sovereign token signing, which has its own external trust root.
See the Device Identity Guide for step-by-step setup and TPM attestation details.