Skip to main content
bun add @ave-id/sdk

What you implement

  1. Encrypt the secret for the invitee’s identity using encryptPayloadForHandle (or encryptPayloadForIdentity with their public key).
  2. Encode the result with encodeWrappedPayloadParam from @ave-id/sdk/client.
  3. Add it to the Ave sign-in / authorize URL as the query parameter wrapped_key (see below).
  4. Read the plaintext after redirect: fragment unwrapped_secret (base64url of the decrypted bytes), or unwrappedSecretB64 on the embed success payload — not decryptWrappedPayload in your own app.
Ave runs unwrap in the browser after the user consents and unlocks their key. Your server never receives the Ave master key; you only store the wrapped ciphertext until you send the user to Ave.

Where to put wrapped_key

Use buildAuthorizeUrl (or any link to https://aveid.net/signin / /authorize with the same query shape) and pass the encoded blob via extraParams:
import { buildAuthorizeUrl, getIdentityPublicKey } from "@ave-id/sdk";
import {
  encryptPayloadForHandle,
  encodeWrappedPayloadParam,
} from "@ave-id/sdk/client";

const wrapped = await encryptPayloadForHandle(
  new TextEncoder().encode(JSON.stringify({ workspaceKey: "…" })),
  { issuer: "https://aveid.net", handle: "alice" }
);

const wrappedKey = encodeWrappedPayloadParam(wrapped);

const url = buildAuthorizeUrl(
  {
    clientId: "YOUR_CLIENT_ID",
    redirectUri: "https://yourapp.com/callback",
  },
  {
    codeChallenge: challenge,
    codeChallengeMethod: "S256",
    extraParams: { wrapped_key: wrappedKey },
  }
);

window.location.href = url;
Query paramValue
wrapped_keyOutput of encodeWrappedPayloadParam(wrapped) — URL-safe base64 over JSON {"encryptedPayload","senderPublicKey"}. Max length 65536 characters.
Do not send the raw JSON in the query string; always use encodeWrappedPayloadParam.

What you get back

After successful authorization:
ChannelPlaintext
Full-page redirectURL fragment includes unwrapped_secret=<base64url> (same encoding style as encodeWrappedPayloadParam input: base64url over raw decrypted bytes). If the secret is too long for a safe fragment (~1800 chars), authorization fails unless embed=1.
embed=1postMessage success payload includes unwrappedSecretB64 (same bytes, base64url string).
If the app is E2EE-capable, app_key may appear in the same fragment; parse both keys from the hash.

API reference (keys only)

  • GET /api/signing/public-key/:handle — public key for wrapping.
  • GET /api/signing/keys/:identityId — envelope (session); used by Ave during unwrap, not for your invite encryption step.
Signing API

decryptWrappedPayload in the SDK

That helper is for local testing or non-Ave environments. Production flows should use wrapped_key → Ave → unwrapped_secret, not client-side unwrap on your origin without the master key.

Model (short)

Wrapped blobStored in your database until the user visits Ave with wrapped_key.
E2EE app_keySeparate mechanism — End-to-end encryption.

FedCM

wrapped_key is not supported on FedCM finalize yet; use the normal redirect flow.
Last modified on May 1, 2026