Token storage per provider
When you connect an integration, Wisteria has to store something to call the provider’s API on your behalf later. This page details what gets stored, how it’s protected, and how it’s revoked.
The general principle: store the minimum needed, encrypt it, never log it, support easy revocation.
Microsoft 365
What Wisteria stores:
- Your tenant ID — a public identifier, not a secret. Stored in plaintext in
company_integrations. - NO refresh token, NO access token — Microsoft’s admin-consent flow doesn’t issue tokens to Wisteria the way per-user OAuth would. Instead, Wisteria mints fresh access tokens on every API call using its own client credentials + your tenant ID.
What Wisteria stores on its own infrastructure (not per-tenant):
- Microsoft Application Client ID + Client Secret — Wisteria’s app credentials, stored in Vercel environment variables. Not per-customer.
To revoke at your end:
- Inside Wisteria: Settings → Integrations → Microsoft 365 → Disconnect. The tenant ID is removed.
- At Microsoft’s end:
admin.microsoft.com→ Enterprise Applications → Wisteria → Remove. Revokes the admin consent.
Google Workspace (Domain-Wide Delegation)
What Wisteria stores:
- Your domain — public identifier. Plaintext.
- The super-admin email you specified for impersonation — plaintext.
- NO refresh token, NO long-lived credentials — DWD mints tokens server-side using Wisteria’s service account private key + your authorised impersonation.
What Wisteria stores on its own infrastructure:
- Service account private key — in Vercel environment variables. Encrypted at rest by Vercel’s infrastructure. Not per-customer.
To revoke at your end:
- Inside Wisteria: Settings → Integrations → Google Workspace → Disconnect.
- At Google’s end:
admin.google.com→ Security → Domain-wide delegation → find Wisteria’s Client ID → Remove.
Lark / Feishu (Self-Built App)
What Wisteria stores per workspace:
- App ID — public identifier. Plaintext.
- App Secret — encrypted at rest with AES-256-GCM. The encryption key is stored in Vercel environment variables.
- Region —
larkorfeishu. Plaintext.
Storage location: company_integrations.encrypted_key column.
Why this is the only integration where Wisteria stores the secret itself: Lark / Feishu doesn’t expose a service-account or admin-consent pattern. The self-built app’s credentials ARE the only mechanism for API access, so they must be stored.
To revoke at your end:
- Inside Wisteria: Settings → Integrations → Lark / Feishu → Disconnect. The encrypted App Secret is deleted.
- At Lark / Feishu’s end: developer console → delete the app entirely. Even if Wisteria still held the credentials in a backup, the app would no longer authenticate.
Per-user Google Drive (OAuth)
What Wisteria stores per user:
- OAuth refresh token — encrypted at rest with AES-256-GCM. Used to mint short-lived access tokens on each scan.
- Token expiry timestamps — plaintext.
Storage location: company_integrations.encrypted_key (per user, not per workspace).
To revoke:
- Inside Wisteria: Settings → Integrations → Google Drive → Disconnect (the connecting user only).
- At Google’s end:
myaccount.google.com→ Security → Third-party apps with account access → revoke Wisteria.
Slack (Incoming Webhooks)
What Wisteria stores per workspace:
- The webhook URL — contains a secret token in the path. Stored encrypted at rest.
Storage location: company_notification_settings.slack_webhook_url.
The webhook URL is one-way (Wisteria → Slack). Wisteria can’t read your Slack messages with it; only post to a specific channel.
To revoke:
- Inside Wisteria: Settings → Notifications → Slack → Disconnect.
- At Slack’s end: Apps → Custom Integrations → Incoming Webhooks → delete the webhook.
Encryption key management
The AES-256-GCM keys used for application-level encryption live in Vercel environment variables. They are:
- Never committed to source control.
- Never logged.
- Rotated periodically. When a key is rotated, the old key remains valid for decryption of existing records; new records use the new key. Old records are re-encrypted in a background migration.
If you have a specific requirement to rotate keys on a faster cadence than Wisteria’s default, talk to us.
Token lifetimes
| Provider | Token type | Lifetime |
|---|---|---|
| Microsoft 365 | Access token (minted per-call) | 1 hour |
| Google Workspace | Access token (minted per-call) | 1 hour |
| Lark / Feishu | tenant_access_token (cached) | 2 hours |
| Per-user Google Drive | Access token (cached) | 1 hour; refresh token long-lived |
| Wisteria session JWT | Used for API calls | 1 hour |
Refresh tokens (for OAuth) can expire if not used for a long time — typically 6 months of inactivity. If a user’s refresh token expires, they’re prompted to re-connect when next scanned.
What happens on Wisteria-side breach
In the unlikely event Wisteria’s database is exposed:
- Application-encrypted tokens (Lark App Secret, Google OAuth refresh tokens) — useless without the AES-256-GCM key, which lives in a separate Vercel environment.
- Microsoft tenant IDs, Google domains — these are public identifiers. Knowing your tenant ID gives an attacker no API access without admin consent (which they don’t have).
- Resend webhook tokens — encrypted at rest. Useless without the key.
The defense-in-depth model means a database leak alone is not a token leak. Both layers (DB + env var) would have to be compromised.
What happens on Vercel-side breach
If Vercel’s environment is compromised but the database is not:
- Encryption keys — exposed. The attacker could decrypt the database tokens IF they also had the database.
- Microsoft client secret, Google service account key — exposed. The attacker could impersonate Wisteria against your tenant.
This is a more severe scenario. Vercel has its own SOC 2 attestation and infrastructure security; we depend on those plus our application-level controls.
Revoking everything at once
If you suspect a breach and want to revoke every integration immediately:
- Inside Wisteria: Settings → Integrations → disconnect each integration.
- At each provider’s end: remove the admin consent (Microsoft), revoke DWD (Google), delete the app (Lark), revoke OAuth (per-user Google).
- Optionally: deactivate all Wisteria sessions for your workspace from Settings → Security → Sign all sessions out.
Then re-connect when you’re ready.
Reporting a breach
If you suspect a token leak or any kind of unauthorised access — yours or Wisteria’s — email security@getwisteria.com immediately. We treat these as the highest-priority alerts and respond within hours.