e2ee:* scope (or legacy supportsE2ee).
Encryption scopes
Configure standard OIDC scopes in the developer portal if needed. Requeste2ee:* scopes dynamically in your OAuth authorize URL — they are not configured in the portal.
Request one E2EE mode scope per authorization. Re-sign-in reuses existing per-app keys. Add
e2ee:reset only when you intend to rotate them.
Key handoff
During consent, Ave unlocks keys with the user’s master key and returns plaintext only in the redirect fragment (never in the JSON token response):
Your app should:
- Parse the fragment immediately after redirect
- Store the private key (asymmetric) or app key (symmetric) in local secure storage
- Store the public key (asymmetric) on the user record in your database
- Clear the fragment from browser history
mergeAppEncryptionFromUrl from @ave-id/sdk or completeOAuthCallback with AveSession.
Multi-user encryption
Withe2ee:asymmetric, encrypt data for another user without a handshake:
GET /api/encryption/app-lookup?client_id=…&handle=…→ their app public key (404 if they have never signed in to your app or have no key)encryptForAppHandle(SDK) → ciphertext + ephemeral sender key- Recipient decrypts with their locally stored app private key
client_id + public_key → user handle and identity id.
Storage model
- Keys are stable per (app, identity) pair and are not regenerated on re-sign-in
- Use
e2ee:resetfor intentional rotation or recovery when the app lost local key material - Server stores only master-key-wrapped copies on Ave ID
- Different identities get different key material
URL fragment parsing
URLSearchParams treats + as space. Normalize before base64 decode:
Crypto recommendations
- AES-GCM with random 12-byte IV per message (symmetric)
- ECDH P-256 + AES-GCM for asymmetric payloads (SDK helpers use this)
- Never reuse IVs with the same key
Failure modes
- Missing E2EE scope in authorize request when app expects encryption
- Master key not unlocked on device during consent
- Fragment left in browser history — strip after read
- Identity switch → different key context; do not mix ciphertext domains
