Learn Backstage - Authentication & Identity
Episode 8 of 23

Learn Backstage - Authentication & Identity

Securing the entrance to Backstage: choosing and configuring auth providers from guest mode for development, OIDC, GitHub, Google, SAML, to Microsoft Entra ID and custom providers, understanding sign-in resolvers, and tracing Backstage identity through tokens, the Backstage-Identity header, and user principals.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 7, the documentation you built with TechDocs finally appears inside Backstage — but anyone who opens the portal gets to read all of it. Episode 8 closes that gap: we dive into Authentication & Identity, the layer that decides who gets into Backstage and what they hold. This is where Backstage changes from an open portal into a gate connected to your organization's identity provider, whether that's GitHub, Google, OIDC, SAML, or Microsoft Entra ID.

Authentication vs Identity

These two concepts are often conflated, but they're different:

  • Authentication — proving that a user is who they claim to be. Backstage does this through auth providers: GitHub, Google, OIDC, and so on.
  • Identity — determining who a user is within the Backstage system once authenticated, and what ownership attaches to them. This is what flows into every backend request.

Authentication answers the question who is coming, while identity answers what are they allowed to do. Episode 8 covers both, starting with authentication providers.

Auth Providers

Overview

An auth provider is a module that connects Backstage to an external identity provider. Each provider implements an OAuth flow or a similar protocol, and the results are normalized into a single Backstage identity format. Providers are enabled through the auth.providers configuration in app-config.yaml.

ProviderProtocolBest for
GuestNo credentialsLocal development (not for production)
GitHubOAuth AppTeams that use GitHub daily
GoogleOAuth 2.0Organizations using Google Workspace
OIDCOpenID ConnectGeneric SSO with IdPs like Keycloak or Okta
SAMLXML-based assertionEnterprise IdPs like ADFS
Microsoft Entra IDOAuth 2.0 / OpenID ConnectMicrosoft 365 organizations
CustomDepends on implementationInternal IdPs or specific needs

Guest Mode for Development

The simplest provider is guest mode: one click to sign in without a username or password. Its purpose is purely for development — so developers don't have to open OAuth every time they run Backstage on a local machine.

Mengaktifkan guest mode di app-config.yaml
auth:
  environment: development
  providers:
    guest: {}

Other providers (GitHub, Google, and so on) are configured with clientId and clientSecret, usually pulled from environment variables so they're never recorded in the repository. Secret values are substituted when the config is loaded.

Mengonfigurasi beberapa provider sekaligus
auth:
  environment: development
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
    google:
      development:
        clientId: ${AUTH_GOOGLE_CLIENT_ID}
        clientSecret: ${AUTH_GOOGLE_CLIENT_SECRET}

Custom Auth Providers

When no built-in provider fits — for example an internal IdP with a proprietary protocol — Backstage lets you build your own provider through the auth extension point in the backend. A custom provider typically wraps an OAuth flow or another protocol and produces an identity in the same format as built-in providers.

Menambahkan custom auth provider (new backend system)
import { createBackendModule } from '@backstage/backend-plugin-api';
import { authProvidersExtensionPoint } from '@backstage/plugin-auth-node';
import { myCustomProvider } from './providers';
 
export default createBackendModule({
  pluginId: 'auth',
  moduleId: 'custom-provider',
  register(reg) {
    reg.registerInit({
      deps: { authProviders: authProvidersExtensionPoint },
      async init({ authProviders }) {
        authProviders.registerProvider({
          providerId: 'custom',
          factory: myCustomProvider,
        });
      },
    });
  },
});

Once registered, a custom provider is treated like any other: it appears on the login page and can be attached to sign-in resolvers.

Sign-in Resolvers

When a user is authenticated at an external provider, Backstage doesn't yet know who that user is in the catalog. A sign-in resolver bridges the two: it maps a profile from the provider to a user entity in the catalog, usually based on email or username. Resolvers are attached per provider via signIn.resolvers — they can also be attached for all providers.

Sign-in resolver untuk provider GitHub
auth:
  providers:
    github:
      development:
        clientId: ${AUTH_GITHUB_CLIENT_ID}
        clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
        signIn:
          resolvers:
            - resolver: emailMatchingUserEntityAnnotation

emailMatchingUserEntityAnnotation matches the provider's email against the email on the user entity in the catalog. If no resolver matches, sign-in fails — this isn't a bug but a control mechanism: only users registered in the catalog are allowed in.

Warning

Never enable guest mode in a production environment. It grants access without any authentication and is usually meant for demos only. In production, enable only real providers and make sure every provider has a correct sign-in resolver.

Backstage Identity

Tokens, Headers, and Principals

After a successful sign-in, Backstage builds an identity used across the entire system. Three concepts you need to know:

ConceptFormUsage
Backstage tokenShort-lived JWT tokenIssued at sign-in, used for requests that need identity
Backstage-Identity headerHTTP header carrying the tokenSent on requests between backends and to backend plugins
User principalResolved identity objectThe request context held by backend plugins

A Backstage token is a JWT issued when the user signs in. It's short-lived and contains claims such as the user's identity. The Backstage-Identity header is the channel that carries that token from the frontend to the backend — every request that needs a user identity includes it. The user principal is the result of resolving the token into an identity object containing a reference to the user entity, the entities the user owns, and additional attributes. This principal becomes the context of every request in a backend plugin.

Identity in the Backend

Backend-to-backend communication also uses tokens, but in a different way than the frontend: service identity uses service tokens, while requests from the frontend use user tokens carried by the Backstage-Identity header. The backend verifies the token to know where the request came from, then translates it into a user principal for the plugins.

Menelusuri identitas dari token yang diterima
curl -i "http://localhost:7007/api/catalog/entities" \
  -H "Authorization: Bearer ${BACKSTAGE_USER_TOKEN}"

The value of the BACKSTAGE_USER_TOKEN variable is a token taken from the login session. The backend verifies that token, builds the user principal, and executes the request in the context of that identity — including the ownership rules we'll explore further in episode 11 and the permission framework in episode 13.

Conclusion

In this episode 8, you secured the entrance to Backstage: the difference between authentication and identity, the catalog of auth providers from guest mode, OIDC, GitHub, Google, SAML, to Microsoft Entra ID and custom providers, the role of sign-in resolvers in mapping external users into the catalog, and the path of Backstage identity through tokens, the Backstage-Identity header, and user principals.

The key takeaways:

  • Guest mode is only for development — in production use real providers, and never leave guest enabled.
  • Auth providers and identity are two layers — the provider proves who the user is, the sign-in resolver links them to a catalog entity.
  • Short-lived tokens, carried by a header — the frontend sends Backstage-Identity; the backend verifies and builds a user principal.
  • Custom providers are possible — an internal IdP can be wrapped through the auth extension point in the backend.

In the next episode, episode 9, we tidy up the foundation you've been tweaking all series: Advanced Configuration & Secrets — how app-config is validated, how environment variables are substituted, and how secrets like auth provider credentials are stored without ever touching the repository.