Connect with Spunto
Connectez les utilisateurs à votre app avec leur compte Spunto — OAuth 2 en authorization code avec PKCE, et qui ils sont dans quelles organisations.
Spunto est un fournisseur OAuth 2 pour ses apps. « Connect with Spunto » indique à votre app qui est un membre, à quelles organisations il appartient, et avec quel rôle — de quoi montrer à chaque membre ce qui appartient à son organisation, et ne laisser que les owners et les admins le modifier.
C’est ce qu’utilise la page où une organisation gère ses propres machines : cette page vit sur le domaine de l’app, pas dans le dashboard, et a besoin de savoir qui la regarde.
| Flux | Authorization code, PKCE S256 obligatoire |
client_id | L’id de votre app, tiré de son manifeste |
client_secret | Le secret de signature de votre app — le seul secret que vous partagez déjà avec Spunto |
| URI de redirection | Celles que votre manifeste déclare dans oauth.redirectUris, comparées à l’identique. HTTPS uniquement (http est accepté pour localhost). Une fois l’app publiée, seulement celles qui ont été revues |
| Qui peut se connecter | Tant que votre app n’est pas publiée, seulement les membres de l’organisation qui l’a enregistrée |
| Scopes | identity |
| Access token | Opaque (spo_…), valable 1 heure. Pas de refresh token |
Envoyez l’utilisateur chez Spunto
Générez un code_verifier et un state, gardez-les tous les deux (un cookie signé de courte durée fait l’affaire), et redirigez :
https://spunto.net/api/oauth/authorize
?response_type=code
&client_id=acme-git
&redirect_uri=https%3A%2F%2Fgit.acme.dev%2Fspunto%2Foauth%2Fcallback
&scope=identity
&state=…
&code_challenge=BASE64URL(SHA256(code_verifier))
&code_challenge_method=S256Un utilisateur qui n’est pas connecté à Spunto se connecte d’abord. La première fois, il voit un écran de consentement ; ensuite, le consentement est mémorisé pour votre app et ces scopes, et il revient directement.
Récupérez le code
Spunto redirige vers votre redirect_uri avec ?code=…&state=…. Vérifiez state. Le code est valable 60 secondes et ne sert qu’une fois.
Échangez-le, de serveur à serveur
curl -X POST https://spunto.net/api/oauth/token \
-d grant_type=authorization_code \
-d code=… \
-d redirect_uri=https://git.acme.dev/spunto/oauth/callback \
-d code_verifier=… \
-d client_id=acme-git \
-d client_secret=…En form-encoded ou en JSON ; les identifiants du client peuvent aussi passer dans un en-tête HTTP Basic.
{ "access_token": "spo_…", "token_type": "Bearer", "expires_in": 3600, "scope": "identity" }Demandez de qui il s’agit
curl https://spunto.net/api/oauth/userinfo -H "Authorization: Bearer spo_…"{
"sub": "usr_…",
"name": "Ada Lovelace",
"email": "ada@acme.dev",
"picture": "https://…",
"orgs": [{ "id": "org_…", "name": "Acme", "slug": "acme", "role": "admin" }]
}Ouvrez ensuite votre propre session — un cookie sur votre domaine — avec ce qu’a dit userinfo. Quand elle expire, relancez le flux : le consentement étant mémorisé, cela ne coûte aucun clic à l’utilisateur.
- Une erreur sur une URI de redirection inconnue n’est pas redirigée. Si la
redirect_urine fait pas partie de celles que déclare votre manifeste, Spunto affiche l’erreur lui-même plutôt que d’envoyer le navigateur vers une adresse dont il ne peut pas se porter garant. - Un rôle lu à la connexion est le rôle au moment de la connexion. Si un admin est rétrogradé, votre app l’apprend à sa connexion suivante. Gardez des sessions courtes si cela compte pour vous.
org.idest le même id que celui que Spunto envoie dans chaque appel de capability — c’est ainsi que vous rapprochez un membre connecté des installations de son organisation.- Servez vos pages sur votre propre origine. OAuth n’a de sens qu’entre origines distinctes ; ne montez jamais les pages de votre app sous le domaine de Spunto.
- Une clé d’API ne peut pas donner son consentement. Seul un membre connecté au dashboard peut consentir ; une clé
spk_est refusée.