Applogin — connexion unifiée
Ajoutez la connexion Google et e-mail/mot de passe à votre application avec un seul script. Toute l'authentification — connexion, inscription, vérification d'e-mail, réinitialisation du mot de passe, Google — se déroule dans un iframe protégé sur applogin.one. Votre page ne voit jamais le mot de passe de l'utilisateur et ne vérifie rien — vous recevez uniquement un token limité à votre application.
- Affiche le formulaire de connexion/inscription (dans son propre iframe) — vous n'en construisez pas.
- Reçoit le mot de passe, vérifie les identifiants, envoie et vérifie les codes par e-mail — vous ne vérifiez rien.
- Maintient un compte unique par e-mail (Google et mot de passe pointent vers le même compte).
- Gère une session inter-applications et reprend silencieusement la connexion entre vos apps.
Fonctionnement
Applogin est un fournisseur d'authentification (comme Auth0/Clerk), mais le formulaire de connexion est servi dans un frame depuis notre domaine. Votre app ouvre ce frame (en modal) via le SDK et reçoit le résultat par postMessage. Le token est un JWT signé avec le secret de votre application (aud=app_id) — il est inutilisable dans toute autre application.
| Concept | Description |
|---|---|
| Application (app) | Une entité de la plateforme. Possède un app_id public, un jwt_secret (vérification du token côté backend) et les listes allowed_origins / redirect_uris. |
| Utilisateur final | Un compte global (un par e-mail) partagé par toutes les applications de la plateforme. Google et mot de passe pointent vers le même compte. |
| Token d'app | JWT (HS256, aud=app_id) signé avec le jwt_secret de votre app. Adossé à une session révocable. |
| Session SSO | Session globale dans le cookie HttpOnly+Partitioned al_sso sur applogin.one. Partagée au sein d'un même site de premier niveau. |
Démarrage rapide
Incluez deux scripts et montez le widget — il tente le SSO silencieux, affiche un bouton « Se connecter », ouvre le formulaire hébergé dans un frame et renvoie l'utilisateur.
<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>
C'est tout. Formulaire, inscription, codes par e-mail, Google et réinitialisation du mot de passe sont pris en charge par Applogin. La seule exigence : enregistrer un app_id et lister vos allowed_origins (voir Créer une application).
?v=1 dans les URL des scripts empêche le navigateur de servir un SDK obsolète depuis le cache après une mise à jour.Le widget ApploginUI recommandé
Un « verrou » prêt à l'emploi pour votre app : tant que l'utilisateur est déconnecté, il affiche un écran avec un bouton « Se connecter » ; un clic ouvre le formulaire hébergé en modal ; après la connexion, il appelle onAuth(user) et retire l'écran.
| Méthode | Description |
|---|---|
ApploginUI.mount({ appId, onAuth, onLogout, title? }) | Monter. Tente le SSO silencieux ; si déconnecté, affiche l'écran « Se connecter ». |
ApploginUI.logout() | Déconnexion (révoque la session, réaffiche l'écran). |
ApploginUI.getUser() | L'utilisateur courant ou null. |
Vous affichez vous-même le profil (avatar, nom, e-mail) et le bouton de déconnexion depuis onAuth(user) — c'est votre UI. Les données utilisateur arrivent prêtes à l'emploi.
Méthodes du SDK (applogin.js) bas niveau
Si vous voulez votre propre UX plutôt que le widget, utilisez le SDK directement. Appelez d'abord Applogin.init({ appId }). Le token est stocké dans localStorage sous al_token_<appId>.
| Méthode | Description | Renvoie |
|---|---|---|
init({ appId }) | Initialisation. | — |
getSession() | SSO silencieux : reprendre la session si l'utilisateur s'est connecté dans une autre app du même site. | { authenticated, token, user } |
openLogin() | Ouvrir le modal du formulaire hébergé (iframe sur applogin.one). | { token, user, lang } ou null |
verify() | Vérifier le token courant. | { valid, user } |
logout() | Déconnexion (révoque la session et efface le token). | — |
getToken() | Le token d'app courant. | 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
Authentification unique (SSO)
À la connexion, Applogin dépose le cookie al_sso avec l'attribut Partitioned. La clé de partition est le site de premier niveau (le plus externe). Par conséquent :
- Plusieurs de vos apps sous un même site (ex. intégrées dans
appdock.pro) partagent la session →getSession()dans la seconde app reprend la connexion sans formulaire. - La même app ouverte comme site séparé (autre premier niveau) est une autre partition → l'utilisateur se reconnecte.
const s = await Applogin.getSession(); // ← {authenticated:true,…} if a session exists in this partition
if (s.authenticated) showApp(s.user);
allowed_origins d'une app doivent donc lister son propre domaine ET le domaine englobant (ex. appdock.pro).allowed_origins (un site étranger n'obtient jamais de token).Langues
Le formulaire de connexion hébergé parle 10 langues : English, Deutsch, Français, Español, Italiano, Português, 日本語, 한국어, 中文, Русский. Par défaut il s'ouvre dans la langue du navigateur de l'utilisateur (anglais en secours) ; la langue se change directement dans le formulaire — le menu à drapeaux en bas.
- Forcer une langue. Passez
langau widget ou au SDK :ApploginUI.mount({ appId, lang: "fr" })ouApplogin.init({ appId, lang: "fr" })— le formulaire s'ouvre dans cette langue. Sans l'option, le SDK envoie automatiquement la langue du navigateur. - Relire le choix. L'utilisateur peut changer la langue dans le formulaire. Le résultat de
Applogin.openLogin()contientlang— la langue du formulaire au moment de la connexion — pour que votre page puisse suivre. Le widget la mémorise aussi (localStorageal_lang) : le prochain formulaire s'ouvrira dans cette langue. - Les e-mails suivent le formulaire. Les e-mails de vérification et de réinitialisation partent dans la langue du formulaire.
Sous le capot, l'URL du formulaire accepte ?lang=xx (code à deux lettres de la liste ci-dessus) — le SDK le transmet pour vous.
Exemple en direct : AppDock
appdock.pro est un lanceur « dock » : une page qui ouvre plusieurs applications dans des iframes. Les applications vivent sur leurs propres domaines :
| Application | Domaine | app_id |
|---|---|---|
| Email Writer | emailwriter.online | app_emailwriter |
| Audio Recorder | audiorecorder.info | app_recorder |
Connectez-vous à Email Writer dans le dock, puis ouvrez Audio Recorder (également dans le dock) — la connexion est reprise automatiquement : les deux tournent sous le même site de premier niveau appdock.pro et partagent une partition SSO.
1. Le lanceur (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. Une application (ex. 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. Enregistrement des apps pour ce scénario
Chaque application liste dans allowed_origins son propre domaine + celui du dock (frame-ancestors voit toute la chaîne d'ancêtres du frame imbriqué) :
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.Vérifier le token sur votre backend
Votre frontend place Applogin.getToken() dans l'en-tête Authorization de ses requêtes. Côté backend, deux méthodes de vérification.
1. Via l'endpoint de la plateforme tient compte de la révocation
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. En local (HS256 avec votre jwt_secret) sans réseau
// 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.Structure du JWT
{
"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 (facultatif)
Si une application définit un webhook_url, la plateforme y envoie un POST signé avec l'identité vérifiée à chaque connexion Google réussie — pour la synchronisation côté serveur en plus du token.
| En-tête | Valeur |
|---|---|
X-Applogin-Timestamp | unix-ms |
X-Applogin-Signature | sha256=<hex> de 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();
Créer une application
Les applications se créent dans le tableau de bord privé applogin.one/dashboard (connexion via Applogin lui-même). Vous fournissez :
| Champ | Pourquoi |
|---|---|
name | Affiché dans le formulaire de connexion (« Connexion · <name> »). |
allowed_origins | Origines autorisées à intégrer le formulaire et à recevoir des tokens. Listez le domaine de l'app + le domaine englobant (ex. le dock). |
redirect_uris | Pour la connexion Google : https://applogin.one/auth-callback.html. |
webhook_url | (facultatif) où envoyer le webhook de connexion. |
Vous recevez : app_id (public), jwt_secret (vérification du token côté backend), client_secret, webhook_signing_secret.
API REST — référence
Base : https://applogin.one/api. Ci-dessous, ce dont un intégrateur a réellement besoin. Les endpoints e-mail/mot de passe et d'échange Google sont appelés par le formulaire hébergé lui-même — jamais par vous.
Pour l'intégrateur
Vérifier un token d'app côté backend (avec révocation). { app_id, token } → { valid, user }.
Données publiques de l'application (name, allowed_origins). Utilisées par la page de connexion hébergée.
Internes (appelés par le formulaire hébergé/SDK, pas par vous)
| Endpoint | Rôle |
|---|---|
POST /v1/email/register · verify · resend · login · reset/request · reset/confirm · password/change | e-mail/mot de passe — appelés depuis le formulaire hébergé /login. |
POST /v1/auth/start, GET /oauth/google/callback, POST /v1/auth/exchange | OAuth Google (dans le formulaire hébergé). |
POST /v1/session/sso | SSO silencieux (appelé par /session depuis un iframe caché). |
POST /v1/session/establish | Dépose le cookie SSO dans la bonne partition (après Google). |
POST /v1/session/logout | Révocation de session (via le SDK logout()). |
Erreurs
| HTTP | Quand |
|---|---|
| 400 | Entrée invalide (mot de passe trop court, code invalide/expiré, « Email already registered »). |
| 403 | « Invalid credentials », accès refusé, « Too many attempts » (limitation de débit). |
| 404 | Application/route inconnue. |
{"error":"Invalid or expired code","message":"Invalid or expired code"}
Sécurité
- Le mot de passe est isolé. Les champs de saisie n'existent que dans l'iframe applogin.one ; le JS du site intégrateur ne peut pas les atteindre.
- Tokens limités à l'app. Le JWT est signé avec le secret de l'application et porte
aud=app_id— le token d'une app est invalide dans une autre. - Livraison du token uniquement à vos origines. Le formulaire envoie le token par
postMessageuniquement vers une origine desallowed_origins; la page de connexion est servie avecContent-Security-Policy: frame-ancestors <allowed_origins>(anti-clickjacking). - La session globale est HttpOnly. Le cookie
al_ssoest inaccessible au JS ; l'intégrateur ne détient jamais qu'un token d'app. - Anti-CSRF sur le SSO.
/v1/session/sson'émet un token que pourOrigin ∈ allowed_origins— un site étranger avec le cookie de l'utilisateur n'obtient rien. - Anti-bruteforce. Limitation de débit sur login/reset/verify (par e-mail et par IP).
- Les mots de passe sont hachés (PBKDF2) ; les codes sont hachés, TTL 10 minutes, limite de tentatives ; HTTPS partout ; les tokens Google ne sont jamais stockés. Connexion Google avec PKCE (S256) + state + nonce.
Aide-mémoire LLM
Modèle : toute l'authentification se passe dans un iframe sur applogin.one. L'intégrateur ne rend PAS de formulaire, n'envoie PAS de mots de passe, ne vérifie PAS de codes. Il inclut SDK + widget et reçoit un token d'app.
// 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 : la connexion dépose le cookie al_sso (Partitioned, par site de premier niveau). Les apps sous un même site (ex. iframes d'un dock comme appdock.pro) partagent la session ; un domaine séparé → reconnexion. Les allowed_origins d'une app = son domaine + le domaine englobant.
Le token est limité à l'app : iss=applogin, aud=app_id, sub=id utilisateur, signé avec le jwt_secret de l'app.
Applogin · connexion unifiée · tableau de bord · exemple en direct : AppDock