iss: https://id.agentboxd.com
Laissez les agents IA se connecter à votre app.
Shakehand ajoute un bouton « Se connecter avec Agentboxd » à votre application : un fournisseur OpenID Connect dont l’utilisateur est un agent IA. Les agents prouvent qui ils sont avec un jeton de courte durée au lieu d’un mot de passe, et votre application sait qu’elle parle à un agent. Donnez une identité à n’importe quel agent en un appel — boîte mail facultative.
- exp − iat ≤ 300
- Chaque jeton vit 5 minutes au plus, ne sert qu’une fois et n’est adressé qu’à une seule application.
- sub (pairwise)
- Chaque application voit un sujet différent et stable pour un même agent.
- OIDC · PKCE · JWKS
- OpenID Connect standard sur id.agentboxd.com. Better Auth, Auth.js ou tout client OIDC.
https://agentboxd.com/claims/agent: true
Les deux côtés d’une même connexion.
Les applications décident d’accepter les agents ; les agents ont besoin d’un accès qui ne soit pas un mot de passe emprunté. Shakehand est conçu pour les deux.
Vous créez une application ou une API
Des agents IA utilisent déjà votre produit : ils s’inscrivent avec des mots de passe et cliquent sur des e-mails de vérification, ou partagent les identifiants d’une personne. Donnez-leur une porte d’entrée à eux.
- Sachez que c’est un agent. Chaque jeton porte
agent: true, pour orienter les agents vers une inscription pensée pour l’API ou leur appliquer leurs propres limites. - Aucun mot de passe à stocker et aucune boucle d’e-mails à automatiser. Vérifiez un jeton signé et ouvrez votre session.
- OpenID Connect standard. Découverte, JWKS, flux par code avec PKCE, ou échange de jeton côté serveur. Aucun SDK propriétaire requis.
Vous créez des agents IA
Donnez une identité à n’importe quel agent en un appel — boîte mail facultative. Un agent doté d’une boîte mail Agentboxd en a déjà une ; un agent qui n’a jamais besoin d’e-mail reçoit une identité sans boîte mail. L’un comme l’autre se connecte à toute application qui accepte « Se connecter avec Agentboxd ».
- Un appel, aucun secret à garder.
mr.identity.token()renvoie un jeton de 5 minutes pour une application. - Boîte mail facultative.
mr.identities.create()crée une identité sans boîte mail : elle se connecte, et ses jetons ne portent aucun e-mail. - Confidentiel par défaut. Chaque application voit un sujet différent, si bien que les applications ne peuvent pas suivre votre agent d’un service à l’autre.
- Vous gardez la main. Coupez la connexion boîte mail par boîte mail et voyez chaque application à laquelle elle s’est connectée.
POST /v1/inboxes/:id/identity-token
Comment ça marche.
Trois étapes, et aucun mot de passe nulle part. C’est le flux sans navigateur (headless), pour les agents qui appellent directement votre API ou votre application.
- /app/identity
Enregistrez votre application
Dans le tableau de bord, enregistrez l’application et choisissez son type : une application serveur (avec le bouton), une application publique, ou vérification seule pour les agents qui appellent votre API. Vous obtenez un
client_id, l’audience de chaque jeton. - POST /v1/inboxes/:id/identity-token
L’agent demande un jeton
En un appel, l’agent obtient un jeton d’identité signé en ES256, adressé à votre
client_idet valable 5 minutes, et vous l’envoie. Depuis un client MCP, c’est l’outilget_identity_token. - verifyAgentIdentityToken
Vous le vérifiez et ouvrez une session
Vérifiez la signature avec les clés publiques, ainsi que l’émetteur, l’audience, l’expiration et le nonce, et rejetez un jeton déjà vu. Le SDK fait tout cela ; vous pouvez aussi échanger le jeton auprès de l’émetteur, qui garantit l’usage unique pour vous.
import { Agentboxd } from 'agentboxd';
const mr = new Agentboxd(); // a key with identity:sign (preset "sign_in")
// A 5-minute, single-use ID token addressed to one app (its client_id).
const { id_token } = await mr.identity.token({
inboxId: inbox.id,
audience: 'abxc_4kQ9...',
nonce, // optional: the one the app gave you
});
await fetch('https://app.example.com/login/agent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id_token }),
});import { MemoryReplayCache, verifyAgentIdentityToken } from 'agentboxd/identity'; // npm install agentboxd jose
const replayCache = new MemoryReplayCache(); // several processes: back it with Redis (SET jti 1 NX EXAT exp)
export async function signInAgent(idToken: string, nonce?: string) {
const agent = await verifyAgentIdentityToken(idToken, {
audience: process.env.AGENTBOXD_CLIENT_ID!, // your client_id
nonce, // if you handed the agent one
replayCache, // single use: a second presentation of the same jti throws
});
// agent.sub is stable for your app and different at every other app: key the user on it.
return { sub: agent.sub, email: agent.email, isAgent: agent.isAgent };
}{
"iss": "https://id.agentboxd.com",
"sub": "Qm9vZ2xlLXBhaXJ3aXNlLXN1YmplY3QtZXhhbXBsZQ",
"aud": "abxc_4kQ9...",
"iat": 1790327643,
"exp": 1790327943,
"auth_time": 1790327643,
"jti": "3f2e1d0c-9b8a-4765-8432-10fedcba9876",
"nonce": "n-3f9a2c",
"email": "support-bot@homingbox.net",
"email_verified": true,
"https://agentboxd.com/claims/agent": true
}alg: ES256
Conçu pour qu’un jeton ne puisse pas resservir.
Le jeton d’un agent ne vaut pas grand-chose pour qui le vole : il est de courte durée, à usage unique et valable pour une seule application. Les détails sont dans la documentation.
- ES256
Signés, avec des clés renouvelées
Les jetons sont signés avec des clés ECDSA P-256 renouvelées régulièrement. Les vérificateurs les récupèrent depuis le JWKS ; les algorithmes
noneet HMAC sont refusés. - ≤ 300 S
Courte durée, sans jeton de rafraîchissement
Un jeton d’identité vit 5 minutes au plus. Il n’y a pas de jeton de rafraîchissement : un agent se reconnecte en un appel API, et c’est votre session qui décide combien de temps elle dure.
- USAGE UNIQUE
Chaque jeton ne sert qu’une fois
Chaque jeton a un
jtiunique. Tenez un cache anti-rejeu, ou échangez le jeton auprès de l’émetteur avec l’autorisation JWT bearer (RFC 7523), qui l’enregistre et refuse une seconde utilisation. - AUD = CLIENT_ID
Lié à une seule application
Un jeton nomme exactement une audience, votre
client_id. Un jeton émis pour une autre application échoue à la vérification et ne peut pas être échangé auprès de l’émetteur par un autre client. - PAIRWISE SUB
Un sujet différent dans chaque application
Chaque application voit son propre
substable pour un même agent, si bien que deux applications ne peuvent pas croiser leurs tables d’utilisateurs pour le suivre. Identifiez vos utilisateurs par leursub. - AGENT: TRUE
Les agents se déclarent comme agents
Chaque jeton porte
https://agentboxd.com/claims/agent: true. Le sujet est la boîte mail d’un agent IA, jamais une personne qui prétendrait le contraire. - PKCE S256
Un flux navigateur sûr
Le bouton utilise le flux par code d’autorisation avec PKCE S256,
stateetnoncetous obligatoires, des URI de redirection exactes, des codes à usage unique valables 60 secondes etissdans la réponse (RFC 9207). - COUPURE · HISTORIQUE
Les propriétaires voient et arrêtent chaque connexion
Chaque boîte mail a un interrupteur de connexion qui prend effet immédiatement, un historique de chaque jeton et de chaque connexion (conservé 180 jours), et un webhook pour chacun.
GET {issuer}/authorize
Ajoutez un bouton « Se connecter avec Agentboxd ».
Pour une application web, c’est une personne qui clique sur le bouton : le propriétaire de l’agent. Il approuve sur agentboxd.com et choisit laquelle des boîtes mail de ses agents se connecte, et votre application reçoit un résultat OpenID Connect normal, qui contient agent: true.
Faites pointer le bouton vers la route de connexion de votre bibliothèque d’authentification pour le fournisseur agentboxd. Le code à droite est un point de départ ; gardez le libellé « Sign in with Agentboxd » (ou « Se connecter avec Agentboxd » en français).
<a class="siwa" href="/api/auth/signin/agentboxd">
<svg width="20" height="20" viewBox="0 0 32 32" aria-hidden="true">
<circle cx="12.5" cy="16" r="8" fill="none" stroke="#D4FF3A" stroke-width="3" />
<path d="M22.5 11.5h7M23.5 16h6M22.5 20.5h7" stroke="#EDEAE2" stroke-width="2.2" />
</svg>
Sign in with Agentboxd
</a>
<style>
.siwa { display: inline-flex; align-items: center; gap: 10px; min-height: 44px;
padding: 0 18px 0 12px; border: 1px solid #2A2D33; border-radius: 2px;
background: #0A0B0D; color: #EDEAE2; font: 600 15px/1 system-ui, sans-serif;
text-decoration: none; }
.siwa:focus-visible { outline: 2px solid #D4FF3A; outline-offset: 2px; }
</style>/.well-known/openid-configuration
Compatible avec l’authentification que vous avez déjà.
Shakehand, c’est de l’OpenID Connect standard : rien de nouveau à apprendre. Indiquez à votre bibliothèque le document de découverte, et elle trouve les clés et les points de terminaison.
- Better Auth : le plugin Generic OAuth, avec PKCE et vérification du jeton d’identité.
- Auth.js (NextAuth) : un petit fournisseur OIDC avec les vérifications pkce, state et nonce.
- Tout client OIDC avec le flux par code d’autorisation et PKCE, dans n’importe quel langage.
- Sans navigateur : verifyAgentIdentityToken depuis agentboxd/identity, ou l’échange de jeton RFC 7523.
Le code Better Auth, Auth.js et sans navigateur est vérifié par le typage dans examples/identity et présenté pas à pas dans le guide.
import { betterAuth } from 'better-auth';
import { genericOAuth } from 'better-auth/plugins';
const ISSUER = process.env.AGENTBOXD_ISSUER ?? 'https://id.agentboxd.com';
export const auth = betterAuth({
// database: your adapter
user: {
additionalFields: { isAgent: { type: 'boolean', required: false, defaultValue: false, input: false } },
},
plugins: [
genericOAuth({
config: [
{
providerId: 'agentboxd',
name: 'Agentboxd',
discoveryUrl: `${ISSUER}/.well-known/openid-configuration`,
clientId: process.env.AGENTBOXD_CLIENT_ID!,
clientSecret: process.env.AGENTBOXD_CLIENT_SECRET!,
scopes: ['openid', 'email', 'profile'],
pkce: true,
requireIdTokenVerification: true,
mapProfileToUser: (profile) => ({
name: typeof profile.name === 'string' ? profile.name : undefined,
email: typeof profile.email === 'string' ? profile.email : null,
emailVerified: profile.email_verified === true,
isAgent: profile['https://agentboxd.com/claims/agent'] === true,
}),
},
],
}),
],
});
// In the browser:
// await authClient.signIn.social({ provider: 'agentboxd', callbackURL: '/dashboard' });import type { OIDCConfig, OIDCUserConfig } from '@auth/core/providers';
export interface AgentboxdProfile extends Record<string, unknown> {
sub: string;
email?: string;
email_verified?: boolean;
name?: string;
'https://agentboxd.com/claims/agent': true;
}
export default function Agentboxd(options: OIDCUserConfig<AgentboxdProfile>): OIDCConfig<AgentboxdProfile> {
return {
id: 'agentboxd',
name: 'Agentboxd',
type: 'oidc',
issuer: 'https://id.agentboxd.com',
checks: ['pkce', 'state', 'nonce'], // Agentboxd requires all three
authorization: { params: { scope: 'openid email profile' } },
profile: (p) => ({ id: p.sub, name: p.name ?? p.email ?? null, email: p.email ?? null, image: null }),
options,
};
}curl https://id.agentboxd.com/.well-known/openid-configuration
# Configure any OpenID Connect client with:
# issuer https://id.agentboxd.com
# client_id abxc_... (register the app in the dashboard, Identity)
# client_secret abxs_... (server apps only; shown once)
# scopes openid email profile
# flow authorization code + PKCE (S256), with state and noncecurl -X POST https://id.agentboxd.com/token \
-u "$AGENTBOXD_CLIENT_ID:$AGENTBOXD_CLIENT_SECRET" \
-d grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer \
-d assertion="$ID_TOKEN"
# 200 { "access_token": "abxat_...", "token_type": "Bearer", "expires_in": 300,
# "id_token": "eyJ...", "scope": "openid email" }
# A second exchange of the same token: 400 { "error": "invalid_grant" }GET /platform/plans
Les applications sont gratuites, pour toujours.
Enregistrez autant d’applications que vous voulez, avec n’importe quelle offre, et ne payez jamais par connexion à votre application. L’espace de travail de l’agent a Shakehand avec son offre Agentboxd. Pendant la bêta publique, chaque espace de travail utilise les limites de l’offre Free et rien n’est facturé.
Une connexion correspond à un jeton d’identité que nous émettons pour un agent. Une identité sans boîte mail se connecte mais ne reçoit aucun e-mail ; chaque boîte mail est aussi une identité et compte comme une boîte mail. L’offre Free s’arrête à son quota de connexions jusqu’au mois suivant ; les offres payantes relèvent d’un usage raisonnable, sans prix de dépassement. Tous les tarifs
- Votre application
- Gratuite et illimitée avec toutes les offres.
- Free
- 100 identités sans boîte mail, 10 000 connexions par mois
- Builder · 15 $/mois après la bêta
- 1 000 identités sans boîte mail, 100 000 connexions par mois
- Team · 60 $/mois après la bêta
- 10 000 identités sans boîte mail, 1 000 000 connexions par mois
- Scale · sur mesure, après la bêta
- Identités sans boîte mail illimitées, connexions illimitées
Questions
Questions.
Qu’est-ce que Shakehand ?
Shakehand est le produit Agentboxd qui ajoute un bouton « Se connecter avec Agentboxd » à votre application. Derrière le bouton se trouve un fournisseur d’identité OpenID Connect, sur id.agentboxd.com, dont l’utilisateur est un agent IA. L’identité d’un agent est sa boîte mail Agentboxd, ou une identité sans boîte mail, et il se connecte aux applications avec un jeton d’identité de courte durée et à usage unique au lieu d’un mot de passe.
Mon agent a-t-il besoin d’une boîte mail pour se connecter ?
Non. Donnez une identité à n’importe quel agent en un appel — boîte mail facultative. POST /v1/identities crée une identité sans boîte mail : elle se connecte avec tous les flux, ses jetons ne portent aucune adresse e-mail mais une revendication mailbox: false, et elle compte dans une limite d’identités distincte (100 avec l’offre Free), pas dans vos boîtes mail. Identité sans boîte mail.
Me faut-il un compte Agentboxd pour accepter des agents dans mon application ?
Il vous faut un compte gratuit pour enregistrer votre application et obtenir un client_id. Ensuite, vérifier un jeton ne demande que les clés publiques : n’importe quelle bibliothèque OpenID Connect ou JOSE convient, et le paquet TypeScript agentboxd fournit une fonction qui fait toutes les vérifications. Créer un compte.
Avec quelles bibliothèques cela fonctionne-t-il ?
Tout client OpenID Connect qui prend en charge le flux par code d’autorisation avec PKCE. Le guide contient des configurations fonctionnelles pour Better Auth (plugin Generic OAuth) et Auth.js, ainsi qu’une partie de confiance (relying party) sans navigateur en TypeScript. Les autres clients n’ont besoin que de l’URL de découverte, de votre client_id et, pour les applications serveur, du secret client. Le guide.
Comment un jeton est-il protégé contre le rejeu ou le vol ?
Il vit au plus 5 minutes, nomme exactement une application comme audience, porte un jti unique que votre application ou l’émetteur n’accepte qu’une fois, et peut être lié à une tentative de connexion par un nonce. Le flux navigateur ajoute PKCE, state et des URI de redirection exactes.
Les applications peuvent-elles suivre mon agent d’un service à l’autre ?
Pas via Shakehand. Par défaut, chaque application reçoit un sujet différent pour un même agent. La revendication email est la même partout : une application qui la demande peut donc s’en servir pour recouper ; les applications soucieuses de la vie privée ne devraient pas la demander.
Qui approuve une connexion depuis le navigateur ?
Le propriétaire de l’agent. Le bouton l’envoie sur agentboxd.com, où il voit le nom de votre application, son hôte de redirection et les scopes, choisit quelle boîte mail se connecte et approuve. Aucun consentement n’est mémorisé : chaque connexion depuis le navigateur est approuvée.
Combien ça coûte ?
Les applications sont gratuites pour toujours : enregistrez-en autant que vous voulez, avec n’importe quelle offre, et personne ne paie par connexion à votre application. Les agents ont Shakehand avec toutes les offres Agentboxd : l’offre Free inclut 100 identités sans boîte mail et 10 000 connexions par mois, les offres payantes davantage, dans le cadre d’un usage raisonnable. Shakehand est en bêta publique et gratuit pendant la bêta. Tarifs de Shakehand.
/app/identity
Ouvrez votre application aux agents.
Enregistrez votre application dans le tableau de bord pour obtenir un client_id, puis suivez le guide. Gratuit avec toutes les offres.