Aller au contenu

Configurez l'authentification SAML dans Backstage en utilisant Keycloak

La configuration de l'authentification SAML dans Backstage peut être une tâche difficile en raison du manque de documentation.

Si tu es ici, cette image ne t'es pas inconnue !

La configuration de l'authentification SAML dans Backstage peut être une tâche difficile en raison du manque de documentation.

Son intégration nécessite une compréhension approfondie des deux technologies (mécanisme d'authentification Backstage basé sur les configurations de passeport-saml et celle du fournisseur SAML). La documentation assez limitée peut nécessiter de nombreux essais et erreurs, ce qui prend beaucoup de temps pour les personnes cherchant à mettre en œuvre efficacement l'authentification SAML dans Backstage.

Dans cet article, je vais vous fournir un guide étape par étape sur la façon de configurer l'authentification SAML en utilisant Keycloak comme fournisseur d'identité.

Déployez et configurez votre propre Keycloak à l'aide de Docker

  • Ouvrez un terminal et démarrez l'image du conteneur Keycloak à l'aide de la commande suivante:
$ docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:21.0.2 start-dev
  • Attendez quelques secondes, puis dans votre navigateur, ouvrez la console d'administration sur http://localhost:8080/
  • Créez un client SAML en utilisant les attributs suivants:
| Property                 | Value                       |
| ------------------------ | --------------------------- |
| Name                     | backstage                   |
| Root URL                 | http://localhost:3000       |
| Name ID format           | email                       |
| Sign documents           | on                          |
| Sign assertions          | on                          |
| Signature algorithm      | RSA_SHA256                  |
| Signing keys config      | on (gardez la clé privée)   | 
  • Créez un nouveau "client scope" et ajoutez celui-ci au client SAML (configuration requise pour recevoir l'email dans la réponse SAML)
| Property                 | Value                       |
| ------------------------ | --------------------------- |
| Name                     | emailAddress                |
| Protocol                 | SAML                        |
| Mapper type              | User Attribute              |
| Mapper Name              | email                       |
| User Attribute           | email                       |
| SAML Attribute Name      | email                       |

Configurez l'authentication SAML dans Backstage

  • Ajoutez le plugin d'authentification SAML dans votre application backstage. La configuration SAML reflète étroitement celle de l'OIDC (OpenID Connect). Reportez-vous à la documentation OIDC pour plus de détails: https://backstage.io/docs/auth/oidc
+++ b/backstage-app/packages/app/src/apis.ts
@@ -19,7 +19,7 @@ import {
   discoveryApiRef,
   oauthRequestApiRef,
 } from '@backstage/core-plugin-api';
+import { OAuth2, SamlAuth } from '@backstage/core-app-api'
 
 
 export const localOIDCAuthApiRef: ApiRef<
@@ -32,6 +32,14 @@ export const localOIDCAuthApiRef: ApiRef<
   id: 'internal.auth.oidc',
 });
 
+export const localSamlAuthApiRef: ApiRef<
+  ProfileInfoApi &
+  BackstageIdentityApi &
+  SessionApi
+> = createApiRef({
+  id: 'internal.auth.saml',
+});
+

 export const apis: AnyApiFactory[] = [
@@ -63,5 +71,24 @@ export const apis: AnyApiFactory[] = [
           defaultScopes: ['openid', 'profile', 'email'],
         })
     }),
+
+  createApiFactory(
+    {
+      api: localSamlAuthApiRef,
+      deps: {
+        discoveryApi: discoveryApiRef,
+        configApi: configApiRef,
+      },
+      factory: ({ discoveryApi }) =>
+        SamlAuth.create({
+          discoveryApi,
+          provider: {
+            id: 'saml',
+            title: 'Custom saml provider',
+            icon: () => null,
+          },
+        })
+    }),
+
   ScmAuth.createDefaultApiFactory(),
+++ b/backstage-app/packages/app/src/App.tsx
@@ -22,7 +22,7 @@ import {
 import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
 import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
 import { UserSettingsPage } from '@backstage/plugin-user-settings';
+import { apis, localOIDCAuthApiRef, localSamlAuthApiRef } from './apis';
 import { entityPage } from './components/catalog/EntityPage';
 import { searchPage } from './components/search/SearchPage';
 import { Root } from './components/Root';
@@ -67,6 +67,12 @@ const app = createApp({
                 title: 'OIDC',
                 message: 'Sign in using OIDC
                 apiRef: localOIDCAuthApiRef,
+              },
+              {
+                id: 'saml',
+                title: 'SAML',
+                message: 'Sign in using SAML',
+                apiRef: localSamlAuthApiRef,
               }
             ]
           }
+++ b/backstage-app/packages/backend/src/plugins/auth.ts
@@ -99,7 +98,33 @@ export default async function createPlugin(
           },
         },
       }),
+      saml: providers.saml.create({
+        signIn: {
+          resolver: async (info, ctx) => {
+            const {
+              profile: { email },
+            } = info;
+            if (!email) {
+              throw new Error('Profile contained no email');
+            }
+            const userId = email.split('@')[0];
+            const entityRef = stringifyEntityRef({
+              kind: 'User',
+              namespace: DEFAULT_NAMESPACE,
+              name: userId,
+            });
 
+            const token = await ctx.issueToken({
+              claims: {
+                sub: entityRef,
+                ent: [entityRef],
+              },
+            });
+            return token;
+          },
+        }
+      }),
       oidc: providers.oidc.create({
         signIn: {
           resolver: async (info, ctx) => {
  • L'aspect le plus difficile consiste à trouver les paramètres de configuration requis pour activer l'authentification SAML. Les propriétés peuvent être trouvées dans la définition du schéma: schema definition.
+    saml:
+      privateKey: ${SAML_PRIVATE_KEY}
+      entryPoint: ${SAML_ENTRYPOINT}
+      issuer: ${SAML_ISSUER}
+      cert: ${SAML_CERT}
+      signatureAlgorithm: sha256
  • SAML_PRIVATE_KEY:
    Error: error:1E08010C:DECODER routines::unsupported
    La clé privée téléchargée lors de la création du client est de type RSA encodé en base64, mais backstage attend du texte brut PEM. Vous pouvez utiliser les commandes suivantes pour effectuer la conversion (supprimez les en-têtes et les caractères de nouvelle ligne):
$ cat private.key| base64 -d > private.rsa
$ openssl rsa -in private.rsa -outform pem

Démarrez l'application et profitez de votre configuration SAML 🚀

 "happy developers write happy code"

Dernier