Backstage est un formidable outil de tableau de bord pour les développeurs. Son système de plugin le rends particulièrement flexible. Cependant la configuration de ces plugins peut s’avérer fastidueuse.
Backstage est en constante évolution, ce qui fait que la documentation à parfois du mal à suivre. C’est le cas depuis la migration vers le nouveau Backend system. Backstage dispose de plusieurs plugin permettant de
se connecter à la majorité des providers d’identité via OIDC. Toutefois, si vous souhaitez connecter backstage à un provider personnalisé comme un Keycloak d’entreprise la documentation n’est pas vraiment clair. C’est ce que nous allons voir dans ce post.
Création du plugin
Backstage fournis un provider OIDC mais pas de plugin prêt à l’emploi. Nous allons devoir créer un module pour étendre le plugin Auth de backstage avec notre support de OIDC. Nous utilisons la CLI de backstage pour cela
backstage-cli new --select backend-module
# ? Enter the ID of the plugin [required] : auth# ? Enter the ID of the module [required] : oidc
Backstage à maintenant générer une structure de plugin dans le dossier plugins/auth-backend-module-oidc. Commençons par ajouter la dépendences au provider OIDC fournis par Backstage
import{oidcAuthenticator}from'@backstage/plugin-auth-backend-module-oidc-provider';import{authProvidersExtensionPoint,createOAuthProviderFactory}from'@backstage/plugin-auth-node'import{coreServices,createBackendModule,}from'@backstage/backend-plugin-api';import{DEFAULT_NAMESPACE,stringifyEntityRef}from'@backstage/catalog-model';exportconstauthModuleOidc=createBackendModule({pluginId:'auth',moduleId:'oidc',register(reg){reg.registerInit({deps:{logger: coreServices.logger,providers: authProvidersExtensionPoint},asyncinit({logger,providers}){logger.info('Registering OIDC provider!');providers.registerProvider({providerId:'sso-auth-provider',factory: createOAuthProviderFactory({authenticator: oidcAuthenticator,asyncsignInResolver(info,ctx){constuserRef=stringifyEntityRef({kind:'User',name: info.result.fullProfile.userinfo.sub,namespace:DEFAULT_NAMESPACE});returnctx.issueToken({claims:{sub: userRef,// The user's own identity
ent:[userRef],// A list of identities that the user claims ownership through
}});}})});},});},});
Notre plugin est maintenant opérationel. Vérifions que le module est bien activé dans packages/backend/index.ts. La ligne suivant doit être présente :
Nous allons maintenant référencer le plugin comme API d’autentification dans le front. Pour cela ajouter le code suivant dans le fichier packages/app/src/apis.ts :
import{AnyApiFactory,ApiRef,BackstageIdentityApi,configApiRef,createApiFactory,createApiRef,discoveryApiRef,oauthRequestApiRef,OpenIdConnectApi,ProfileInfoApi,SessionApi,}from'@backstage/core-plugin-api';import{OAuth2}from'@backstage/core-app-api';exportconstoidcAuthApiRef: ApiRef<OpenIdConnectApi&// The OIDC API that will handle authentification
ProfileInfoApi&// Profile API for requesting user profile info from the auth provider in question
BackstageIdentityApi&// Backstage Identity API to handle and associate the user profile with backstage identity
SessionApi// Sesssion API, to handle the session the user will have while logged in
>=createApiRef({id:'sso-auth-provider'// Can be anything as long as it doesn't conflict with other API ref IDs
})exportconstapis: AnyApiFactory[]=[createApiFactory({api: oidcAuthApiRef,deps:{discoveryApi: discoveryApiRef,oauthRequestApi: oauthRequestApiRef,configApi: configApiRef},factory:({discoveryApi,oauthRequestApi,configApi})=>Oauth2.create({configApi,discoveryApi,oauthRequestApi,provider:{id:'sso-auth-provider',title:'Enterprise SSO',icon:()=>null},environment: configApi.getOptionalString('auth.environment'),defaultScopes:['openId','profile','email'],popupOptions:{size:{// fullscreen: true
// or specify popup width and height
width: 1000,height: 1000,}}})}),// Other createApiFactory
]
Ajout du bouton de connexion dans l’interface
Allons maintenant dans le fichier packages/app/src/App.tsx pour ajouter le bouton de connexion à backstage.
import{apis,oidcAuthApiRef}from'./apis';import{configApiRef,useApi}from'@backstage/core-plugin-api';constapp=createApp({// Other stuff...
components:{SignInPage: props=>(<SignInPage{...props}autoproviders={useApi(configApiRef).getString('auth.environment')==='development'?['guest']:[{id:'sso-auth-provider',title:'Enterprise SSO',message:'Sign in with Enterprise SSO',apiRef: oidcAuthApiRef}]}/>)}// Other stuff...
})
Ajoutez la configuration suivante dans votre fichier app-config.local.yaml:
Avec la configuration ci-dessus, l’authentification se fera comme guest en mode developement et via SSO en mode production. Pour plus d’information, vous pouvez consulter la documentation officielle
Félicitation votre application backstage supporte maintenant la connexion via OIDC. Jetez également un œil à l’intégration Keycloak pour l’import automatique des utilisateurs et des groupes dans Backstage.