- Iframe embedding —
X-Frame-Optionsand CSPframe-ancestorsto prevent clickjacking - Phishing domain attacks — how to lock your integration to the correct tenant using
clientId - Tenant impersonation — how
clientId+ backendOriginvalidation closes the multi-tenant attack surface - CSP for in-memory token protection — blocking the script-injection path that bypasses the in-memory storage defense
- Library limitations — an honest disclosure of what ailita-library cannot prevent
Iframe embedding protection
A login form embedded in an attacker-controlled<iframe> allows clickjacking attacks where the user believes they are interacting with the legitimate page but their clicks are captured by an invisible overlay on the attacker’s site. Both X-Frame-Options and CSP frame-ancestors prevent your login page from being embedded in third-party frames.
X-Frame-Options header
Set this response header on pages that renderLoginForm or any ailita-library auth component:
X-Frame-Options is widely supported but is superseded by the CSP frame-ancestors directive in modern browsers. If you set both, frame-ancestors takes precedence in supporting browsers. Set both for maximum compatibility.CSP frame-ancestors
Add aContent-Security-Policy header with a frame-ancestors directive. In Next.js, set this in next.config.ts:
Phishing domain protection
A phishing attack presents users with a look-alike domain (e.g.,app-mycompany.com vs app.mycompany.com) that hosts a copy of your login page. At the ailita-library integration layer, clientId is the canonical identifier that binds the login form to a specific tenant.
Hard-code clientId — never derive from the URL
Hard-code yourclientId as a constant and pass it directly to AilitaProvider — never read it from the URL, query parameters, or localStorage.
Tenant impersonation and the clientId + Origin model
ailita-library is a multi-tenant platform. The primary defense against tenant impersonation is the combination of an opaqueclientId (not a human-readable slug) and backend Origin header validation.
How clientId + Origin validation works:
The library calls GET /auth/discovery?clientId=pk_live_abc123. The backend looks up the tenant by clientId and checks the request’s HTTP Origin header against that tenant’s registered domain allowlist (e.g., ["https://app.mycompany.com"]). If the Origin is not in the allowlist, the backend responds with 403 — no tenant config is returned and no auth requests can proceed.
The discovery call sequence in AilitaProvider is:
Origin header automatically for cross-origin requests and JavaScript cannot override it. A script on app-phishing.com that hard-codes a valid clientId will still receive a 403 because Origin: https://app-phishing.com is not in your tenant’s allowlist. Postman and curl can forge Origin, but Cloudflare bot protection and rate limiting handle that layer.
The library does not send
window.location.origin in the request body — that would be spoofable by any script. The security guarantee comes from the HTTP Origin header, which browsers enforce at the network layer.CSP headers to protect the in-memory token
TheaccessToken is stored in memory and is not accessible via localStorage. However, a script injection that executes in the same browsing context before the library initializes can monkey-patch XMLHttpRequest or fetch to intercept requests and extract tokens from Authorization headers. A strict Content Security Policy prevents untrusted scripts from running.
For more context on the in-memory storage pattern and why XSS is still a threat despite it, see Token Security Model.
Recommended CSP
Next.js generates runtime inline scripts for hydration. You will need to use nonces or hashes for those scripts. See the Next.js CSP documentation for the nonce-based approach with Middleware.
Library limitations
ailita-library is a client-side React library. It cannot enforce the following properties — and does not claim to.| Protection | Why ailita-library cannot provide it |
|---|---|
| Prevent phishing of the host app | The library runs inside your app; if the user navigates to a phishing domain, the library is not loaded — the attacker’s page is |
| Prevent credential interception by malicious browser extensions | Extensions run with elevated privileges and can read page content regardless of CSP |
| Enforce HTTPS | SSL/TLS is a network layer concern — your web server or CDN must enforce HTTPS |
| Verify domain authenticity (DNSSEC, HSTS) | Infrastructure concern — configure HSTS headers and DNSSEC at the DNS/CDN layer |
| Prevent server-side credential stuffing | The library submits credentials to your backend; rate limiting and account lockout are backend concerns |
The most important protection against phishing is user education (recognizing the correct domain) combined with TOTP/hardware key 2FA. Even with a perfect client-side implementation, a user who types credentials into a phishing page has bypassed all library-level protections. The library provides correct integration patterns — not a substitute for 2FA.
Next steps
Token Security Model
How accessToken and ailita_rt are stored, the 401 refresh queue, and the security boundary table
Fingerprinting & Bot Detection
BehaviorData signals, VPN/incognito detection, and GDPR privacy requirements

