Applications receive data.
Never tokens.
A zero-trust credential architecture where OAuth tokens never leave the server. Applications request actions, not credentials. The vault fetches the token, uses it for one HTTP call, and discards it. The caller receives only the result.
This isn't a configuration choice. It's an architectural constraint. Tokens are physically excluded from API responses, browser memory, log statements, and workflow outputs.
Traditional vaults solve storage. They fail at usage.
HashiCorp Vault, AWS Secrets Manager, and Azure Key Vault encrypt secrets at rest. Then they return those secrets to the calling application. The token lands in application code, browser memory, and log files. Every exposure point becomes a compliance violation.
XSS vulnerability
Token in JavaScript memory. A single XSS exploit steals it. The attacker now has a valid OAuth token for every system the user connected. Traditional PAM can't prevent this — the token was designed to be returned.
Logging leaks
console.log(response) permanently exposes the token in plaintext. It happens on every team. Once it's in the logs, it's in your SIEM, your log aggregator, and your compliance violation report.
Developer misuse
Token can be extracted and used outside the authorized application. Stored in localStorage. Passed to a test script. Shared with a colleague. The vault did its job — the application undid it.
Compliance exposure
Token exposure triggers SOC 2, GDPR, and HIPAA violations. Not because the vault was breached — because the vault returned the secret to the caller. The architecture violates data minimization by design.
The pattern: App fetches token → Token in app code → App uses token. Our pattern: App requests action → Token used internally → App receives data. The token never crosses the trust boundary.
The ironclad trust boundary
Three zones. Tokens exist in exactly one of them. The boundary between zones is enforced architecturally — not by configuration, not by policy, but by the fact that the runtime physically cannot serialize a token into a response.
Browser, plugins, agents
No credentials present. Ever. Agents operate here. They can request actions through MCP tool calls, but they never see, hold, or transmit tokens. XSS cannot steal what is not in the browser.
BFF layer
Validates sessions and routes authorized requests. Extracts user ARN and agent ARN. Credentials are not accessible — this layer handles identity, not secrets. The PDP authorizes before any token is even fetched.
Orchestration Service + Vault
Tokens decrypted in-memory, used for a single HTTP call, then discarded. Never serialized to responses. Never logged. Never stored beyond the request lifetime. The API response schema mathematically excludes tokens — developers cannot accidentally expose them.
Requests action
via MCP tool call
Authorizes action
Token not yet fetched
Decrypts token
Single HTTP call
Receives request
with user's Bearer token
Receives data
Token discarded
The Delegation Keycard: agents without credential sharing
When an AI agent needs to search Jira on behalf of Alice, it doesn't get Alice's OAuth token. It gets a Delegation ID — a restricted keycard that proves Alice consented and the PDP authorized. The actual token stays locked in the vault.
The actual OAuth token. FIPS 140-2 encrypted. Stored in the vault's enc_blob column. Permanently server-side. Used only inside the Orchestration Service for a single HTTP call, then discarded from memory. The agent never sees it. The BFF never sees it. The browser never sees it.
A Delegation ID. A restricted, digital keycard. Proves Alice consented to this agent using this tool. Verified by the four-layer delegation model — capability ceiling, delegatable scope, user consent, and data-level authorization. The keycard opens one door at a time. It can never become the master key.
The interaction loop
Initiates tool call (e.g., Jira Search) with delegation ID
Validates delegation, checks capability list, evaluates ABAC scope
Decrypts Alice's token in-memory. Single HTTP call to Jira. Token discarded.
Jira issues returned. Actions attributed to Alice, not a bot account. Token never exposed.
A fail-closed, rigorously validated OAuth lifecycle
Every step in the OAuth flow is validated, time-bounded, and cryptographically verified. If any step fails, the entire flow fails closed — no partial states, no stale tokens, no silent fallbacks.
PKCE + ephemeral state
PKCE code verifier generated. Ephemeral Redis session state with strict 5-minute TTL. State parameter bound to user ARN and system key. After 5 minutes, the flow is dead — no stale authorization codes.
State consumption + nonce
State parameter consumed (single-use, CSRF prevention). Nonce verified for postMessage flows. One-time use enforced — a replayed callback is rejected. The authorization code is exchanged for tokens server-side only.
Canonical ARN binding
Strict canonical ARN validation. unique_id and principal_arn parsed from JWT. Absolute multi-tenant isolation — Alice's Jira token in Tenant A is cryptographically isolated from Alice's token in Tenant B.
FIPS 140-2 AEAD
AES-256-GCM encryption. Sealed inside enc_blob column in PostgreSQL. Config-driven metadata extracted (cloud_id, scopes, org_id). Per-tenant key derivation. The token is now locked — it will only emerge server-side, for one HTTP call, then be discarded.
Credential routing defaults to user identity
When a workflow or MCP tool needs credentials, the CredentialService hierarchy checks the user's OAuth token first. System credentials and API keys are fallbacks — and the fallback can be explicitly disabled. The system defaults to failure, not to a shared service account.
Workflow uses the delegating user's OAuth token. Actions attributed to the end user, not a system account. The recommended pattern for agent tool calls.
A physical gate preventing insecure, silent credential downgrades. If the user hasn't connected their OAuth, the action fails — it doesn't silently fall back to a shared service account.
Maintenance-free delegation: the auto-refresh engine
Users connect once. The vault handles everything after that — proactive token refresh, retry on network failure, and clean re-authentication when refresh tokens expire. Zero maintenance for end users. Zero latency for workflow execution.
Token is valid. Background worker monitors expiration via FIPS-encrypted reads. Proactive refresh before expiry — the user never encounters an expired token during a workflow.
Temporary failure reaching the provider's token endpoint. The service intelligently batches and retries without dropping the connection. The user's status stays active until retry limits are exhausted.
Hard refresh failure — the provider revoked the refresh token or the user changed their password. System cleanly transitions to prompt the user for reconnection, failing securely.
Refresh execution per batched token (network-bound)
End-user latency for workflow execution
Background refresh cycle — credentials expiring within 1 hour are proactively renewed
How the Zero-Trust Vault compares
| Security Dimension | Traditional PAM (HashiCorp, AWS, Azure) | EmpowerNow Zero-Trust Vault |
|---|---|---|
| Token exposure to applications | Returned in API response | Never — server-side only |
| XSS vulnerability | High — token in JavaScript | Zero — token not in browser |
| Developer misuse | Possible — token extractable | Impossible — not accessible |
| Token persistence risk | Can be stored/cached | Cannot be stored — discarded after use |
| Logging leaks | console.log() exposes token | Schema excludes tokens — cannot be logged |
| Compliance (SOC 2 / GDPR / HIPAA) | Exposure = violation | Zero exposure — compliant by architecture |
| Audit trail | Partial — fetch logged, usage not | Complete — every action logged with signed receipt |
What changes for your organization
XSS can't steal a token that isn't in the browser. Developers can't log a token that isn't in the response. The architecture prevents the entire class of credential exposure attacks — not by catching them, but by making them impossible.
SOC 2, GDPR, and HIPAA don't ask "did you encrypt the token at rest?" They ask "can the token be exposed?" The answer is architecturally no. Data minimization isn't a policy — it's enforced by the runtime.
Every agent action is attributed to the delegating user. When the agent reads Alice's Jira issues, Jira sees Alice — not a shared service account. Audit trails are clean. Permissions are scoped. The four-layer delegation model governs every step.
Connect once. The auto-refresh engine keeps tokens valid indefinitely. Users never see expired-token errors during workflows. When a refresh token is revoked, the system cleanly prompts for reconnection — no silent failures, no stale data.
Three integration patterns
The vault serves workflows, MCP tools, and system-to-system integrations. The same credential security applies everywhere — but the routing logic adapts to the caller.
Workflow with delegated credential
Set use_delegated_credential: true in YAML connector config. The Connector & Tool Factory handles the rest — credential resolution, header injection, URL template override with cloud_id. The workflow author never touches tokens.
MCP tool via mini-workflow
MCP tools execute mini-workflows with delegated credentials. The agent initiates the tool call, the ARIA MCP Gateway routes through the PDP, and the workflow engine uses the vault. The agent handles data — never tokens.
Service accounts (traditional)
For back-end integrations that don't represent a user context — batch jobs, sync pipelines, infrastructure operations. Traditional credential storage with per-connector isolation. The PDP still authorizes every action.
Technical deep-dive OAuth Vault internals: FIPS storage, request transformation, multi-tenant isolation, and workflow output constraints
Encrypted Storage (DbVaultStrategyOAuthExtension)
Tokens encrypted with AES-256-GCM (FIPS 140-2 AEAD) and stored in PostgreSQL third_party_credentials table as an enc_blob field. Each tenant has its own key derivation — multi-tenant isolation enforced at the encryption layer, not just the query layer. Metadata stored separately: cloud_id, scopes, system_key, user_arn, status, expires_at. Config-driven metadata extraction per provider.
Request Transformation (CommandExecutor)
When use_delegated_credential: true, the CommandExecutor: (1) resolves the user's OAuth credential via the CredentialService hierarchy, (2) overrides base_url with oauth_base_url_template (injecting cloud_id for tenant-specific API endpoints), (3) builds the Authorization: Bearer header, (4) masks the token in all log statements. The token is converted to an internal HTTP header and immediately masked — it never appears in any serializable output.
Workflow Output Schema Constraints
Workflow output variables are explicitly defined in YAML. The runtime extracts only named output variables (e.g., {{var.jira_issues}}, {{var.total_issues}}). oauth_access_token is an execution context variable, not an output variable — the workflow physically cannot serialize a token into a response. This is the architectural enforcement: the API response schema mathematically excludes tokens.
Token Lifecycle Timing
Token fetch with cache hit: <5ms. DB read: <10ms. Decryption: <2ms. Total vault overhead per request: <15ms. Auto-refresh service runs every 5 minutes, queries credentials expiring within 1 hour, and refreshes via provider token endpoints. Refresh execution: ~500ms per batched token (network-bound). The caller never waits for a refresh.
Multi-Tenant Isolation
Five isolation layers: (1) Per-tenant encryption key derivation, (2) User ARN scoping on all vault queries, (3) Canonical ARN validation during OAuth callback, (4) System key partitioning, (5) PostgreSQL row-level constraints. A vault query for user_arn=auth:account:empowernow:alice in Tenant A can never return credentials from Tenant B — even with identical user identifiers.
Consumer-grade UX, enterprise-grade security
Users manage their own OAuth connections through a self-service interface. Connect Jira, Salesforce, or any supported system in three clicks. See active scopes. Grant agents permission to use connections. Disconnect anytime — the token is securely wiped from the FIPS vault.
OAuth flow completes in the browser. Token encrypted and stored server-side. User sees scopes and connection status.
Grant specific agents access to specific connections. The delegation model ensures agents only get the tools their role allows.
One click. Playbook-compliant confirmation dialog. DELETE /oauth/disconnect securely wipes the token from the FIPS vault.
Part of the control plane
The OAuth Vault is one layer in the EmpowerNow control plane. Authorization gates vault access. Connectors consume vault credentials. Agents use delegation to act on behalf of users.
Connector & Tool Factory
How connectors use the vault. use_delegated_credential: true in YAML.
AuthZEN Authorization
The PDP authorizes every action before the vault releases any token.
Hybrid ReBAC + ABAC →ARIA
How agents use delegation without credential sharing.
Runtime agent control →See the zero-trust vault in action
We'll walk through an agent tool call end to end — from delegation to vault retrieval to proof receipt — and show you why the token never leaves the server.