Security

Credential protection, token security, and security recommendations for integrators.

Credential Storage

CredentialNatureStorage Recommendation
client_idPublic identifierCan be used within the integrator application
client_secretLong-term secretStore securely; avoid leaking via source code / app package / frontend code / logs
code_verifierOne-timeUsed within the authorization flow; discard after use
access_tokenShort-term credential (1 hour)Held only by the caller; not recommended to propagate across multiple endpoints
refresh_tokenLong-term credential (permanent)Store with the same level of security as client_secret
ℹ️

The table above only describes the security level of credentials. The specific storage location (application process memory / Keychain / self-hosted key management system, etc.) is determined by the integrator based on its own architecture.

WebView Token Security

  • One-time issuance — Each call to the Get Embedded View URL API returns a new token
  • Replayable — Can be used multiple times within the validity period defined by the server (multiple page refreshes and API calls within the WebView all use the same token); not bound to IP / UA (otherwise mobile devices would fail when switching networks)
  • Leakage risk — The token in the URL may appear in browser history, Referer headers, and application logs
  • Best practice — Request a new one each time you need it; do not cache the webview URL long-term
⚠️

Avoid writing the embedded page URL to persistent logs to prevent the token from being replayed after leakage.

State Parameter & CSRF Protection

To prevent CSRF, it is recommended to:

  1. Generate a new state (≥ 32 bytes random string) before each authorization
  2. Bind it together with the PKCE code_verifier to the current session
  3. When the callback returns, validate that state matches the local value before entering the token exchange flow

Designated Space Mode Security Notes

RiskHandling
space_id tampered with in the authorization URL by a man-in-the-middleThe server locks space_id into the session during the GET /openapi/v1/oauth/auth stage; the Consent page only holds the session_token and cannot modify the bound Space
A malicious party forges an authorization URL to inject members into any SpaceThe pre-add member API requires a valid Bearer Token, and the app must be authorized to operate the target Space; unauthorized apps cannot call it
A non-pre-added user attempts to enter a Space via OAuth authorizationThe server validates whether the member exists; if not, returns access_denied and does not auto-create the member