Applogin — einheitlicher Login
Fügen Sie Ihrer Anwendung mit einem Skript Google- und E-Mail/Passwort-Login hinzu. Die gesamte Authentifizierung — Anmeldung, Registrierung, E-Mail-Bestätigung, Passwort-Reset, Google — findet in einem geschützten iframe auf applogin.one statt. Ihre Seite sieht das Passwort des Nutzers nie und prüft nichts — Sie erhalten nur ein fertiges app-gebundenes Token.
- Rendert das Anmelde-/Registrierungsformular (im eigenen iframe) — Sie bauen keins.
- Nimmt das Passwort entgegen, prüft die Zugangsdaten, sendet und prüft E-Mail-Codes — Sie verifizieren nichts.
- Führt ein Nutzerkonto pro E-Mail (Google und Passwort gehören zum selben Konto).
- Hält eine app-übergreifende Sitzung und übernimmt den Login zwischen Ihren Apps automatisch.
So funktioniert es
Applogin ist ein Authentifizierungsanbieter (wie Auth0/Clerk), aber das Login-Formular wird in einem Frame von unserer Domain ausgeliefert. Ihre App öffnet diesen Frame (als Modal) über das SDK und erhält das Ergebnis per postMessage. Das Token ist ein JWT, signiert mit dem Secret Ihrer Anwendung (aud=app_id) — in jeder anderen Anwendung ist es nutzlos.
| Begriff | Bedeutung |
|---|---|
| Anwendung (App) | Eine Entität auf der Plattform. Hat eine öffentliche app_id, ein jwt_secret (Token-Prüfung im Backend) und die Listen allowed_origins / redirect_uris. |
| End User | Ein globales Konto (eins pro E-Mail) für alle Plattform-Anwendungen. Google und Passwort verweisen auf dasselbe Konto. |
| App-Token | JWT (HS256, aud=app_id), signiert mit dem jwt_secret Ihrer App. Dahinter steht eine widerrufbare Sitzung. |
| SSO-Sitzung | Globale Sitzung im HttpOnly+Partitioned-Cookie al_sso auf applogin.one. Geteilt innerhalb einer Top-Level-Site. |
Schnellstart
Binden Sie zwei Skripte ein und mounten Sie das Widget — es versucht still SSO, zeigt einen „Anmelden“-Button, öffnet das gehostete Formular im Frame und liefert den Nutzer zurück.
<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>
Das war's. Formular, Registrierung, E-Mail-Codes, Google und Passwort-Reset übernimmt Applogin. Einzige Voraussetzung: eine app_id registrieren und die allowed_origins eintragen (siehe Anwendung erstellen).
?v=1 in den Skript-URLs verhindert, dass der Browser nach Updates eine veraltete SDK-Version aus dem Cache liefert.Das ApploginUI-Widget empfohlen
Ein fertiges „Schloss“ für Ihre App: solange der Nutzer abgemeldet ist, zeigt es einen Bildschirm mit „Anmelden“-Button; ein Klick öffnet das gehostete Formular im Modal; nach der Anmeldung ruft es onAuth(user) auf und entfernt den Bildschirm.
| Methode | Beschreibung |
|---|---|
ApploginUI.mount({ appId, onAuth, onLogout, title? }) | Mounten. Versucht stilles SSO; wenn abgemeldet, wird der „Anmelden“-Screen gezeigt. |
ApploginUI.logout() | Abmelden (Sitzung widerrufen, wieder der Landing-Screen). |
ApploginUI.getUser() | Der aktuelle Nutzer oder null. |
Profil (Avatar, Name, E-Mail) und Abmelde-Button rendern Sie selbst aus onAuth(user) — das ist Ihre UI. Die Nutzerdaten kommen fertig an.
SDK-Methoden (applogin.js) Low-Level
Wenn Sie statt des Widgets Ihre eigene UX möchten, nutzen Sie das SDK direkt. Zuerst Applogin.init({ appId }). Das Token liegt im localStorage unter al_token_<appId>.
| Methode | Beschreibung | Rückgabe |
|---|---|---|
init({ appId }) | Initialisierung. | — |
getSession() | Stilles SSO: Sitzung übernehmen, wenn der Nutzer in einer anderen App derselben Site angemeldet ist. | { authenticated, token, user } |
openLogin() | Das Modal mit dem gehosteten Login-Formular öffnen (iframe auf applogin.one). | { token, user, lang } oder null |
verify() | Das aktuelle Token prüfen. | { valid, user } |
logout() | Abmelden (Sitzung widerrufen, Token löschen). | — |
getToken() | Das aktuelle 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)
Beim Anmelden setzt Applogin das Cookie al_sso mit dem Attribut Partitioned. Der Partitionsschlüssel ist die Top-Level-Site (die äußerste). Daher:
- Mehrere Ihrer Apps unter einer Site (z. B. eingebettet in
appdock.pro) teilen die Sitzung →getSession()in der zweiten App übernimmt den Login ohne Formular. - Dieselbe App als eigene Site geöffnet (anderes Top-Level) ist eine andere Partition → der Nutzer meldet sich erneut an.
const s = await Applogin.getSession(); // ← {authenticated:true,…} if a session exists in this partition
if (s.authenticated) showApp(s.user);
allowed_origins einer App sowohl ihre eigene Domain als auch die Wrapper-Domain stehen (z. B. appdock.pro).allowed_origins abgesichert (eine fremde Site bekommt nie ein Token).Sprachen
Das gehostete Login-Formular spricht 10 Sprachen: English, Deutsch, Français, Español, Italiano, Português, 日本語, 한국어, 中文, Русский. Standardmäßig öffnet es sich in der Browsersprache des Nutzers (Fallback Englisch); die Sprache lässt sich direkt im Formular wechseln — das Flaggenmenü unten.
- Sprache erzwingen. Übergeben Sie
langan Widget oder SDK:ApploginUI.mount({ appId, lang: "de" })oderApplogin.init({ appId, lang: "de" })— das Formular öffnet in dieser Sprache. Ohne die Option sendet das SDK automatisch die Browsersprache. - Die Wahl zurücklesen. Der Nutzer kann die Sprache im Formular wechseln. Das Ergebnis von
Applogin.openLogin()enthältlang— die Sprache des Formulars beim Anmelden — damit Ihre Seite folgen kann. Das Widget speichert sie zudem (localStorageal_lang), das nächste Formular öffnet darin. - E-Mails folgen dem Formular. Bestätigungs- und Reset-E-Mails werden in der Formularsprache gesendet.
Intern akzeptiert die Formular-URL ?lang=xx (Zweibuchstaben-Code aus der Liste oben) — das SDK übergibt ihn für Sie.
Live-Beispiel: AppDock
appdock.pro ist ein „Dock“-Launcher: eine Seite, die mehrere Anwendungen in iframes öffnet. Die Anwendungen leben auf eigenen Domains:
| Anwendung | Domain | app_id |
|---|---|---|
| Email Writer | emailwriter.online | app_emailwriter |
| Audio Recorder | audiorecorder.info | app_recorder |
Melden Sie sich im Dock beim Email Writer an und öffnen Sie dann den Audio Recorder (ebenfalls im Dock) — die Anmeldung wird automatisch übernommen: Beide laufen unter derselben Top-Level-Site appdock.pro und teilen eine SSO-Partition.
1. Der 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. Eine Anwendung (z. B. 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-Registrierung für dieses Szenario
Jede Anwendung listet in allowed_origins ihre eigene Domain + die Dock-Domain (frame-ancestors sieht die gesamte Vorfahrenkette des verschachtelten Frames):
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"]
ApploginUI.mount.Token-Prüfung in Ihrem Backend
Ihr Frontend legt Applogin.getToken() in den Authorization-Header seiner Requests. Im Backend gibt es zwei Prüfwege.
1. Über den Plattform-Endpunkt berücksichtigt Widerruf
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. Lokal (HS256 mit Ihrem jwt_secret) ohne Netz
// 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")
/v1/session/verify.JWT-Struktur
{
"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)
Wenn eine Anwendung eine webhook_url setzt, sendet die Plattform bei jedem erfolgreichen Google-Login einen signierten POST mit der verifizierten Identität — für serverseitige Synchronisierung zusätzlich zum Token.
| Header | Wert |
|---|---|
X-Applogin-Timestamp | Unix-ms |
X-Applogin-Signature | sha256=<hex> von 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();
Anwendung erstellen
Anwendungen werden im geschlossenen Dashboard unter applogin.one/dashboard erstellt (Anmeldung über Applogin selbst). Sie geben an:
| Feld | Wozu |
|---|---|
name | Wird im Login-Formular angezeigt („Anmelden · <name>“). |
allowed_origins | Origins, die das Formular einbetten und Tokens erhalten dürfen. App-Domain + Wrapper-Domain (z. B. das Dock) angeben. |
redirect_uris | Für den Google-Login: https://applogin.one/auth-callback.html. |
webhook_url | (optional) wohin der Login-Webhook gesendet wird. |
Sie erhalten: app_id (öffentlich), jwt_secret (Token-Prüfung im Backend), client_secret, webhook_signing_secret.
REST-API — Referenz
Basis: https://applogin.one/api. Unten steht, was ein Builder wirklich braucht. Die E-Mail/Passwort- und Google-Endpunkte ruft das gehostete Formular selbst auf — Sie nie.
Für den Builder
App-Token im Backend prüfen (mit Widerruf). { app_id, token } → { valid, user }.
Öffentliche App-Daten (name, allowed_origins). Nutzt die gehostete Login-Seite.
Intern (ruft das gehostete Formular/SDK auf, nicht der Builder)
| Endpunkt | Rolle |
|---|---|
POST /v1/email/register · verify · resend · login · reset/request · reset/confirm · password/change | E-Mail/Passwort — vom gehosteten /login-Formular aufgerufen. |
POST /v1/auth/start, GET /oauth/google/callback, POST /v1/auth/exchange | Google OAuth (innerhalb des gehosteten Formulars). |
POST /v1/session/sso | Stilles SSO (ruft /session aus einem versteckten iframe auf). |
POST /v1/session/establish | Setzt das SSO-Cookie in der richtigen Partition (nach Google). |
POST /v1/session/logout | Sitzungswiderruf (über SDK logout()). |
Fehler
| HTTP | Wann |
|---|---|
| 400 | Ungültige Eingabe (kurzes Passwort, ungültiger/abgelaufener Code, „Email already registered“). |
| 403 | „Invalid credentials“, Zugriff verweigert, „Too many attempts“ (Rate-Limit). |
| 404 | Unbekannte Anwendung/Route. |
{"error":"Invalid or expired code","message":"Invalid or expired code"}
Sicherheit
- Das Passwort ist isoliert. Eingabefelder existieren nur im applogin.one-iframe; das JS der einbettenden Seite kommt nicht daran. Ein Builder kann das Passwort nicht „mitlesen“.
- App-gebundene Tokens. Das JWT ist mit dem App-Secret signiert und trägt
aud=app_id— das Token einer App ist in einer anderen ungültig. - Token-Zustellung nur an eigene Origins. Das Formular sendet das Token per
postMessagenur an eine Origin aus denallowed_origins; die Login-Seite selbst wird mitContent-Security-Policy: frame-ancestors <allowed_origins>ausgeliefert (Anti-Clickjacking). - Die globale Sitzung ist HttpOnly. Das Cookie
al_ssoist für JS unerreichbar; der Builder hält immer nur ein App-Token. - Anti-CSRF beim SSO.
/v1/session/ssogibt ein Token nur fürOrigin ∈ allowed_originsaus — eine fremde Site mit dem Cookie des Nutzers bekommt nichts. - Anti-Bruteforce. Rate-Limits auf Login/Reset/Verify (pro E-Mail und pro IP).
- Passwörter werden gehasht (PBKDF2); Codes werden gehasht, TTL 10 Minuten, Versuchslimit; überall HTTPS; Google-Tokens werden nie gespeichert. Google-Login mit PKCE (S256) + state + nonce.
LLM-Spickzettel
Modell: Die gesamte Authentifizierung findet in einem iframe auf applogin.one statt. Der Builder rendert KEIN Formular, sendet KEINE Passwörter, prüft KEINE Codes. Der Builder bindet SDK + Widget ein und erhält ein 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: Der Login setzt das Cookie al_sso (Partitioned, pro Top-Level-Site). Apps unter einer Site (z. B. iframes eines Docks wie appdock.pro) teilen die Sitzung; eine eigene Domain → neue Anmeldung. In den allowed_origins einer App: ihre Domain + die Wrapper-Domain.
Das Token ist app-gebunden: iss=applogin, aud=app_id, sub=User-ID, signiert mit dem jwt_secret der App.
Applogin · einheitlicher Login · Dashboard · Live-Beispiel: AppDock