AuthN and AuthZ with Keycloak logo

Backstage Authentication and Authorization with Keycloak Plugin

Created by Red Hat

Authentication and Authorization with Keycloak means your Backstage uses Keycloak for identity and access. Keycloak is open source. It provides single sign on, user management, group roles, and token based security. It supports standard protocols like OpenID Connect and SAML.

This plugin brings your Keycloak users and groups into the Backstage catalog. It connects to the Keycloak API, reads a realm, then creates or updates User and Group entities in Backstage. You can keep ownership data current, use group membership for permissions, and align Backstage sign in with your existing identity setup. Authentication can use either client credentials or username and password through Keycloak.

Typical use cases include syncing org charts from Keycloak, driving ownership pages, showing user profiles, and mapping groups to Backstage permission rules. For teams that already rely on Keycloak, this avoids manual entry in Backstage and keeps roles and teams consistent across tools.

If you want a simple path to unify sign in, ownership data, and group based access in a self hosted Backstage, this plugin gives you that foundation.

Installation Instructions

These instructions apply to self-hosted Backstage only.

Install the backend package

Copy
yarn workspace backend add @backstage-community/plugin-catalog-backend-module-keycloak

Configure the provider

Add a Keycloak provider entry in your app config. Set real values for your host and credentials. You can tune the schedule if you want.

Copy
catalog:
  providers:
    keycloakOrg:
      default:
        baseUrl: https://your.keycloak.host
        loginRealm: ${KEYCLOAK_REALM}
        realm: ${KEYCLOAK_REALM}
        clientId: ${KEYCLOAK_CLIENTID}
        clientSecret: ${KEYCLOAK_CLIENTSECRET}
        schedule:
          frequency: { minutes: 30 }
          timeout: { minutes: 3 }

You can use password based auth instead of client credentials. Use username and password keys in the same place. Remove clientId and clientSecret in that case.

Supported config keys

  • baseUrl
  • realm
  • loginRealm
  • username
  • password
  • clientId
  • clientSecret
  • userQuerySize
  • groupQuerySize
  • maxConcurrency
  • schedule with frequency and timeout

New backend system

Register the backend module in your backend entry point.

Copy
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';

const backend = createBackend();

backend.add(
  import('@backstage-community/plugin-catalog-backend-module-keycloak'),
);

backend.start();

Nothing is needed in the frontend. This module syncs users and groups into the catalog. The default catalog plugin will render them.

Old backend system

Add the entity provider in the catalog backend plugin. This wires the Keycloak sync into the legacy catalog builder.

Copy
// packages/backend/src/plugins/catalog.ts
import { CatalogBuilder } from '@backstage/plugin-catalog-backend';
import { PluginEnvironment } from '../types';
import { KeycloakOrgEntityProvider } from '@backstage-community/plugin-catalog-backend-module-keycloak';

export default async function createPlugin(env: PluginEnvironment) {
  const builder = await CatalogBuilder.create(env);

  builder.addEntityProvider(
    KeycloakOrgEntityProvider.fromConfig(env.config, {
      id: 'default',
      logger: env.logger,
      scheduler: env.scheduler,
      tokenManager: env.tokenManager,
    }),
  );

  const { processingEngine, router } = await builder.build();
  await processingEngine.start();
  return router;
}

No frontend changes are required. The catalog pages will show the synced users and groups.

Optional custom transformers

You can override how users and groups are mapped into entities. Create a backend module and set custom transformers with the extension point. Install your module into the backend.

Copy
// plugins/keycloak-transformer/src/module.ts
import { createBackendModule } from '@backstage/backend-plugin-api';
import {
  GroupTransformer,
  keycloakTransformerExtensionPoint,
  UserTransformer,
} from '@backstage-community/plugin-catalog-backend-module-keycloak';

const customGroupTransformer: GroupTransformer = async (entity, realm, groups) => {
  // mutate group entity if needed
  return entity;
};

const customUserTransformer: UserTransformer = async (entity, user, realm, groups) => {
  // mutate user entity if needed
  return entity;
};

export const keycloakBackendModuleTransformer = createBackendModule({
  pluginId: 'catalog',
  moduleId: 'keycloak-transformer',
  register(reg) {
    reg.registerInit({
      deps: {
        keycloak: keycloakTransformerExtensionPoint,
      },
      async init({ keycloak }) {
        keycloak.setUserTransformer(customUserTransformer);
        keycloak.setGroupTransformer(customGroupTransformer);
      },
    });
  },
});

Then register your module in the new backend entry point.

Copy
// packages/backend/src/index.ts
import { createBackend } from '@backstage/backend-defaults';
import { keycloakBackendModuleTransformer } from '../../plugins/keycloak-transformer/src/module';

const backend = createBackend();

backend.add(
  import('@backstage-community/plugin-catalog-backend-module-keycloak'),
);
backend.add(keycloakBackendModuleTransformer);

backend.start();

Keycloak access setup

When you use client credentials, set the client access type to confidential. Enable service accounts. Grant these realm management roles to the client

  • query-groups
  • query-users
  • view-users

Metrics

This module exposes OpenTelemetry counters

  • backend_keycloak_fetch_task_failure_count_total
  • backend_keycloak_fetch_data_batch_failure_count_total

You can export them with any OpenTelemetry backend such as Prometheus. Use the Backstage OpenTelemetry setup to wire this.

TLS note

If you use self signed certs, you can set this env var before starting the backend. This is not recommended.

Copy
export NODE_TLS_REJECT_UNAUTHORIZED=0

Changelog

This changelog is produced from commits made to the AuthN and AuthZ with Keycloak plugin since 8 months ago, and based on the code located here. It may not contain information about all commits. Releases and version bumps are intentionally omitted. This changelog is generated by AI.

Breaking changes

  • Sanitize user and group names by default. Names with spaces or other illegal characters now get transformed so they pass Backstage catalog validation. This can change entity names in your catalog and any links that reference them. You can override the default transformers in your plugin config if you need the old behavior. #4369 merged 3 months ago

Features

  • Add default transformers to sanitize user names and group names. Add plugin catalog backend module logs to surface catalog logs. #4369 merged 3 months ago
  • Add metrics for the Keycloak backend plugin. #3445 merged 6 months ago
  • Update plugin metadata to list support for Keycloak and RHBK version 26. #3122 merged 7 months ago

Bug fixes

  • Fetch subgroups from the correct realm when listing subgroups. #4054 merged 4 months ago

Dependencies

  • Update Keycloak admin client to v26.3.4. Brings upstream fixes and security updates from the Keycloak project. #5340 merged 16 days ago
  • Update Keycloak admin client to v26.3.3. #5051 merged 26 days ago
  • Update Keycloak admin client to v26.3.2. #4779 merged 2 months ago
  • Update Keycloak admin client to v26.3.1. #4363 merged 2 months ago
  • Update Keycloak admin client to v26.1.4. #3125 merged 7 months ago
  • Update Keycloak admin client to v26.1.2. #2912 merged 7 months ago
  • Update type packages used in development
    • Update types for lodash to v4.17.20. #4338 merged 3 months ago
    • Update types for lodash to v4.17.17. #4145 merged 4 months ago
    • Update types for lodash to v4.17.16. #3164 merged 7 months ago
    • Update types for lodash to v4.17.15. #2598 merged 8 months ago
    • Update types for uuid to v10. #2233 merged 8 months ago

Maintenance

  • Remove support keywords and lifecycle keywords from some plugins. Also remove app config for dynamic plugins where not needed. #4302 merged 3 months ago
  • Switch from the inclusion helper to dynamic imports for ESM modules in the Keycloak plugin. Simplifies the setup on Backstage v1.36 and later. #3269 merged 6 months ago
  • Clean up historical references to vendor products and Janus in package metadata. #3476 merged 6 months ago
  • Reduce false positives in knip reports by moving to a workspace level config. #3018 merged 7 months ago

Set up Backstage in minutes with Roadie