Applogin Dashboard

Applogin — unified sign-in

Add Google and email/password sign-in to your application with one script. All authentication — sign-in, sign-up, email verification, password reset, Google — happens inside a protected iframe on applogin.one. Your page never sees the user's password and never validates anything — you only receive a ready-made app-scoped token.

What the platform does for you
  • Renders the sign-in/sign-up form (in its own iframe) — you don't build one.
  • Accepts the password, checks credentials, sends and verifies email codes — you verify nothing.
  • Keeps one user account per email (Google and password map to the same account).
  • Maintains a cross-app session and silently picks the sign-in up between your apps.

How it works

Applogin is an authentication provider (like Auth0/Clerk), but the login form is served in a frame from our domain. Your app opens that frame (in a modal) through the SDK and receives the result via postMessage. The token is a JWT signed with your application's secret (aud=app_id), so it is useless in any other application.

Your application (e.g. emailwriter.online) │ applogin.js + applogin-ui.js (SDK / widget) │ opens a modal with an iframe: ▼ ┌──────────────────────────────────────────┐ │ iframe → https://applogin.one/login │ ← password is typed HERE │ (form: Google / email+password / reset) │ your JS never sees it └──────────────────────────────────────────┘ ▲ postMessage { token, user } (only to your origin) │ ▼ You receive an app token → verify it on your backend (/v1/session/verify)
ConceptWhat it is
Application (app)An entity on the platform. Has a public app_id, a jwt_secret (backend token verification) and the allowed_origins / redirect_uris lists.
End userA global account (one per email) shared by all platform applications. Google and password link to the same account.
App tokenJWT (HS256, aud=app_id) signed with your app's jwt_secret. Backed by a revocable session.
SSO sessionGlobal session in the HttpOnly+Partitioned cookie al_sso on applogin.one. Shared within one top-level site.

Quick start

Include two scripts and mount the widget — it silently tries SSO, shows a "Sign in" button, opens the hosted form in a frame and returns the user.

<script src="https://applogin.one/applogin.js?v=1"></script>
<script src="https://applogin.one/applogin-ui.js?v=1"></script>
<script>
  ApploginUI.mount({
    appId: "app_your_id",
    onAuth:   (user) => renderApp(user),  // signed in: { id, email, name, picture, email_verified }
    onLogout: ()     => showLanding()
  });
  // sign-out button:  ApploginUI.logout();
</script>

That's it. The form, registration, email codes, Google and password reset are all handled by Applogin. The only requirement is to register an app_id and list your allowed_origins (see Creating an application).

The ?v=1 version in the script URLs prevents the browser from serving a stale cached SDK after updates.

The ApploginUI widget recommended

A ready-made "lock" for your app: while signed out it shows a screen with a "Sign in" button; a click opens the hosted form in a modal; after sign-in it calls onAuth(user) and removes the screen.

MethodDescription
ApploginUI.mount({ appId, onAuth, onLogout, title? })Mount. Tries silent SSO; if signed out, renders the "Sign in" landing.
ApploginUI.logout()Sign out (revokes the session, shows the landing again).
ApploginUI.getUser()The current user or null.

You render the profile (avatar, name, email) and the sign-out button yourself from onAuth(user) — that is your UI. The user data arrives ready to use.

SDK methods (applogin.js) low level

If you want your own UX instead of the widget, use the SDK directly. Call Applogin.init({ appId }) first. The token is stored in localStorage under al_token_<appId>.

MethodDescriptionReturns
init({ appId })Initialization.
getSession()Silent SSO: pick up the session if the user signed in to another app of the same site.{ authenticated, token, user }
openLogin()Open the hosted login form modal (iframe on applogin.one).{ token, user, lang } or null
verify()Check the current token.{ valid, user }
logout()Sign out (revokes the session and clears the token).
getToken()The current app token.string | null
Applogin.init({ appId: "app_xxx" });

// on load — silently try SSO:
const s = await Applogin.getSession();
if (s.authenticated) showApp(s.user);
else {
  const r = await Applogin.openLogin();     // modal with the applogin.one form
  if (r) showApp(r.user);
}
// attach Applogin.getToken() to your backend requests

Single sign-on (SSO)

On sign-in Applogin sets the al_sso cookie with the Partitioned attribute. The partition key is the top-level site (the outermost one). Therefore:

const s = await Applogin.getSession();   // ← {authenticated:true,…} if a session exists in this partition
if (s.authenticated) showApp(s.user);
The allowed_origins requirement. The login frame checks the whole ancestor chain (frame-ancestors), so an app's allowed_origins must list both its own domain and the wrapper domain (e.g. appdock.pro).
Being honest about isolation. The "same site → SSO, other top-level → sign in again" split is enforced by the browser (cookie partitioning, CHIPS). In browsers without CHIPS the cookie may behave as shared — then auto-login also happens on the app's standalone page. It is not a hole: token issuance is still gated by allowed_origins (a foreign site never gets a token).

Languages

The hosted login form speaks 10 languages: English, Deutsch, Français, Español, Italiano, Português, 日本語, 한국어, 中文, Русский. By default it opens in the user's browser language (falling back to English), and the user can switch the language right in the form — the flag menu at the bottom.

Under the hood the form URL accepts ?lang=xx (a two-letter code from the list above) — the SDK passes it for you.

Live example: AppDock

appdock.pro is a "dock" launcher: one page that opens several applications in iframes. The applications live on their own domains:

ApplicationDomainapp_id
Email Writeremailwriter.onlineapp_emailwriter
Audio Recorderaudiorecorder.infoapp_recorder

Sign in to Email Writer inside the dock, then open Audio Recorder (also inside the dock) — the sign-in is picked up automatically: both run under the same top-level site appdock.pro, so they share one SSO partition.

1. The dock launcher (appdock.pro)

<button class="tile" data-src="https://emailwriter.online/">Email Writer</button>
<button class="tile" data-src="https://audiorecorder.info/">Audio Recorder</button>
<iframe id="frame" allow="microphone; clipboard-write"></iframe>
<script>
  document.querySelectorAll(".tile").forEach(t =>
    t.onclick = () => document.getElementById("frame").src = t.dataset.src);
</script>

2. An application (e.g. emailwriter.online)

<script src="https://applogin.one/applogin.js?v=1"></script>
<script src="https://applogin.one/applogin-ui.js?v=1"></script>
<script>
  ApploginUI.mount({
    appId: "app_emailwriter",
    title: "Email Writer — sign in",
    onAuth: (user) => {              // render the profile + the app
      header.textContent = user.name + " · " + user.email;
      app.hidden = false;
    },
    onLogout: () => { app.hidden = true; }
  });
</script>

3. App registration for this scenario

Each application lists its own domain + the dock domain in allowed_origins (frame-ancestors sees the nested frame's whole ancestor chain):

app_emailwriter → allowed_origins: ["https://emailwriter.online", "https://appdock.pro"]
app_recorder    → allowed_origins: ["https://audiorecorder.info", "https://appdock.pro"]
// redirect_uris (for Google): ["https://applogin.one/auth-callback.html"]
Resulting behaviour: inside the dock — one shared sign-in between Email Writer and Audio Recorder; each app opened standalone (its own domain as top-level) — a fresh sign-in. The apps contain no login form of their own — only ApploginUI.mount.

Verifying the token on your backend

Your frontend puts Applogin.getToken() in the Authorization header of its requests. On the backend there are two ways to verify it.

1. Via the platform endpoint revocation-aware

POST https://applogin.one/api/v1/session/verify
{ "app_id": "app_xxx", "token": "<JWT from Authorization>" }
// → { "valid": true, "user": { "id": 2, "email": "…", "email_verified": true, "name": "…", "picture": null } }
//   invalid/revoked (logout) → { "valid": false, "user": null }

2. Locally (HS256 with your jwt_secret) no network

// Node.js
const jwt = require("jsonwebtoken");
const claims = jwt.verify(token, process.env.APPLOGIN_JWT_SECRET, {
  algorithms: ["HS256"], audience: "app_xxx", issuer: "applogin"
});
// claims.sub — user id, claims.email, claims.email_verified

# Python
import jwt
claims = jwt.decode(token, APPLOGIN_JWT_SECRET, algorithms=["HS256"],
                    audience="app_xxx", issuer="applogin")
Local verification does not see an instant session revocation (logout). If you need instant revocation, use /v1/session/verify.

JWT structure

{
  "iss": "applogin",
  "aud": "app_xxx",          // your app_id
  "sub": "2",                // user id (as a string)
  "jti": "…",                // session id (for revocation)
  "email": "user@example.com",
  "email_verified": true,
  "name": "Jane", "picture": null,
  "iat": 1782194619, "exp": 1784786619   // ~30 days
}

Webhook (optional)

If an application sets a webhook_url, the platform sends it a signed POST with the verified identity on each successful Google sign-in — for server-side syncing in addition to the token.

HeaderValue
X-Applogin-Timestampunix-ms
X-Applogin-Signaturesha256=<hex> of timestamp + "." + rawBody
const exp = "sha256=" + crypto.createHmac("sha256", WEBHOOK_SIGNING_SECRET)
  .update(ts + "." + rawBody).digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(exp), Buffer.from(sig))) reject();

Creating an application

Applications are created in the closed dashboard at applogin.one/dashboard (sign in via Applogin itself). You provide:

FieldWhy
nameShown in the login form ("Sign in · <name>").
allowed_originsOrigins allowed to embed the form and receive tokens. List the app's domain + the wrapper domain (e.g. the dock).
redirect_urisFor Google sign-in: https://applogin.one/auth-callback.html.
webhook_url(optional) where to send the sign-in webhook.

You get back: app_id (public), jwt_secret (backend token verification), client_secret, webhook_signing_secret.

REST API — reference

Base: https://applogin.one/api. Below is what a builder actually needs. The email/password and Google-exchange endpoints are called by the hosted form itself — you never call them.

For the builder

POST/v1/session/verify

Verify an app token on your backend (revocation-aware). { app_id, token }{ valid, user }.

GET/v1/app/public

Public application data (name, allowed_origins). Used by the hosted login page.

Internal (called by the hosted form/SDK, not by the builder)

EndpointRole
POST /v1/email/register · verify · resend · login · reset/request · reset/confirm · password/changeemail/password — called from the hosted /login form.
POST /v1/auth/start, GET /oauth/google/callback, POST /v1/auth/exchangeGoogle OAuth (inside the hosted form).
POST /v1/session/ssoSilent SSO (called by /session from a hidden iframe).
POST /v1/session/establishSets the SSO cookie in the correct partition (after Google).
POST /v1/session/logoutSession revocation (via SDK logout()).

Errors

HTTPWhen
400Bad input (short password, invalid/expired code, "Email already registered").
403"Invalid credentials", access denied, "Too many attempts" (rate limit).
404Unknown application/route.
{"error":"Invalid or expired code","message":"Invalid or expired code"}

Security

LLM cheat sheet

Model: all authentication happens in an iframe on applogin.one. The builder does NOT render a form, does NOT send passwords, does NOT verify codes. The builder includes the SDK + widget and receives an app token.

// include
<script src=https://applogin.one/applogin.js?v=1></script>
<script src=https://applogin.one/applogin-ui.js?v=1></script>

// mount (a lock on the app)
ApploginUI.mount({ appId, onAuth:(user)=>..., onLogout:()=>... });
ApploginUI.logout();

// low level
Applogin.init({ appId });
await Applogin.getSession();   // {authenticated, token, user} — silent SSO
await Applogin.openLogin();    // {token, user, lang}|null — modal with the form
Applogin.getToken(); await Applogin.verify(); await Applogin.logout();

// backend: verify the token
POST https://applogin.one/api/v1/session/verify {app_id, token} -> {valid, user}
// or locally: jwt.verify(token, jwt_secret, {algorithms:["HS256"], audience:app_id, issuer:"applogin"})

SSO: signing in sets the al_sso cookie (Partitioned, per top-level site). Apps under one site (e.g. iframes of one dock like appdock.pro) share the session; a separate domain → sign in again. An app's allowed_origins = its domain + the wrapper domain.

The token is app-scoped: iss=applogin, aud=app_id, sub=user id, signed with the app's jwt_secret.

Applogin · unified sign-in · dashboard · live example: AppDock