SuperTokens se décrit comme une alternative open source à Auth0, mais alors, qu’en est-il vraiment ? Comme toujours, pour se faire une conviction, rien de mieux qu’une analyse. Super ou pas super ? C’est ce que nous allons voir.

SuperTokens, c’est quoi ?

La promesse de SuperTokens est de fournir des fonctionnalités d’authentification prêtes à l’emploi, implémentables rapidement et facilement personnalisables.

Il s’agit donc d’un middleware d’authentification.

Le produit est assez jeune puisque le premier commit date de janvier 2020, soit un peu moins de 3 ans au moment de la rédaction de cet article.

De l’authentification sous toutes ses formes

Une des grandes forces de SuperTokens est de fournir les mécanismes d’authentification les plus répandus.

Appelés “recettes” (recipes), nous retrouvons les traditionnels flows de Login / password, ou Social Login, mais également des flows que certains de ses concurrents ne proposent pas nativement, comme l’authentification sans mots de passe (via SMS ou Magic Link par exemple).

D’autres sont en cours d’implémentation ou dans la roadmap comme le 2FA / MFA ou de l’authentification via Wallet Ethereum.

En plus de l’authentification, SuperTokens fournit les tunnels de création de compte (très basique) et de récupération de mots de passe.

Une architecture 4 tiers

Pour fonctionner, SuperTokens s’appuie sur une architecture traditionnelle :

Architecture SuperTokens
  • le module CORE, à déployer chez soi, héberge les apis d’authentification (cf. la spécification OpenAPI) et s’occupe de gérer l’état des sessions utilisateurs en les sauvegardant en BDD.
  • un module d’API, qui, à l’aide d’adapters SuperTokens, mettra à disposition du front les endpoints du module CORE.
  • une application front qui utilisera le SDK SuperTokens pour proposer les pages d’authentification et communiquer avec le backend.

SuperTokens se démarque sur son mode de fonctionnement puisque votre application front ne contactera jamais la brique CORE en directe (comme ce serait le cas pour un flow OAuth par exemple). Elle sera forcée de communiquer avec votre propre API, qui elle, s’occupera de la communication avec le CORE.

Des SDKS peu nombreux, mais efficaces

Implémenter une authentification en moins de 45 minutes n’est pas possible sans facilitateurs.

SuperTokens propose donc des SDKs pour faciliter sa mise en œuvre, mais ils sont peu nombreux pour le moment.

La core team s’est concentrée sur trois langages (novembre 2022) : Javascript, Python et Go.

Ceci se traduit par :

  • Une intégration coté front pour les technologies React, Vue, Angular (et Javascript/Typescript)
    • La partie UI est basée sur leurs composants React. Si vous utilisez Vue ou Angular, vous devrez alors faire un peu de JSX dans votre application pour servir les pages d’authentification (et donc utiliser également le runtime react) si vous ne souhaitez pas les redévelopper.
    • L’API de gestion de l’authentification (session, gestion des “recipes”, etc) est quant à elle disponible via un SDK supertokens-web-js.
  • Une intégration backend pour NodeJS, GoLang et Python
    • Pour la partie NodeJS, l’équipe SuperTokens supporte pas moins de 8 frameworks (impressionnant !) tels que Express, Hapi, Fastify, Next.js ou encore NestJS.
    • Coté Python, idem, vous pourrez intégrer SuperTokens dans du FastAPI, Flask ou encore Django.

Je regrette qu’il n’y ait pas de support pour l’écosystème java à ce jour, mais le sujet est au moins dans la roadmap (lointaine ?) du produit.

Moins d’une heure pour mettre en place l’authentification

La promesse de SuperTokens est tenue. Vous parviendrez à sécuriser votre application en quelques dizaines de minutes.

Les SDKs sont bien pensés et la documentation du produit facilite leur mise en place.

Pour développer les pages de connexions sur votre application, il vous suffit de suivre l’une des recettes proposées par SuperTokens :

  • Déployer le service CORE afin de mettre à disposition les endpoints d’authentification
  • Ajouter à votre backend :
  • Ajouter à votre front
    • La configuration liée a Supertokens
    • La mise en place des pages d’authentification en fonction de vos use-cases en utilisant les widgets SuperTokens
    • Exploiter l’API Session pour contrôler l’état de la session de l’utilisateur

Vous n’aurez pas besoin de fournir à vos APIs les tokens/cookies d’authentification, car SuperTokens est capable d’intercepter les requêtes de type Axios ou XHR et de s’en charger pour vous.

Une gestion du RBAC simplifiée

RBAC, pour Role-based Access Control, permet d’assigner à vos utilisateurs des rôles et des permissions afin de conditionner leurs actions sur vos applications.

Là encore, SuperTokens a fait en sorte que la fonctionnalité soit facile à mettre en place (ce qui est ordinairement un sujet plutôt complexe).

D’ailleurs, la core team semble être assez fière du travail accompli à en croire ce thread de tweets.

Thread de tweets concernant le RBAC SuperTokens

Pour implémenter le RBAC avec SuperTokens, il suffit de :

  • Ajouter le “recipe” UserRoles.init() dans la configuration SuperTokens
  • Créer les rôles et leurs permissions via l’API UserRoles
  • Assigner ses rôles et permissions aux utilisateurs via un simple UserRoles.addRoleToUser(userId, "user");
  • Utiliser les validators SuperTokens coté backend ou frontend pour conditionner l’accès

Attention, si vous modifiez des rôles ou permissions sur un utilisateur qui a déjà une session active, pensez à rafraîchir sa session en conséquence via :

import {UserRoleClaim, PermissionClaim} from "supertokens-node/recipe/userroles";
import {SessionContainer} from "supertokens-node/recipe/session"

async function addRolesAndPermissionsToSession(session: SessionContainer) {
    // we add the user's roles to the user's session
    await session.fetchAndSetClaim(UserRoleClaim)

    // we add the permissions of a user to the user's session
    await session.fetchAndSetClaim(PermissionClaim)
}

Fonctionnalités avancées

Hormis les fonctionnalités standards que l’on attend d’une brique d’authentification, SuperTokens supporte un certain nombre de fonctionnalités intéressantes :

Intégration avec des IAM externes

SuperTokens supporte la communication avec les fournisseurs d’identité externes les plus répandus pour l’authentification et permet également d’en configurer d’autres.

Alors, évidemment, nous avons voulu tester cela avec Keycloak, et ça fonctionne assez bien :

ThirdPartyEmailPassword.init({
       // contactMethod: "EMAIL", // This example will work with any contactMethod
       // flowType: "USER_INPUT_CODE_AND_MAGIC_LINK", // This example will work with any flowType
       providers: [
           {
               id: "keycloak",
               get: (redirectURI, authCodeFromRequest) => {
                   return {
                       accessTokenAPI: {
                           // this contains info about the token endpoint which exchanges the auth code with the access token and profile info.
                           url: "http://localhost:8580/auth/realms/supertoken/protocol/openid-connect/token",
                           params: {
                               // example post params
                               client_id: "supertoken",
                               client_secret: "fSiw9XekCzaSx6XXbOP2mtrFAjoww64v",
                               grant_type: "authorization_code",
                               redirect_uri: redirectURI || "",
                               code: authCodeFromRequest || "",
                               //...
                           }
                       },
                       authorisationRedirect: {
                           // this contains info about forming the authorisation redirect URL without the state params and without the redirect_uri param
                           url: "http://localhost:8580/auth/realms/supertoken/protocol/openid-connect/auth",
                           params: {
                               client_id: "supertoken",
                               scope: "openid profile",
                               response_type: "code",
                               //...
                           }
                       },
                       getClientId: () => {
                           return "supertoken";
                       },
                       getProfileInfo: async (accessTokenAPIResponse) => {
                           const newVar: any = jwt_decode(accessTokenAPIResponse.access_token);
                           // @ts-ignore
                           return {
                               // id: newVar!.sub,
                               id: newVar!.email,
                               email : { // optional
                                   id: newVar!.email, // emailID
                                   isVerified: newVar!.email_verified // true if the email is verified already
                               }
                           };
                       }
                   }
               }
           }
       ],
   })

Pour récupérer les identifiants de l’utilisateur coté SuperTokens, vous devez implémenter la méthode getProfileInfo et y retourner la structure attendue par SuperTokens en y assignant les claims du token JWT adaptés.

Vous pouvez essayer SuperTokens en utilisant notre projet auth-benchmarks.

https://github.com/ineat/ineat-auth-benchmarks

Alors, SuperTokens est il parfait ?

Non, évidemment, mais qui l’est 🙂 ?

Il n’est déjà pertinent que pour les technologies citées au début de cet article. Utiliser SuperTokens dans un écosystème Java par exemple serait contre productif.

Le produit est encore en cours de développement et donc certains de ses aspects sont perfectibles, notamment la documentation.

La roadmap du produit est disponible ici !

https://supertokens.com/product-roadmap

Cette dernière, bien que séduisante sur la forme, est parfois décousue (il peut être difficile de retomber sur un chapitre de la doc dans une des pages des recettes par exemple). Certaines fonctionnalités ne sont pas encore documentées, mais des projets d’exemples restent néanmoins disponibles.

SuperTokens n’est pas une solution exposant les endpoints standards OAuth2 / OIDC ; Vous ne pourrez donc pas proposer à des acteurs externes l’intégration avec votre système d’authentification comme on pourrait le faire avec un Keycloak par exemple.

En tout cas, SuperTokens propose de belles choses, à travers une approche assez disruptive pour un middleware d’authentification, il mérite donc que nous continuions de nous y intéresser, et vous ?

Liens utiles