Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@backstage/plugin-permission-node

backstage876.6kApache-2.00.10.4TypeScript support: included

Common permission and authorization utilities for backend plugins

backstage, permissions

readme

headline

Backstage

English | 한국어 | 中文版 | Français

License CNCF Status Discord Code style Codecov OpenSSF Best Practices OpenSSF Scorecard

What is Backstage?

Backstage is an open source framework for building developer portals. Powered by a centralized software catalog, Backstage restores order to your microservices and infrastructure and enables your product teams to ship high-quality code quickly without compromising autonomy.

Backstage unifies all your infrastructure tooling, services, and documentation to create a streamlined development environment from end to end.

software-catalog

Out of the box, Backstage includes:

  • Backstage Software Catalog for managing all your software such as microservices, libraries, data pipelines, websites, and ML models
  • Backstage Software Templates for quickly spinning up new projects and standardizing your tooling with your organization’s best practices
  • Backstage TechDocs for making it easy to create, maintain, find, and use technical documentation, using a "docs like code" approach
  • Plus, a growing ecosystem of open source plugins that further expand Backstage’s customizability and functionality

Backstage was created by Spotify but is now hosted by the Cloud Native Computing Foundation (CNCF) as an Incubation level project. For more information, see the announcement.

Project roadmap

For information about the detailed project roadmap including delivered milestones, see the Roadmap.

Getting Started

To start using Backstage, see the Getting Started documentation.

Documentation

The documentation of Backstage includes:

Community

To engage with our community, you can use the following resources:

Governance

See the GOVERNANCE.md document in the backstage/community repository.

License

Copyright 2020-2025 © The Backstage Authors. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our Trademark Usage page: https://www.linuxfoundation.org/trademark-usage

Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0

Security

Please report sensitive security issues using Spotify's bug-bounty program rather than GitHub.

For further details, see our complete security release process.

changelog

@backstage/plugin-permission-node

0.10.4

Patch Changes

0.10.4-next.0

Patch Changes

0.10.3

Patch Changes

0.10.3-next.0

Patch Changes

0.10.2

Patch Changes

0.10.2-next.0

Patch Changes

0.10.1

Patch Changes

0.10.1-next.1

Patch Changes

0.10.1-next.0

Patch Changes

0.10.0

Minor Changes

  • 4da2965: Fixed an issue causing the PermissionClient to exhaust the request body size limit too quickly when making many requests.

Patch Changes

0.10.0-next.2

Patch Changes

0.10.0-next.1

Minor Changes

  • 4da2965: Fixed an issue causing the PermissionClient to exhaust the request body size limit too quickly when making many requests.

Patch Changes

0.9.2-next.0

Patch Changes

0.9.1

Patch Changes

0.9.0

Minor Changes

  • 22ace13: BREAKING The ServerPermissionClient can no longer be instantiated with a tokenManager and must instead be instantiated with an auth service. If you are still on the legacy backend system, use createLegacyAuthAdapters() from @backstage/backend-common to create a compatible auth service.

Patch Changes

0.8.9-next.1

Patch Changes

0.8.9-next.0

Patch Changes

0.8.8

Patch Changes

  • 049d5d4: The returned router from createPermissionIntegrationRouter is now mutable, allowing for permissions and resources to be added after creation of the router.
  • b71f634: Added a new PermissionRuleset type that encapsulates a lookup function for permission rules, which can be created by the new PermissionsRegistryService via the getPermissionRuleset method. The createConditionTransformer and createConditionAuthorizer functions have been adapted to receive these accessors as arguments, with their older counterparts being deprecated.
  • a9621de: Added a new createPermissionResourceRef utility that encapsulates the constants and types related to a permission resource types. The createConditionExports and createPermissionRule functions have also been adapted to accept these references as arguments, deprecating their older counterparts.
  • Updated dependencies

0.8.8-next.2

Patch Changes

  • b71f634: Added a new PermissionRuleset type that encapsulates a lookup function for permission rules, which can be created by the new PermissionsRegistryService via the getPermissionRuleset method. The createConditionTransformer and createConditionAuthorizer functions have been adapted to receive these accessors as arguments, with their older counterparts being deprecated.
  • a9621de: Added a new createPermissionResourceRef utility that encapsulates the constants and types related to a permission resource types. The createConditionExports and createPermissionRule functions have also been adapted to accept these references as arguments, deprecating their older counterparts.
  • Updated dependencies

0.8.8-next.1

Patch Changes

0.8.8-next.0

Patch Changes

0.8.7

Patch Changes

0.8.7-next.1

Patch Changes

0.8.7-next.0

Patch Changes

0.8.6

Patch Changes

0.8.6-next.2

Patch Changes

0.8.6-next.1

Patch Changes

0.8.6-next.0

Patch Changes

0.8.5

Patch Changes

0.8.5-next.2

Patch Changes

0.8.5-next.1

Patch Changes

0.8.5-next.0

Patch Changes

0.8.4

Patch Changes

0.8.4-next.1

Patch Changes

0.8.4-next.0

Patch Changes

0.8.3

Patch Changes

0.8.3-next.2

Patch Changes

0.8.3-next.1

Patch Changes

0.8.3-next.0

Patch Changes

0.8.1

Patch Changes

0.8.1-next.3

Patch Changes

0.8.1-next.2

Patch Changes

0.8.1-next.1

Patch Changes

0.8.1-next.0

Patch Changes

0.8.0

Minor Changes

  • 36f91e8: BREAKING: Updated the ServerPermissionClient to match the new PermissionsService interface, where the deprecated token option has been removed and the options are now required.

Patch Changes

  • ed10fd2: The PermissionPolicy interface has been updated to align with the recent changes to the Backstage auth system. The second argument to the handle method is now of the new PolicyQueryUser type. This type maintains the old fields from the BackstageIdentityResponse, which are now all deprecated. Instead, two new fields have been added, which allows access to the same information:

    • credentials - A BackstageCredentials object, which is useful for making requests to other services on behalf of the user as part of evaluating the policy. This replaces the deprecated token field. See the Auth Service documentation for information about how to create a token using these credentials.
    • info - A BackstageUserInfo object, which contains the same information as the deprecated identity, except for the type field that was redundant.

    Most existing policies can be updated by replacing the BackstageIdentityResponse type with PolicyQueryUser, which is exported from @backstage/plugin-permission-node, as well as replacing any occurrences of user?.identity with user?.info.

  • 28b2cfb: Fix invalid cross-reference in API Reference docs

  • Updated dependencies

0.7.33-next.1

Patch Changes

0.7.32-next.0

Patch Changes

0.7.30

Patch Changes

0.7.30-next.3

Patch Changes

0.7.30-next.2

Patch Changes

0.7.30-next.1

Patch Changes

0.7.30-next.0

Patch Changes

0.7.29

Patch Changes

0.7.29-next.1

Patch Changes

0.7.29-next.0

Patch Changes

0.7.28

Patch Changes

0.7.28-next.1

Patch Changes

0.7.28-next.0

Patch Changes

0.7.27

Patch Changes

0.7.26

Patch Changes

0.7.25

Patch Changes

0.7.25-next.2

Patch Changes

0.7.25-next.1

Patch Changes

0.7.24-next.0

Patch Changes

0.7.21

Patch Changes

0.7.21-next.3

Patch Changes

0.7.21-next.2

Patch Changes

0.7.21-next.1

Patch Changes

0.7.21-next.0

Patch Changes

0.7.20

Patch Changes

0.7.20-next.2

Patch Changes

0.7.20-next.1

Patch Changes

0.7.20-next.0

Patch Changes

0.7.19

Patch Changes

0.7.19-next.3

Patch Changes

0.7.19-next.2

Patch Changes

0.7.19-next.1

Patch Changes

0.7.19-next.0

Patch Changes

0.7.18

Patch Changes

0.7.18-next.2

Patch Changes

0.7.18-next.1

Patch Changes

0.7.18-next.0

Patch Changes

0.7.17

Patch Changes

0.7.17-next.2

Patch Changes

0.7.16-next.1

Patch Changes

0.7.16-next.0

Patch Changes

0.7.14

Patch Changes

0.7.14-next.3

Patch Changes

0.7.14-next.2

Patch Changes

0.7.14-next.1

Patch Changes

0.7.13-next.0

Patch Changes

0.7.11

Patch Changes

0.7.11-next.2

Patch Changes

0.7.11-next.1

Patch Changes

0.7.11-next.0

Patch Changes

0.7.10

Patch Changes

0.7.10-next.0

Patch Changes

0.7.9

Patch Changes

0.7.9-next.2

Patch Changes

0.7.9-next.1

Patch Changes

0.7.9-next.0

Patch Changes

0.7.8

Patch Changes

0.7.8-next.1

Patch Changes

0.7.8-next.0

Patch Changes

0.7.7

Patch Changes

0.7.7-next.2

Patch Changes

0.7.7-next.1

Patch Changes

0.7.7-next.0

Patch Changes

0.7.6

Patch Changes

0.7.6-next.2

Patch Changes

0.7.6-next.1

Patch Changes

0.7.6-next.0

Patch Changes

0.7.5

Patch Changes

0.7.5-next.2

Patch Changes

0.7.5-next.1

Patch Changes

0.7.5-next.0

Patch Changes

0.7.3

Patch Changes

0.7.3-next.1

Patch Changes

0.7.3-next.0

Patch Changes

0.7.2

Patch Changes

0.7.2-next.3

Patch Changes

0.7.2-next.2

Patch Changes

0.7.2-next.1

Patch Changes

0.7.2-next.0

Patch Changes

0.7.1

Patch Changes

0.7.1-next.1

Patch Changes

0.7.1-next.0

Patch Changes

0.7.0

Minor Changes

  • 46b4a72cee: BREAKING: When defining permission rules, it's now necessary to provide a ZodSchema that specifies the parameters the rule expects. This has been added to help better describe the parameters in the response of the metadata endpoint and to validate the parameters before a rule is executed.

    To help with this, we have also made a change to the API of permission rules. Before, the permission rules toQuery and apply signature expected parameters to be separate arguments, like so...

    createPermissionRule({
      apply: (resource, foo, bar) => true,
      toQuery: (foo, bar) => {},
    });

    The API has now changed to expect the parameters as a single object

    createPermissionRule({
      paramSchema: z.object({
        foo: z.string().describe('Foo value to match'),
        bar: z.string().describe('Bar value to match'),
      }),
      apply: (resource, { foo, bar }) => true,
      toQuery: ({ foo, bar }) => {},
    });

    One final change made is to limit the possible values for a parameter to primitives and arrays of primitives.

Patch Changes

0.7.0-next.2

Minor Changes

  • 46b4a72cee: BREAKING: When defining permission rules, it's now necessary to provide a ZodSchema that specifies the parameters the rule expects. This has been added to help better describe the parameters in the response of the metadata endpoint and to validate the parameters before a rule is executed.

    To help with this, we have also made a change to the API of permission rules. Before, the permission rules toQuery and apply signature expected parameters to be separate arguments, like so...

    createPermissionRule({
      apply: (resource, foo, bar) => true,
      toQuery: (foo, bar) => {},
    });

    The API has now changed to expect the parameters as a single object

    createPermissionRule({
      paramSchema: z.object({
        foo: z.string().describe('Foo value to match'),
        bar: z.string().describe('Bar value to match'),
      }),
      apply: (resource, { foo, bar }) => true,
      toQuery: ({ foo, bar }) => {},
    });

    One final change made is to limit the possible values for a parameter to primitives and arrays of primitives.

Patch Changes

0.6.6-next.1

Patch Changes

0.6.6-next.0

Patch Changes

0.6.5

Patch Changes

0.6.5-next.3

Patch Changes

0.6.5-next.2

Patch Changes

0.6.5-next.1

Patch Changes

0.6.5-next.0

Patch Changes

0.6.4

Patch Changes

0.6.4-next.0

Patch Changes

0.6.3

Patch Changes

0.6.3-next.2

Patch Changes

0.6.3-next.1

Patch Changes

0.6.3-next.0

Patch Changes

0.6.2

Patch Changes

  • 58426f9c0f: Added a new endpoint for aggregating permission metadata from a plugin backend: /.well-known/backstage/permissions/metadata

    By default, the metadata endpoint will return information about the permission rules supported by the plugin. Plugin authors can also provide an optional permissions parameter to createPermissionIntegrationRouter. If provided, these Permission objects will be included in the metadata returned by this endpoint. The permissions parameter will eventually be required in a future breaking change.

  • 8f7b1835df: Updated dependency msw to ^0.41.0.

  • Updated dependencies

0.6.2-next.2

Patch Changes

0.6.2-next.1

Patch Changes

0.6.2-next.0

Patch Changes

0.6.1

Patch Changes

0.6.1-next.1

Patch Changes

0.6.1-next.0

Patch Changes

0.6.0

Minor Changes

  • 8012ac46a0: BREAKING: Stronger typing in PermissionPolicy 🎉.

    Previously, it was entirely the responsibility of the PermissionPolicy author to only return CONDITIONAL decisions for permissions that are associated with a resource, and to return the correct kind of PermissionCondition instances inside the decision. Now, the policy authoring helpers provided in this package now ensure that the decision and permission match.

    For policy authors: rename and adjust api of createConditionExports. Previously, the function returned a factory for creating conditional decisions named createPolicyDecision, which had a couple of drawbacks:

    1. The function always creates a conditional policy decision, but this was not reflected in the name.
    2. Conditional decisions should only ever be returned from PermissionPolicy#handle for resource permissions, but there was nothing in the API that encoded this constraint.

    This change addresses the drawbacks above by making the following changes for policy authors:

    • The createPolicyDecision method has been renamed to createConditionalDecision.
    • Along with conditions, the method now accepts a permission, which must be a ResourcePermission. This is expected to be the handled permission in PermissionPolicy#handle, whose type must first be narrowed using methods like isPermission and isResourcePermission:
    class TestPermissionPolicy implements PermissionPolicy {
      async handle(
        request: PolicyQuery<Permission>,
        _user?: BackstageIdentityResponse,
      ): Promise<PolicyDecision> {
        if (
          // Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
          isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
        ) {
          return createCatalogConditionalDecision(
            request.permission,
            catalogConditions.isEntityOwner(
              _user?.identity.ownershipEntityRefs ?? [],
            ),
          );
        }
    
        return {
          result: AuthorizeResult.ALLOW,
        };

    BREAKING: when creating PermissionRules, provide a resourceType.

    export const isEntityOwner = createCatalogPermissionRule({
      name: 'IS_ENTITY_OWNER',
      description: 'Allow entities owned by the current user',
    +  resourceType: RESOURCE_TYPE_CATALOG_ENTITY,
      apply: (resource: Entity, claims: string[]) => {
        if (!resource.relations) {
          return false;
        }
    
        return resource.relations
          .filter(relation => relation.type === RELATION_OWNED_BY)
          .some(relation => claims.includes(relation.targetRef));
      },
      toQuery: (claims: string[]) => ({
        key: 'relations.ownedBy',
        values: claims,
      }),
    });
  • c98d271466: BREAKING:

    • Rename PolicyAuthorizeQuery to PolicyQuery
    • Remove PolicyDecision, DefinitivePolicyDecision, and ConditionalPolicyDecision. These types are now exported from @backstage/plugin-permission-common
  • 322b69e46a: BREAKING: ServerPermissionClient now implements PermissionEvaluator, which moves out the capabilities for evaluating conditional decisions from authorize() to authorizeConditional() method.

Patch Changes

0.6.0-next.2

Minor Changes

  • 322b69e46a: BREAKING: ServerPermissionClient now implements PermissionEvaluator, which moves out the capabilities for evaluating conditional decisions from authorize() to authorizeConditional() method.

Patch Changes

0.6.0-next.1

Minor Changes

  • 8012ac46a0: BREAKING: Stronger typing in PermissionPolicy 🎉.

    Previously, it was entirely the responsibility of the PermissionPolicy author to only return CONDITIONAL decisions for permissions that are associated with a resource, and to return the correct kind of PermissionCondition instances inside the decision. Now, the policy authoring helpers provided in this package now ensure that the decision and permission match.

    For policy authors: rename and adjust api of createConditionExports. Previously, the function returned a factory for creating conditional decisions named createPolicyDecision, which had a couple of drawbacks:

    1. The function always creates a conditional policy decision, but this was not reflected in the name.
    2. Conditional decisions should only ever be returned from PermissionPolicy#handle for resource permissions, but there was nothing in the API that encoded this constraint.

    This change addresses the drawbacks above by making the following changes for policy authors:

    • The createPolicyDecision method has been renamed to createConditionalDecision.
    • Along with conditions, the method now accepts a permission, which must be a ResourcePermission. This is expected to be the handled permission in PermissionPolicy#handle, whose type must first be narrowed using methods like isPermission and isResourcePermission:
    class TestPermissionPolicy implements PermissionPolicy {
      async handle(
        request: PolicyQuery<Permission>,
        _user?: BackstageIdentityResponse,
      ): Promise<PolicyDecision> {
        if (
          // Narrow type of `request.permission` to `ResourcePermission<'catalog-entity'>
          isResourcePermission(request.permission, RESOURCE_TYPE_CATALOG_ENTITY)
        ) {
          return createCatalogConditionalDecision(
            request.permission,
            catalogConditions.isEntityOwner(
              _user?.identity.ownershipEntityRefs ?? [],
            ),
          );
        }
    
        return {
          result: AuthorizeResult.ALLOW,
        };

    BREAKING: when creating PermissionRules, provide a resourceType.

    export const isEntityOwner = createCatalogPermissionRule({
      name: 'IS_ENTITY_OWNER',
      description: 'Allow entities owned by the current user',
    +  resourceType: RESOURCE_TYPE_CATALOG_ENTITY,
      apply: (resource: Entity, claims: string[]) => {
        if (!resource.relations) {
          return false;
        }
    
        return resource.relations
          .filter(relation => relation.type === RELATION_OWNED_BY)
          .some(relation => claims.includes(relation.targetRef));
      },
      toQuery: (claims: string[]) => ({
        key: 'relations.ownedBy',
        values: claims,
      }),
    });
  • c98d271466: BREAKING:

    • Rename PolicyAuthorizeQuery to PolicyQuery
    • Remove PolicyDecision, DefinitivePolicyDecision, and ConditionalPolicyDecision. These types are now exported from @backstage/plugin-permission-common

Patch Changes

0.5.6-next.0

Patch Changes

0.5.5

Patch Changes

0.5.4

Patch Changes

0.5.4-next.0

Patch Changes

0.5.3

Patch Changes

0.5.2

Patch Changes

0.5.1

Patch Changes

0.5.0

Minor Changes

  • 8c646beb24: BREAKING PermissionCriteria now requires at least one condition in anyOf and allOf arrays. This addresses some ambiguous behavior outlined in #9280.

Patch Changes

0.4.3

Patch Changes

0.4.3-next.0

Patch Changes

0.4.2

Patch Changes

0.4.2-next.1

Patch Changes

0.4.2-next.0

Patch Changes

0.4.1

Patch Changes

0.4.0

Minor Changes

  • 0ae4f4cc82: BREAKING: PolicyAuthorizeRequest type has been renamed to PolicyAuthorizeQuery. BREAKING: Update to use renamed request and response types from @backstage/plugin-permission-common.

Patch Changes

0.4.0-next.0

Minor Changes

  • 0ae4f4cc82: BREAKING: PolicyAuthorizeRequest type has been renamed to PolicyAuthorizeQuery. BREAKING: Update to use renamed request and response types from @backstage/plugin-permission-common.

Patch Changes

0.3.0

Minor Changes

  • 419ca637c0: Optimizations to the integration between the permission backend and plugin-backends using createPermissionIntegrationRouter:

    • The permission backend already supported batched requests to authorize, but would make calls to plugin backend to apply conditions serially. Now, after applying the policy for each authorization request, the permission backend makes a single batched /apply-conditions request to each plugin backend referenced in policy decisions.
    • The getResource method accepted by createPermissionIntegrationRouter has been replaced with getResources, to allow consumers to make batch requests to upstream data stores. When /apply-conditions is called with a batch of requests, all required resources are requested in a single invocation of getResources.

    Plugin owners consuming createPermissionIntegrationRouter should replace the getResource method in the options with a getResources method, accepting an array of resourceRefs, and returning an array of the corresponding resources.

Patch Changes

0.2.3

Patch Changes

0.2.2

Patch Changes

  • 2f8a9b665f: Add ServerPermissionClient, which implements PermissionAuthorizer from @backstage/plugin-permission-common. This implementation skips authorization entirely when the supplied token is a valid backend-to-backend token, thereby allowing backend-to-backend systems to communicate without authorization.

    The ServerPermissionClient should always be used over the standard PermissionClient in plugin backends.

  • Updated dependencies

0.2.1

Patch Changes

  • dcd1a0c3f4: Minor improvement to the API reports, by not unpacking arguments directly
  • a036b65c2f: Updated to use the new BackstageIdentityResponse type from @backstage/plugin-auth-backend.

    The BackstageIdentityResponse type is backwards compatible with the BackstageIdentity, and provides an additional identity field with the claims of the user.

  • Updated dependencies

0.2.0

Minor Changes

  • e7851efa9e: Rename and adjust permission policy return type to reduce nesting
  • 450ca92330: Change route used for integration between the authorization framework and other plugin backends to use the /.well-known prefix.

Patch Changes

0.1.0

Minor Changes

  • 44b46644d9: New package containing common permission and authorization utilities for backend plugins. For more information, see the authorization PRFC.

Patch Changes