Drop AuthFrame into any web app with an iframe and a few lines of JavaScript. Verify tokens on your server using industry-standard RS256 JWTs.
Get AuthFrame running in under 5 minutes.
<!-- Step 1: Add the iframe -->
<iframe
id="authframe"
src="https://cdn.embedauth.com/embed/YOUR_CLIENT_ID.html?mode=signin"
width="420"
height="600"
frameborder="0"
style="border: none;"
></iframe>
<!-- Step 2: Listen for auth events -->
<script>
window.addEventListener('message', (event) => {
if (event.origin !== 'https://cdn.embedauth.com') return;
if (event.data.type === 'authframe:auth-success') {
const { token, user } = event.data.data;
// Store the JWT and redirect the user
sessionStorage.setItem('authframe_token', token);
window.location.href = '/dashboard';
}
});
</script>Verify tokens on your backend server.
AuthFrame issues RS256-signed JWT tokens. Verify them on your server using the public JWKS endpoint: https://embedauth.com/.well-known/jwks.json?clientId=YOUR_CLIENT_ID The JWT payload contains: sub — end user ID email — user's email address name — user's display name clientId — your app's client ID iat & exp — issued at and expiry timestamps
// Node.js verification using the "jose" package
import { createRemoteJWKSet, jwtVerify } from 'jose';
const JWKS = createRemoteJWKSet(
new URL('https://embedauth.com/.well-known/jwks.json?clientId=YOUR_CLIENT_ID')
);
async function verifyToken(token) {
const { payload } = await jwtVerify(token, JWKS, {
issuer: 'https://embedauth.com',
audience: 'YOUR_CLIENT_ID',
});
return payload;
}
// Express middleware example
app.use(async (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '');
if (!token) return res.status(401).json({ error: 'Unauthorized' });
try {
req.user = await verifyToken(token);
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
});Customize the embed behavior with URL parameters.
| Parameter | Values | Description |
|---|---|---|
| mode | signin · signup · forgot-password | Initial form to display |
| theme | (theme ID) | Apply a custom theme from your dashboard |
| redirect | (URL) | Redirect after auth (must be in allowed redirects) |
| compact | true · false | Compact mode for smaller embeds |
<!-- Sign in --> <iframe src="https://cdn.embedauth.com/embed/CLIENT_ID.html?mode=signin"></iframe> <!-- Sign up --> <iframe src="https://cdn.embedauth.com/embed/CLIENT_ID.html?mode=signup"></iframe> <!-- With a post-auth redirect --> <iframe src="https://cdn.embedauth.com/embed/CLIENT_ID.html?mode=signin&redirect=https://yoursite.com/app"></iframe>
Allow the AuthFrame origin in your CSP frame-src directive.
If your site sends a Content-Security-Policy header you must whitelist the AuthFrame origin in the frame-src (or default-src) directive — otherwise browsers will refuse to load the iframe. The embed is served from: https://embedauth.com https://cdn.embedauth.com Note: password-reset and magic-link emails open at the app host (https://embedauth.com) and redirect to the CDN (https://cdn.embedauth.com), so both origins must be present.
<!-- HTTP response header (recommended) -->
Content-Security-Policy: frame-src https://embedauth.com https://cdn.embedauth.com;
<!-- <meta> tag alternative -->
<meta http-equiv="Content-Security-Policy"
content="frame-src https://embedauth.com https://cdn.embedauth.com;">
# Nginx
add_header Content-Security-Policy "frame-src https://embedauth.com https://cdn.embedauth.com;" always;
# Node.js / Express
res.setHeader('Content-Security-Policy', 'frame-src https://embedauth.com https://cdn.embedauth.com;');All events emitted by the embedded auth forms.
The iframe communicates with your page via window.postMessage. Always verify event.origin before processing any message.
window.addEventListener('message', (event) => {
// Always verify the origin
if (event.origin !== 'https://cdn.embedauth.com') return;
switch (event.data.type) {
case 'authframe:auth-success':
// User signed in or signed up
// data: { token: string, user: { id, email, name } }
break;
case 'authframe:auth-error':
// Authentication failed
// data: { error: string, code: string }
break;
case 'authframe:mode-change':
// User switched between signin/signup/forgot-password
// data: { mode: string }
break;
case 'authframe:resize':
// Content height changed — useful for dynamic iframe sizing
// data: { height: number }
break;
case 'authframe:loaded':
// Iframe finished loading
// data: { clientId: string, mode: string }
break;
case 'authframe:signout':
// User signed out
// data: {}
break;
}
});Manage users and sessions programmatically via API keys.
Create API keys in the dashboard under API Keys. Use them to access AuthFrame's REST API for listing users, revoking sessions, and managing app configuration.
// List end users
const response = await fetch('https://embedauth.com/api/v1/users', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
});
const { users } = await response.json();
// Revoke all sessions for a user
await fetch(`https://embedauth.com/api/v1/users/${userId}/sessions`, {
method: 'DELETE',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});Create a free account and have your first embed running in minutes.