Skip to main content

How it works

Ave’s E2EE model gives each (app, identity) pair a stable, isolated encryption context. The server stores an encrypted form of your app key, protected by the user’s master key during the first authorization. From then on, Ave delivers the key back to you on the post-authorization redirect via URL fragment. At consent time, the Ave UI decrypts that ciphertext in the browser using the user’s master key, then places the plaintext app key in the fragment. The token and authorization-code responses do not carry the decrypted secret. When a passkey supports PRF, Ave uses its output in the browser to encrypt and unlock the user’s master key. The PRF output is omitted from credentials sent to the API for registration, sign-in, and key unlocking. Only the encrypted master key is stored on the server. Saved browser master keys are associated with the account’s authenticated identities. Sign-in prefers the key unlocked by the verified passkey; a key from another account cannot substitute for it. Previously saved keys without an account association are reused only after they successfully decrypt an existing key for the current identity. Unmatched keys remain available for recovery. Passkey and recovery-code responses identify the account that owns the recovered key; Ave checks that association before saving it. Device approval applies the session returned with the transferred key. When persistent browser storage is unavailable, an unlocked key remains available for the current page session. For multi-user asymmetric encryption, enable e2ee:asymmetric on your app and use per-user app keypairs with the lookup API. The old identity wrapped OAuth payload flow (wrapped_key) is removed.

Key lifecycle

1

First authorization (key provisioning)

When a user authorizes your E2EE-capable app for the first time, the app generates key material client-side and encrypts it with the user’s passkey. The encrypted key is sent along with the authorization request.
2

Grant storage

Ave stores the encrypted key context in the user’s authorization record. The server never holds the plaintext.
3

Key handoff via URL fragment

After the user consents, the Ave authorization UI reads the server-stored encrypted key and decrypts it on the client side using the user’s master key. It then passes the plaintext app key to your callback as a URL fragment (#app_key=...). The server value is never sent — the fragment contains the already-decrypted key. Parse it from the fragment before or alongside your authorization code exchange.
4

Key import

Your app normalizes the base64 key payload (URL fragments can turn + into a space), decodes it, and imports it into the Web Crypto API.
5

Encrypt and decrypt data

Use AES-GCM with a unique IV for every encryption operation.
6

Identity switch handling

When the user switches identities, transition the encryption context. Different identities have different keys.Key storage pattern: app:{appId}:identity:{identityId}:dataNever merge or share encrypted datasets across identities.

Fragment hygiene

The app key arrives as a URL fragment (#app_key=...). Browsers silently replace + with a space in fragment parameters, which breaks base64 decoding.
After parsing the key, remove the fragment from the browser’s history to prevent it from appearing in logs or being shared via the back button.

Failure handling

Block the action and prompt the user to re-authorize your app. Do not silently degrade to unencrypted storage.
Treat this as a key-context mismatch. Do not overwrite existing ciphertext — you could destroy data. Prompt re-authentication and re-grant.
Fail closed. Request user re-authentication rather than attempting to recover from a potentially tampered key payload.
Last modified on September 5, 2026