===================== Security Cheatsheet ===================== Quick, practical defaults for secure apps. Properties and Hooks -------------------- - Return `None` from a property hook to hide/deny: - GET → hide property in UI and API - PUT/POST → make property read-only/immutable - Store sensitive data in Attributes (buckets), not regular properties. Access Control -------------- - Prefer built-in trust types: `viewer`, `friend`, `partner`, `admin`, `mcp_client`. - Add custom trust types only when necessary; use pattern-based permissions. - Precedence: Explicit deny > explicit allow > trust type allow > default deny. - **Permission merging**: Individual overrides UNION with base patterns (fail-safe). - To restrict access, use `excluded_patterns`; base `patterns` cannot be narrowed. - Use `merge_base=False` only when explicit full override is needed. OAuth2 ------ - Always validate provider config; use the provider-agnostic factory. - Google: refresh tokens available; GitHub: no refresh tokens. - GitHub: only verified primary emails are accepted for actor linking. Unverified primary emails are skipped to prevent account-linking attacks via the GitHub ``/user/emails`` API. - Expect 401 at protected endpoints with a proper `WWW-Authenticate` header. - When multiple providers are configured, 401 redirects go to the factory login page (not directly to a provider) to let the user choose. Mobile OAuth2 ------------- - **PKCE recommended**: Use PKCE (``S256``) for mobile apps even when ``client_secret`` is available. Mobile apps are public clients and PKCE prevents authorization code interception. - **Custom URL scheme security**: Ensure only your app registers a given custom URL scheme (e.g., ``io.actingweb.myapp://callback``). On Android, use App Links (verified ``https://`` schemes) when possible for stronger guarantees. - **BFF pattern**: The backend holds the ``client_secret``; the mobile app never sees it. The authorization code is exchanged server-side via ``POST /oauth/spa/token``. - **Token storage**: Use platform-secure storage -- iOS Keychain Services and Android Keystore / EncryptedSharedPreferences. Never store tokens in plain SharedPreferences or UserDefaults. - **Redirect URI validation**: The ``redirect_uri`` is validated at the OAuth provider level. Register only the exact custom URL scheme in the provider's console; ActingWeb passes it through during code exchange. Custom Routes ------------- - For custom routes, use `auth.check_and_verify_auth()` instead of ad-hoc authentication. - Always validate the `actor_id` parameter matches the authenticated user. - Handle OAuth2 redirects properly (302 responses with Location header). Web UI ------ - Enable UI only when needed; it enforces OAuth2 when configured. - Never use relative links in templates; use `actor_root` and `actor_www`. Data Backend ------------ - Local dev: use DynamoDB Local with `AWS_DB_HOST` set. - Production: use IAM with least privilege and do not set `AWS_DB_HOST`.