Security
Credential protection, token security, and security recommendations for integrators.
Credential Storage
| Credential | Nature | Storage Recommendation |
|---|---|---|
client_id | Public identifier | Can be used within the integrator application |
client_secret | Long-term secret | Store securely; avoid leaking via source code / app package / frontend code / logs |
code_verifier | One-time | Used within the authorization flow; discard after use |
access_token | Short-term credential (1 hour) | Held only by the caller; not recommended to propagate across multiple endpoints |
refresh_token | Long-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:
- Generate a new
state(≥ 32 bytes random string) before each authorization - Bind it together with the PKCE
code_verifierto the current session - When the callback returns, validate that
statematches the local value before entering the token exchange flow
Designated Space Mode Security Notes
| Risk | Handling |
|---|---|
space_id tampered with in the authorization URL by a man-in-the-middle | The 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 Space | The 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 authorization | The server validates whether the member exists; if not, returns access_denied and does not auto-create the member |