Invert based on feedback
Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
---
|
||||
id: index--new
|
||||
id: index--old
|
||||
title: Authentication in Backstage
|
||||
description: Introduction to authentication in Backstage
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the new frontend system](../frontend-system/index.md). If you are on the old frontend system you may want to read [its own article](./index.md) instead.
|
||||
This documentation is written for the old frontend system. If you are on the [new frontend system](../frontend-system/index.md) you may want to read [its own article](./index.md) instead.
|
||||
:::
|
||||
|
||||
The authentication system in Backstage serves two distinct purposes: sign-in and identification of users, as well as delegating access to third-party resources. It is possible to configure Backstage to have any number of authentication providers, but only one of these will typically be used for sign-in, with the rest being used to provide access to external resources.
|
||||
The authentication system in Backstage serves two distinct purposes: sign-in and
|
||||
identification of users, as well as delegating access to third-party resources. It is possible to
|
||||
configure Backstage to have any number of authentication providers, but only
|
||||
one of these will typically be used for sign-in, with the rest being used to provide
|
||||
access to external resources.
|
||||
|
||||
:::note Note
|
||||
|
||||
Identity management and the Sign-In page in Backstage will only block external access when using the new backend system, without setting `backend.auth.dangerouslyDisableDefaultAuthPolicy` in configuration. Even so, the frontend bundle is not protected from external access, protecting it requires the use of the [experimental public entry point](https://backstage.io/docs/tutorials/enable-public-entry/). You can learn more about this in the [Threat Model](../overview/threat-model.md#operator-responsibilities).
|
||||
Identity management and the Sign-In page in Backstage will block external access by default, without setting `backend.auth.dangerouslyDisableDefaultAuthPolicy` in configuration. Even so, the frontend bundle is not protected from external access, protecting it requires the use of the [experimental public entry point](https://backstage.io/docs/tutorials/enable-public-entry/). You can learn more about this in the [Threat Model](../overview/threat-model.md#operator-responsibilities).
|
||||
|
||||
:::
|
||||
|
||||
@@ -37,11 +41,13 @@ Backstage comes with many common authentication providers in the core library:
|
||||
- [OpenShift](openshift/provider.md)
|
||||
- [VMware Cloud](vmware-cloud/provider.md)
|
||||
|
||||
These built-in providers handle the authentication flow for a particular service, including required scopes, callbacks, etc. These providers are each added to a Backstage app in a similar way.
|
||||
These built-in providers handle the authentication flow for a particular service, including required scopes, callbacks, etc. These providers are each added to a
|
||||
Backstage app in a similar way.
|
||||
|
||||
## Configuring Authentication Providers
|
||||
|
||||
Each built-in provider has a configuration block under the `auth` section of `app-config.yaml`. For example, the GitHub provider:
|
||||
Each built-in provider has a configuration block under the `auth` section of
|
||||
`app-config.yaml`. For example, the GitHub provider:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
@@ -53,66 +59,66 @@ auth:
|
||||
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
|
||||
```
|
||||
|
||||
See the documentation for a particular provider to see what configuration is needed.
|
||||
See the documentation for a particular provider to see what configuration is
|
||||
needed.
|
||||
|
||||
The `providers` key may have several authentication providers if multiple authentication methods are supported. Each provider may also have configuration for different authentication environments (development, production, etc). This allows a single auth backend to serve multiple environments, such as running a local frontend against a deployed backend. The provider configuration matching the local `auth.environment` setting will be selected.
|
||||
The `providers` key may have several authentication providers if multiple
|
||||
authentication methods are supported. Each provider may also have configuration
|
||||
for different authentication environments (development, production, etc). This
|
||||
allows a single auth backend to serve multiple environments, such as running a
|
||||
local frontend against a deployed backend. The provider configuration matching
|
||||
the local `auth.environment` setting will be selected.
|
||||
|
||||
## Sign-In Configuration
|
||||
|
||||
Using an authentication provider for sign-in is something you need to configure both in the frontend app as well as the `auth` backend plugin. For information on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md). The rest of this section will focus on how to configure sign-in for the frontend app.
|
||||
Using an authentication provider for sign-in is something you need to configure
|
||||
both in the frontend app as well as the `auth` backend plugin. For information
|
||||
on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md).
|
||||
The rest of this section will focus on how to configure sign-in for the frontend app.
|
||||
|
||||
Sign-in is configured by providing a custom `SignInPage` app component. It will be rendered before any other routes in the app and is responsible for providing the identity of the current user. The `SignInPage` can render any number of pages and components, or just blank space with logic running in the background. In the end, however, it must provide a valid Backstage user identity through the `onSignInSuccess` callback prop, at which point the rest of the app is rendered.
|
||||
Sign-in is configured by providing a custom `SignInPage` app component. It will be
|
||||
rendered before any other routes in the app and is responsible for providing the
|
||||
identity of the current user. The `SignInPage` can render any number of pages and
|
||||
components, or just blank space with logic running in the background. In the end, however, it must provide a valid Backstage user identity through the `onSignInSuccess`
|
||||
callback prop, at which point the rest of the app is rendered.
|
||||
|
||||
If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`, which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions.
|
||||
If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`,
|
||||
which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions.
|
||||
|
||||
The following example for GitHub shows the additions needed to `packages/app/src/App.tsx`, and can be adapted to any of the built-in providers:
|
||||
The following example for GitHub shows the additions needed to `packages/app/src/App.tsx`,
|
||||
and can be adapted to any of the built-in providers:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { createApp } from '@backstage/frontend-defaults';
|
||||
import catalogPlugin from '@backstage/plugin-catalog/alpha';
|
||||
import { navModule } from './modules/nav';
|
||||
|
||||
/* highlight-add-start */
|
||||
import { githubAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
(
|
||||
<SignInPage
|
||||
{...props}
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
/* highlight-add-end */
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
/* highlight-add-start */
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
/* highlight-add-end */
|
||||
],
|
||||
const app = createApp({
|
||||
/* highlight-add-start */
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
auto
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
/* highlight-add-end */
|
||||
// ..
|
||||
});
|
||||
```
|
||||
|
||||
:::note Note
|
||||
|
||||
You can configure sign-in to use a redirect flow with no pop-up by adding `enableExperimentalRedirectFlow: true` to the root of your `app-config.yaml`
|
||||
You can configure sign-in to use a redirect flow with no pop-up by adding
|
||||
`enableExperimentalRedirectFlow: true` to the root of your `app-config.yaml`
|
||||
|
||||
:::
|
||||
|
||||
@@ -121,44 +127,26 @@ You can configure sign-in to use a redirect flow with no pop-up by adding `enabl
|
||||
You can also use the `providers` prop to enable multiple sign-in methods, for example to allow guest access:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { githubAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
(
|
||||
<SignInPage
|
||||
{...props}
|
||||
/* highlight-add-start */
|
||||
providers={[
|
||||
'guest',
|
||||
{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
},
|
||||
]}
|
||||
/* highlight-add-end */
|
||||
/>
|
||||
),
|
||||
const app = createApp({
|
||||
/* highlight-add-start */
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
providers={[
|
||||
'guest',
|
||||
{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
/* highlight-add-start */
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
/* highlight-add-end */
|
||||
],
|
||||
/* highlight-add-end */
|
||||
// ..
|
||||
});
|
||||
```
|
||||
|
||||
@@ -172,14 +160,10 @@ import {
|
||||
githubAuthApiRef,
|
||||
useApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
/* highlight-add-start */
|
||||
loader: async () => props => {
|
||||
const app = createApp({
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
const configApi = useApi(configApiRef);
|
||||
if (configApi.getString('auth.environment') === 'development') {
|
||||
return (
|
||||
@@ -197,64 +181,47 @@ const signInPage = SignInPageBlueprint.make({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SignInPage
|
||||
{...props}
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
id: 'google-auth-provider',
|
||||
title: 'Google',
|
||||
message: 'Sign In using Google',
|
||||
apiRef: googleAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
/* highlight-add-end */
|
||||
},
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
/* highlight-add-start */
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
/* highlight-add-end */
|
||||
],
|
||||
// ..
|
||||
});
|
||||
```
|
||||
|
||||
## Sign-In with Proxy Providers
|
||||
|
||||
Some auth providers are so-called "proxy" providers, meaning they're meant to be used behind an authentication proxy. Examples of these are [Amazon Application Load Balancer](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md), [Azure EasyAuth](./microsoft/azure-easyauth.md), [Cloudflare Access](./cloudflare/provider.md), [Google Identity-Aware Proxy](./google/gcp-iap-auth.md) and [OAuth2 Proxy](./oauth2-proxy/provider.md).
|
||||
Some auth providers are so-called "proxy" providers, meaning they're meant to be used
|
||||
behind an authentication proxy. Examples of these are
|
||||
[Amazon Application Load Balancer](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md),
|
||||
[Azure EasyAuth](./microsoft/azure-easyauth.md),
|
||||
[Cloudflare Access](./cloudflare/provider.md),
|
||||
[Google Identity-Aware Proxy](./google/gcp-iap-auth.md)
|
||||
and [OAuth2 Proxy](./oauth2-proxy/provider.md).
|
||||
|
||||
When using a proxy provider, you'll end up wanting to use a different sign-in page, as there is no need for further user interaction once you've signed in towards the proxy. All the sign-in page needs to do is call the `/refresh` endpoint of the auth providers to get the existing session, which is exactly what the `ProxiedSignInPage` does. The only thing you need to do to configure the `ProxiedSignInPage` is to pass the ID of the provider like this:
|
||||
When using a proxy provider, you'll end up wanting to use a different sign-in page, as
|
||||
there is no need for further user interaction once you've signed in towards the proxy.
|
||||
All the sign-in page needs to do is call the `/refresh` endpoint of the auth providers
|
||||
to get the existing session, which is exactly what the `ProxiedSignInPage` does. The only
|
||||
thing you need to do to configure the `ProxiedSignInPage` is to pass the ID of the provider like this:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import { ProxiedSignInPage } from '@backstage/core-components';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
<ProxiedSignInPage {...props} provider="awsalb" />,
|
||||
const app = createApp({
|
||||
components: {
|
||||
SignInPage: props => <ProxiedSignInPage {...props} provider="awsalb" />,
|
||||
},
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
],
|
||||
// ..
|
||||
});
|
||||
```
|
||||
|
||||
@@ -286,20 +253,18 @@ Headers can also be returned in an async manner:
|
||||
/>
|
||||
```
|
||||
|
||||
A downside of this method is that it can be cumbersome to set up for local development. As a workaround for this, it's possible to dynamically select the sign-in page based on what environment the app is running in and then use a different sign-in method for local development, if one is needed at all. Depending on the exact setup, one might choose to select the sign-in method based on the `process.env.NODE_ENV` environment variable, by checking the `hostname` of the current location, or by accessing the configuration API to read a configuration value. For example:
|
||||
A downside of this method is that it can be cumbersome to set up for local development.
|
||||
As a workaround for this, it's possible to dynamically select the sign-in page based on
|
||||
what environment the app is running in and then use a different sign-in method for local
|
||||
development, if one is needed at all. Depending on the exact setup, one might choose to
|
||||
select the sign-in method based on the `process.env.NODE_ENV` environment variable,
|
||||
by checking the `hostname` of the current location, or by accessing the configuration API
|
||||
to read a configuration value. For example:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { configApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { ProxiedSignInPage, SignInPage } from '@backstage/core-components';
|
||||
import {
|
||||
createFrontendModule,
|
||||
googleAuthApiRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props => {
|
||||
const app = createApp({
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
const configApi = useApi(configApiRef);
|
||||
if (configApi.getString('auth.environment') === 'development') {
|
||||
return (
|
||||
@@ -314,55 +279,93 @@ const signInPage = SignInPageBlueprint.make({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <ProxiedSignInPage {...props} provider="gcpiap" />;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
],
|
||||
// ..
|
||||
});
|
||||
```
|
||||
|
||||
When using multiple auth providers like this, it's important that you configure the different sign-in resolvers so that they resolve to the same identity regardless of the method used.
|
||||
When using multiple auth providers like this, it's important that you configure the different
|
||||
sign-in resolvers so that they resolve to the same identity regardless of the method used.
|
||||
|
||||
## Scaffolder Configuration (Software Templates)
|
||||
|
||||
If you want to use the authentication capabilities of the [Repository Picker](../features/software-templates/writing-templates.md#the-repository-picker) inside your software templates, you will need to configure the [`ScmAuthApi`](https://backstage.io/api/stable/interfaces/_backstage_integration-react.ScmAuthApi.html) alongside your authentication provider. It is an API used to authenticate towards different SCM systems in a generic way, based on what resource is being accessed.
|
||||
|
||||
To set it up, you'll need to add an API factory entry to `packages/app/src/apis.ts`. The example below sets up the `ScmAuthApi` for an already configured GitLab authentication provider:
|
||||
|
||||
```ts title="packages/app/src/apis.ts"
|
||||
createApiFactory({
|
||||
api: scmAuthApiRef,
|
||||
deps: {
|
||||
gitlabAuthApi: gitlabAuthApiRef,
|
||||
},
|
||||
factory: ({ gitlabAuthApi }) => ScmAuth.forGitlab(gitlabAuthApi),
|
||||
});
|
||||
```
|
||||
|
||||
In case you are using a custom authentication providers, you might need to add a [custom `ScmAuthApi` implementation](./index.md#custom-scmauthapi-implementation).
|
||||
|
||||
## For Plugin Developers
|
||||
|
||||
The Backstage frontend core APIs provide a set of Utility APIs for plugin developers to use, both to access the user identity as well as third-party resources.
|
||||
The Backstage frontend core APIs provide a set of Utility APIs for plugin developers
|
||||
to use, both to access the user identity as well as third-party resources.
|
||||
|
||||
### Identity for Plugin Developers
|
||||
|
||||
For plugin developers, there is one main touchpoint for accessing the user identity: the `IdentityApi` exported by `@backstage/core-plugin-api` via the `identityApiRef`.
|
||||
For plugin developers, there is one main touchpoint for accessing the user identity: the
|
||||
`IdentityApi` exported by `@backstage/core-plugin-api` via the `identityApiRef`.
|
||||
|
||||
The `IdentityApi` gives access to the signed-in user's identity in the frontend. It provides access to the user's entity reference, lightweight profile information, and a Backstage token that identifies the user when making authenticated calls within Backstage.
|
||||
The `IdentityApi` gives access to the signed-in user's identity in the frontend.
|
||||
It provides access to the user's entity reference, lightweight profile information, and
|
||||
a Backstage token that identifies the user when making authenticated calls within Backstage.
|
||||
|
||||
When making calls to backend plugins, we recommend that the `FetchApi` is used, which is exported via the `fetchApiRef` from `@backstage/core-plugin-api`. The `FetchApi` will automatically include a Backstage token in the request, meaning there is no need to interact directly with the `IdentityApi`.
|
||||
When making calls to backend plugins, we recommend that the `FetchApi` is used, which
|
||||
is exported via the `fetchApiRef` from `@backstage/core-plugin-api`. The `FetchApi` will
|
||||
automatically include a Backstage token in the request, meaning there is no need
|
||||
to interact directly with the `IdentityApi`.
|
||||
|
||||
### Accessing Third Party Resources
|
||||
|
||||
A common pattern for talking to third-party services in Backstage is user-to-server requests, where short-lived OAuth Access Tokens are requested by plugins to authenticate calls to external services. These calls can be made either directly to the services or through a backend plugin or service.
|
||||
A common pattern for talking to third-party services in Backstage is
|
||||
user-to-server requests, where short-lived OAuth Access Tokens are requested by
|
||||
plugins to authenticate calls to external services. These calls can be made
|
||||
either directly to the services or through a backend plugin or service.
|
||||
|
||||
By relying on user-to-server calls, we keep the coupling between the frontend and backend low and provide a much lower barrier for plugins to make use of third party services. This is in comparison to, for example, a session-based system where access tokens are stored server-side. Such a solution would require a much deeper coupling between the auth backend plugin, its session storage, and other backend plugins or separate services. A goal of Backstage is to make it as easy as possible to create new plugins, and an auth solution based on user-to-server OAuth helps in that regard.
|
||||
By relying on user-to-server calls, we keep the coupling between the frontend and
|
||||
backend low and provide a much lower barrier for plugins to make use of third
|
||||
party services. This is in comparison to, for example, a session-based system
|
||||
where access tokens are stored server-side. Such a solution would require a much
|
||||
deeper coupling between the auth backend plugin, its session storage, and other
|
||||
backend plugins or separate services. A goal of Backstage is to make it as easy
|
||||
as possible to create new plugins, and an auth solution based on user-to-server
|
||||
OAuth helps in that regard.
|
||||
|
||||
The method with which frontend plugins request access to third-party services is through [Utility APIs](../api/utility-apis.md) for each service provider. These are all suffixed with `*AuthApiRef`, for example `githubAuthApiRef`. For a full list of providers, see the [@backstage/core-plugin-api](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.index.html#alertapiref) reference.
|
||||
The method with which frontend plugins request access to third-party services is
|
||||
through [Utility APIs](../api/utility-apis.md) for each service provider. These
|
||||
are all suffixed with `*AuthApiRef`, for example `githubAuthApiRef`. For a
|
||||
full list of providers, see the
|
||||
[@backstage/core-plugin-api](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.index.html#alertapiref) reference.
|
||||
|
||||
## Custom Authentication Provider
|
||||
|
||||
There are generic authentication providers for OAuth2 and SAML. These can reduce the amount of code needed to implement a custom authentication provider that adheres to these standards.
|
||||
There are generic authentication providers for OAuth2 and SAML. These can reduce
|
||||
the amount of code needed to implement a custom authentication provider that
|
||||
adheres to these standards.
|
||||
|
||||
Backstage uses [Passport](http://www.passportjs.org/) under the hood, which has a wide library of authentication strategies for different providers. See [Add authentication provider](add-auth-provider.md) for details on adding a new Passport-supported authentication method.
|
||||
Backstage uses [Passport](http://www.passportjs.org/) under the hood, which has
|
||||
a wide library of authentication strategies for different providers. See
|
||||
[Add authentication provider](add-auth-provider.md) for details on adding a new
|
||||
Passport-supported authentication method.
|
||||
|
||||
## Custom ScmAuthApi Implementation
|
||||
|
||||
The default `ScmAuthApi` provides integrations for `github`, `gitlab`, `azure` (Azure DevOps), `bitbucketServer` and `bitbucketCloud` and is created and registered automatically for you by the New Frontend System.
|
||||
The default `ScmAuthApi` provides integrations for `github`, `gitlab`, `azure` and `bitbucket` and is created by the following code in `packages/app/src/apis.ts`:
|
||||
|
||||
```ts
|
||||
ScmAuth.createDefaultApiFactory();
|
||||
```
|
||||
|
||||
If you require only a subset of these integrations, then you will need a custom implementation of the [`ScmAuthApi`](https://backstage.io/api/stable/interfaces/_backstage_integration-react.ScmAuthApi.html). It is an API used to authenticate different SCM systems generically, based on what resource is being accessed, and is used for example, by the Scaffolder (Software Templates) and Catalog Import plugins.
|
||||
|
||||
@@ -462,7 +465,7 @@ providerFactories: {
|
||||
},
|
||||
```
|
||||
|
||||
In the new backend system you can leverage the `authProvidersExtensionPoint` for this:
|
||||
You can leverage the `authProvidersExtensionPoint` for this:
|
||||
|
||||
```ts
|
||||
// your-auth-plugin-module.ts
|
||||
@@ -500,9 +503,13 @@ backend.add(gheAuth);
|
||||
|
||||
## Configuring token issuers
|
||||
|
||||
By default, the Backstage authentication backend generates and manages its own signing keys automatically for any issued Backstage tokens. However, these keys have a short lifetime and do not persist after instance restarts.
|
||||
By default, the Backstage authentication backend generates and manages its own signing keys automatically for any issued
|
||||
Backstage tokens. However, these keys have a short lifetime and do not persist after instance restarts.
|
||||
|
||||
Alternatively, users can provide their own public and private key files to sign issued tokens. This is beneficial in scenarios where the token verification implementation aggressively caches the list of keys, and doesn't attempt to fetch new ones even if they encounter an unknown key id. To enable this feature add the following configuration to your config file:
|
||||
Alternatively, users can provide their own public and private key files to sign issued tokens. This is beneficial in
|
||||
scenarios where the token verification implementation aggressively caches the list of keys, and doesn't attempt to fetch
|
||||
new ones even if they encounter an unknown key id. To enable this feature add the following configuration to your config
|
||||
file:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
@@ -519,7 +526,9 @@ auth:
|
||||
- keyId: ...
|
||||
```
|
||||
|
||||
The private key should be stored in the PKCS#8 format. The public key should be stored in the SPKI format. You can generate the public/private key pair, using openssl and the ES256 algorithm by performing the following steps:
|
||||
The private key should be stored in the PKCS#8 format. The public key should be stored in the SPKI format.
|
||||
You can generate the public/private key pair, using openssl and the ES256 algorithm by performing the following
|
||||
steps:
|
||||
|
||||
Generate a private key using the ES256 algorithm
|
||||
|
||||
+167
-176
@@ -5,18 +5,14 @@ description: Introduction to authentication in Backstage
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for the old frontend system. If you are on the [new frontend system](../frontend-system/index.md) you may want to read [its own article](./index--new.md) instead.
|
||||
This documentation is written for [the new frontend system](../frontend-system/index.md). If you are on the old frontend system you may want to read [its own article](./index--old.md) instead.
|
||||
:::
|
||||
|
||||
The authentication system in Backstage serves two distinct purposes: sign-in and
|
||||
identification of users, as well as delegating access to third-party resources. It is possible to
|
||||
configure Backstage to have any number of authentication providers, but only
|
||||
one of these will typically be used for sign-in, with the rest being used to provide
|
||||
access to external resources.
|
||||
The authentication system in Backstage serves two distinct purposes: sign-in and identification of users, as well as delegating access to third-party resources. It is possible to configure Backstage to have any number of authentication providers, but only one of these will typically be used for sign-in, with the rest being used to provide access to external resources.
|
||||
|
||||
:::note Note
|
||||
|
||||
Identity management and the Sign-In page in Backstage will block external access by default, without setting `backend.auth.dangerouslyDisableDefaultAuthPolicy` in configuration. Even so, the frontend bundle is not protected from external access, protecting it requires the use of the [experimental public entry point](https://backstage.io/docs/tutorials/enable-public-entry/). You can learn more about this in the [Threat Model](../overview/threat-model.md#operator-responsibilities).
|
||||
Identity management and the Sign-In page in Backstage will only block external access when using the new backend system, without setting `backend.auth.dangerouslyDisableDefaultAuthPolicy` in configuration. Even so, the frontend bundle is not protected from external access, protecting it requires the use of the [experimental public entry point](https://backstage.io/docs/tutorials/enable-public-entry/). You can learn more about this in the [Threat Model](../overview/threat-model.md#operator-responsibilities).
|
||||
|
||||
:::
|
||||
|
||||
@@ -41,13 +37,11 @@ Backstage comes with many common authentication providers in the core library:
|
||||
- [OpenShift](openshift/provider.md)
|
||||
- [VMware Cloud](vmware-cloud/provider.md)
|
||||
|
||||
These built-in providers handle the authentication flow for a particular service, including required scopes, callbacks, etc. These providers are each added to a
|
||||
Backstage app in a similar way.
|
||||
These built-in providers handle the authentication flow for a particular service, including required scopes, callbacks, etc. These providers are each added to a Backstage app in a similar way.
|
||||
|
||||
## Configuring Authentication Providers
|
||||
|
||||
Each built-in provider has a configuration block under the `auth` section of
|
||||
`app-config.yaml`. For example, the GitHub provider:
|
||||
Each built-in provider has a configuration block under the `auth` section of `app-config.yaml`. For example, the GitHub provider:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
@@ -59,66 +53,66 @@ auth:
|
||||
clientSecret: ${AUTH_GITHUB_CLIENT_SECRET}
|
||||
```
|
||||
|
||||
See the documentation for a particular provider to see what configuration is
|
||||
needed.
|
||||
See the documentation for a particular provider to see what configuration is needed.
|
||||
|
||||
The `providers` key may have several authentication providers if multiple
|
||||
authentication methods are supported. Each provider may also have configuration
|
||||
for different authentication environments (development, production, etc). This
|
||||
allows a single auth backend to serve multiple environments, such as running a
|
||||
local frontend against a deployed backend. The provider configuration matching
|
||||
the local `auth.environment` setting will be selected.
|
||||
The `providers` key may have several authentication providers if multiple authentication methods are supported. Each provider may also have configuration for different authentication environments (development, production, etc). This allows a single auth backend to serve multiple environments, such as running a local frontend against a deployed backend. The provider configuration matching the local `auth.environment` setting will be selected.
|
||||
|
||||
## Sign-In Configuration
|
||||
|
||||
Using an authentication provider for sign-in is something you need to configure
|
||||
both in the frontend app as well as the `auth` backend plugin. For information
|
||||
on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md).
|
||||
The rest of this section will focus on how to configure sign-in for the frontend app.
|
||||
Using an authentication provider for sign-in is something you need to configure both in the frontend app as well as the `auth` backend plugin. For information on how to configure the backend app, see [Sign-in Identities and Resolvers](./identity-resolver.md). The rest of this section will focus on how to configure sign-in for the frontend app.
|
||||
|
||||
Sign-in is configured by providing a custom `SignInPage` app component. It will be
|
||||
rendered before any other routes in the app and is responsible for providing the
|
||||
identity of the current user. The `SignInPage` can render any number of pages and
|
||||
components, or just blank space with logic running in the background. In the end, however, it must provide a valid Backstage user identity through the `onSignInSuccess`
|
||||
callback prop, at which point the rest of the app is rendered.
|
||||
Sign-in is configured by providing a custom `SignInPage` app component. It will be rendered before any other routes in the app and is responsible for providing the identity of the current user. The `SignInPage` can render any number of pages and components, or just blank space with logic running in the background. In the end, however, it must provide a valid Backstage user identity through the `onSignInSuccess` callback prop, at which point the rest of the app is rendered.
|
||||
|
||||
If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`,
|
||||
which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions.
|
||||
If you want to, you can use the `SignInPage` component that is provided by `@backstage/core-components`, which takes either a `provider` or `providers` (array) prop of `SignInProviderConfig` definitions.
|
||||
|
||||
The following example for GitHub shows the additions needed to `packages/app/src/App.tsx`,
|
||||
and can be adapted to any of the built-in providers:
|
||||
The following example for GitHub shows the additions needed to `packages/app/src/App.tsx`, and can be adapted to any of the built-in providers:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { createApp } from '@backstage/frontend-defaults';
|
||||
import catalogPlugin from '@backstage/plugin-catalog/alpha';
|
||||
import { navModule } from './modules/nav';
|
||||
|
||||
/* highlight-add-start */
|
||||
import { githubAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
(
|
||||
<SignInPage
|
||||
{...props}
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
/* highlight-add-end */
|
||||
|
||||
const app = createApp({
|
||||
/* highlight-add-start */
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
auto
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
/* highlight-add-end */
|
||||
// ..
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
/* highlight-add-start */
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
/* highlight-add-end */
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
:::note Note
|
||||
|
||||
You can configure sign-in to use a redirect flow with no pop-up by adding
|
||||
`enableExperimentalRedirectFlow: true` to the root of your `app-config.yaml`
|
||||
You can configure sign-in to use a redirect flow with no pop-up by adding `enableExperimentalRedirectFlow: true` to the root of your `app-config.yaml`
|
||||
|
||||
:::
|
||||
|
||||
@@ -127,26 +121,44 @@ You can configure sign-in to use a redirect flow with no pop-up by adding
|
||||
You can also use the `providers` prop to enable multiple sign-in methods, for example to allow guest access:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
const app = createApp({
|
||||
/* highlight-add-start */
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
providers={[
|
||||
'guest',
|
||||
{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
),
|
||||
import { githubAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
(
|
||||
<SignInPage
|
||||
{...props}
|
||||
/* highlight-add-start */
|
||||
providers={[
|
||||
'guest',
|
||||
{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
},
|
||||
]}
|
||||
/* highlight-add-end */
|
||||
/>
|
||||
),
|
||||
},
|
||||
/* highlight-add-end */
|
||||
// ..
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
/* highlight-add-start */
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
/* highlight-add-end */
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -160,10 +172,14 @@ import {
|
||||
githubAuthApiRef,
|
||||
useApi,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
const app = createApp({
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
/* highlight-add-start */
|
||||
loader: async () => props => {
|
||||
const configApi = useApi(configApiRef);
|
||||
if (configApi.getString('auth.environment') === 'development') {
|
||||
return (
|
||||
@@ -181,47 +197,64 @@ const app = createApp({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SignInPage
|
||||
{...props}
|
||||
provider={{
|
||||
id: 'google-auth-provider',
|
||||
title: 'Google',
|
||||
message: 'Sign In using Google',
|
||||
apiRef: googleAuthApiRef,
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
/* highlight-add-end */
|
||||
},
|
||||
// ..
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
/* highlight-add-start */
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
/* highlight-add-end */
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## Sign-In with Proxy Providers
|
||||
|
||||
Some auth providers are so-called "proxy" providers, meaning they're meant to be used
|
||||
behind an authentication proxy. Examples of these are
|
||||
[Amazon Application Load Balancer](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md),
|
||||
[Azure EasyAuth](./microsoft/azure-easyauth.md),
|
||||
[Cloudflare Access](./cloudflare/provider.md),
|
||||
[Google Identity-Aware Proxy](./google/gcp-iap-auth.md)
|
||||
and [OAuth2 Proxy](./oauth2-proxy/provider.md).
|
||||
Some auth providers are so-called "proxy" providers, meaning they're meant to be used behind an authentication proxy. Examples of these are [Amazon Application Load Balancer](https://github.com/backstage/backstage/blob/master/contrib/docs/tutorials/aws-alb-aad-oidc-auth.md), [Azure EasyAuth](./microsoft/azure-easyauth.md), [Cloudflare Access](./cloudflare/provider.md), [Google Identity-Aware Proxy](./google/gcp-iap-auth.md) and [OAuth2 Proxy](./oauth2-proxy/provider.md).
|
||||
|
||||
When using a proxy provider, you'll end up wanting to use a different sign-in page, as
|
||||
there is no need for further user interaction once you've signed in towards the proxy.
|
||||
All the sign-in page needs to do is call the `/refresh` endpoint of the auth providers
|
||||
to get the existing session, which is exactly what the `ProxiedSignInPage` does. The only
|
||||
thing you need to do to configure the `ProxiedSignInPage` is to pass the ID of the provider like this:
|
||||
When using a proxy provider, you'll end up wanting to use a different sign-in page, as there is no need for further user interaction once you've signed in towards the proxy. All the sign-in page needs to do is call the `/refresh` endpoint of the auth providers to get the existing session, which is exactly what the `ProxiedSignInPage` does. The only thing you need to do to configure the `ProxiedSignInPage` is to pass the ID of the provider like this:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import { ProxiedSignInPage } from '@backstage/core-components';
|
||||
|
||||
const app = createApp({
|
||||
components: {
|
||||
SignInPage: props => <ProxiedSignInPage {...props} provider="awsalb" />,
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
<ProxiedSignInPage {...props} provider="awsalb" />,
|
||||
},
|
||||
// ..
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
@@ -253,18 +286,20 @@ Headers can also be returned in an async manner:
|
||||
/>
|
||||
```
|
||||
|
||||
A downside of this method is that it can be cumbersome to set up for local development.
|
||||
As a workaround for this, it's possible to dynamically select the sign-in page based on
|
||||
what environment the app is running in and then use a different sign-in method for local
|
||||
development, if one is needed at all. Depending on the exact setup, one might choose to
|
||||
select the sign-in method based on the `process.env.NODE_ENV` environment variable,
|
||||
by checking the `hostname` of the current location, or by accessing the configuration API
|
||||
to read a configuration value. For example:
|
||||
A downside of this method is that it can be cumbersome to set up for local development. As a workaround for this, it's possible to dynamically select the sign-in page based on what environment the app is running in and then use a different sign-in method for local development, if one is needed at all. Depending on the exact setup, one might choose to select the sign-in method based on the `process.env.NODE_ENV` environment variable, by checking the `hostname` of the current location, or by accessing the configuration API to read a configuration value. For example:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
const app = createApp({
|
||||
components: {
|
||||
SignInPage: props => {
|
||||
import { configApiRef, useApi } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { ProxiedSignInPage, SignInPage } from '@backstage/core-components';
|
||||
import {
|
||||
createFrontendModule,
|
||||
googleAuthApiRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props => {
|
||||
const configApi = useApi(configApiRef);
|
||||
if (configApi.getString('auth.environment') === 'development') {
|
||||
return (
|
||||
@@ -279,93 +314,55 @@ const app = createApp({
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <ProxiedSignInPage {...props} provider="gcpiap" />;
|
||||
},
|
||||
},
|
||||
// ..
|
||||
});
|
||||
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
When using multiple auth providers like this, it's important that you configure the different
|
||||
sign-in resolvers so that they resolve to the same identity regardless of the method used.
|
||||
|
||||
## Scaffolder Configuration (Software Templates)
|
||||
|
||||
If you want to use the authentication capabilities of the [Repository Picker](../features/software-templates/writing-templates.md#the-repository-picker) inside your software templates, you will need to configure the [`ScmAuthApi`](https://backstage.io/api/stable/interfaces/_backstage_integration-react.ScmAuthApi.html) alongside your authentication provider. It is an API used to authenticate towards different SCM systems in a generic way, based on what resource is being accessed.
|
||||
|
||||
To set it up, you'll need to add an API factory entry to `packages/app/src/apis.ts`. The example below sets up the `ScmAuthApi` for an already configured GitLab authentication provider:
|
||||
|
||||
```ts title="packages/app/src/apis.ts"
|
||||
createApiFactory({
|
||||
api: scmAuthApiRef,
|
||||
deps: {
|
||||
gitlabAuthApi: gitlabAuthApiRef,
|
||||
},
|
||||
factory: ({ gitlabAuthApi }) => ScmAuth.forGitlab(gitlabAuthApi),
|
||||
});
|
||||
```
|
||||
|
||||
In case you are using a custom authentication providers, you might need to add a [custom `ScmAuthApi` implementation](./index.md#custom-scmauthapi-implementation).
|
||||
When using multiple auth providers like this, it's important that you configure the different sign-in resolvers so that they resolve to the same identity regardless of the method used.
|
||||
|
||||
## For Plugin Developers
|
||||
|
||||
The Backstage frontend core APIs provide a set of Utility APIs for plugin developers
|
||||
to use, both to access the user identity as well as third-party resources.
|
||||
The Backstage frontend core APIs provide a set of Utility APIs for plugin developers to use, both to access the user identity as well as third-party resources.
|
||||
|
||||
### Identity for Plugin Developers
|
||||
|
||||
For plugin developers, there is one main touchpoint for accessing the user identity: the
|
||||
`IdentityApi` exported by `@backstage/core-plugin-api` via the `identityApiRef`.
|
||||
For plugin developers, there is one main touchpoint for accessing the user identity: the `IdentityApi` exported by `@backstage/core-plugin-api` via the `identityApiRef`.
|
||||
|
||||
The `IdentityApi` gives access to the signed-in user's identity in the frontend.
|
||||
It provides access to the user's entity reference, lightweight profile information, and
|
||||
a Backstage token that identifies the user when making authenticated calls within Backstage.
|
||||
The `IdentityApi` gives access to the signed-in user's identity in the frontend. It provides access to the user's entity reference, lightweight profile information, and a Backstage token that identifies the user when making authenticated calls within Backstage.
|
||||
|
||||
When making calls to backend plugins, we recommend that the `FetchApi` is used, which
|
||||
is exported via the `fetchApiRef` from `@backstage/core-plugin-api`. The `FetchApi` will
|
||||
automatically include a Backstage token in the request, meaning there is no need
|
||||
to interact directly with the `IdentityApi`.
|
||||
When making calls to backend plugins, we recommend that the `FetchApi` is used, which is exported via the `fetchApiRef` from `@backstage/core-plugin-api`. The `FetchApi` will automatically include a Backstage token in the request, meaning there is no need to interact directly with the `IdentityApi`.
|
||||
|
||||
### Accessing Third Party Resources
|
||||
|
||||
A common pattern for talking to third-party services in Backstage is
|
||||
user-to-server requests, where short-lived OAuth Access Tokens are requested by
|
||||
plugins to authenticate calls to external services. These calls can be made
|
||||
either directly to the services or through a backend plugin or service.
|
||||
A common pattern for talking to third-party services in Backstage is user-to-server requests, where short-lived OAuth Access Tokens are requested by plugins to authenticate calls to external services. These calls can be made either directly to the services or through a backend plugin or service.
|
||||
|
||||
By relying on user-to-server calls, we keep the coupling between the frontend and
|
||||
backend low and provide a much lower barrier for plugins to make use of third
|
||||
party services. This is in comparison to, for example, a session-based system
|
||||
where access tokens are stored server-side. Such a solution would require a much
|
||||
deeper coupling between the auth backend plugin, its session storage, and other
|
||||
backend plugins or separate services. A goal of Backstage is to make it as easy
|
||||
as possible to create new plugins, and an auth solution based on user-to-server
|
||||
OAuth helps in that regard.
|
||||
By relying on user-to-server calls, we keep the coupling between the frontend and backend low and provide a much lower barrier for plugins to make use of third party services. This is in comparison to, for example, a session-based system where access tokens are stored server-side. Such a solution would require a much deeper coupling between the auth backend plugin, its session storage, and other backend plugins or separate services. A goal of Backstage is to make it as easy as possible to create new plugins, and an auth solution based on user-to-server OAuth helps in that regard.
|
||||
|
||||
The method with which frontend plugins request access to third-party services is
|
||||
through [Utility APIs](../api/utility-apis.md) for each service provider. These
|
||||
are all suffixed with `*AuthApiRef`, for example `githubAuthApiRef`. For a
|
||||
full list of providers, see the
|
||||
[@backstage/core-plugin-api](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.index.html#alertapiref) reference.
|
||||
The method with which frontend plugins request access to third-party services is through [Utility APIs](../api/utility-apis.md) for each service provider. These are all suffixed with `*AuthApiRef`, for example `githubAuthApiRef`. For a full list of providers, see the [@backstage/core-plugin-api](https://backstage.io/api/stable/modules/_backstage_core-plugin-api.index.html#alertapiref) reference.
|
||||
|
||||
## Custom Authentication Provider
|
||||
|
||||
There are generic authentication providers for OAuth2 and SAML. These can reduce
|
||||
the amount of code needed to implement a custom authentication provider that
|
||||
adheres to these standards.
|
||||
There are generic authentication providers for OAuth2 and SAML. These can reduce the amount of code needed to implement a custom authentication provider that adheres to these standards.
|
||||
|
||||
Backstage uses [Passport](http://www.passportjs.org/) under the hood, which has
|
||||
a wide library of authentication strategies for different providers. See
|
||||
[Add authentication provider](add-auth-provider.md) for details on adding a new
|
||||
Passport-supported authentication method.
|
||||
Backstage uses [Passport](http://www.passportjs.org/) under the hood, which has a wide library of authentication strategies for different providers. See [Add authentication provider](add-auth-provider.md) for details on adding a new Passport-supported authentication method.
|
||||
|
||||
## Custom ScmAuthApi Implementation
|
||||
|
||||
The default `ScmAuthApi` provides integrations for `github`, `gitlab`, `azure` and `bitbucket` and is created by the following code in `packages/app/src/apis.ts`:
|
||||
|
||||
```ts
|
||||
ScmAuth.createDefaultApiFactory();
|
||||
```
|
||||
The default `ScmAuthApi` provides integrations for `github`, `gitlab`, `azure` (Azure DevOps), `bitbucketServer` and `bitbucketCloud` and is created and registered automatically for you by the New Frontend System.
|
||||
|
||||
If you require only a subset of these integrations, then you will need a custom implementation of the [`ScmAuthApi`](https://backstage.io/api/stable/interfaces/_backstage_integration-react.ScmAuthApi.html). It is an API used to authenticate different SCM systems generically, based on what resource is being accessed, and is used for example, by the Scaffolder (Software Templates) and Catalog Import plugins.
|
||||
|
||||
@@ -465,7 +462,7 @@ providerFactories: {
|
||||
},
|
||||
```
|
||||
|
||||
You can leverage the `authProvidersExtensionPoint` for this:
|
||||
In the new backend system you can leverage the `authProvidersExtensionPoint` for this:
|
||||
|
||||
```ts
|
||||
// your-auth-plugin-module.ts
|
||||
@@ -503,13 +500,9 @@ backend.add(gheAuth);
|
||||
|
||||
## Configuring token issuers
|
||||
|
||||
By default, the Backstage authentication backend generates and manages its own signing keys automatically for any issued
|
||||
Backstage tokens. However, these keys have a short lifetime and do not persist after instance restarts.
|
||||
By default, the Backstage authentication backend generates and manages its own signing keys automatically for any issued Backstage tokens. However, these keys have a short lifetime and do not persist after instance restarts.
|
||||
|
||||
Alternatively, users can provide their own public and private key files to sign issued tokens. This is beneficial in
|
||||
scenarios where the token verification implementation aggressively caches the list of keys, and doesn't attempt to fetch
|
||||
new ones even if they encounter an unknown key id. To enable this feature add the following configuration to your config
|
||||
file:
|
||||
Alternatively, users can provide their own public and private key files to sign issued tokens. This is beneficial in scenarios where the token verification implementation aggressively caches the list of keys, and doesn't attempt to fetch new ones even if they encounter an unknown key id. To enable this feature add the following configuration to your config file:
|
||||
|
||||
```yaml
|
||||
auth:
|
||||
@@ -526,9 +519,7 @@ auth:
|
||||
- keyId: ...
|
||||
```
|
||||
|
||||
The private key should be stored in the PKCS#8 format. The public key should be stored in the SPKI format.
|
||||
You can generate the public/private key pair, using openssl and the ES256 algorithm by performing the following
|
||||
steps:
|
||||
The private key should be stored in the PKCS#8 format. The public key should be stored in the SPKI format. You can generate the public/private key pair, using openssl and the ES256 algorithm by performing the following steps:
|
||||
|
||||
Generate a private key using the ES256 algorithm
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
id: addons--new
|
||||
id: addons--old
|
||||
title: TechDocs Addons
|
||||
description: How to find, use, or create TechDocs Addons.
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the new frontend system](../../frontend-system/index.md). If you are on the [old frontend system](./getting-started.md#adding-techdocs-frontend-plugin) you may want to read [its own article](./addons.md) instead.
|
||||
This documentation is written for [the old frontend system](./getting-started.md#adding-techdocs-frontend-plugin). If you are on the [new frontend system](../../frontend-system/index.md) you may want to read [its own article](./addons.md) instead.
|
||||
:::
|
||||
|
||||
## Concepts
|
||||
@@ -50,8 +50,9 @@ representative of physical spaces in the TechDocs UI:
|
||||
### Addon Registry
|
||||
|
||||
The installation and configuration of Addons happens within a Backstage app's
|
||||
frontend. Addons are imported from plugins and registered as a plugin extension which
|
||||
are configured for both the TechDocs Reader page as well as the Entity docs page.
|
||||
frontend. Addons are imported from plugins and added underneath a registry
|
||||
component called `<TechDocsAddons>`. This registry can be configured for both
|
||||
the TechDocs Reader page as well as the Entity docs page.
|
||||
|
||||
Addons are rendered in the order in which they are registered.
|
||||
|
||||
@@ -59,26 +60,62 @@ Addons are rendered in the order in which they are registered.
|
||||
|
||||
To start using Addons you need to add the `@backstage/plugin-techdocs-module-addons-contrib` package to your app. You can do that by running this command from the root of your project: `yarn --cwd packages/app add @backstage/plugin-techdocs-module-addons-contrib`
|
||||
|
||||
Addons can then be installed as a module in your `App.tsx`:
|
||||
Addons can be installed and configured in much the same way as extensions for
|
||||
other Backstage plugins: by adding them underneath an extension registry
|
||||
component (`<TechDocsAddons>`) under the route representing the TechDocs Reader
|
||||
page in your `App.tsx`:
|
||||
|
||||
```tsx
|
||||
// packages/app/src/App.tsx
|
||||
|
||||
import { createApp } from '@backstage/frontend-defaults';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import { techDocsReportIssueAddonModule } from '@backstage/plugin-techdocs-module-addons-contrib/alpha';
|
||||
import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
|
||||
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
|
||||
|
||||
// ...
|
||||
|
||||
const app = createApp({
|
||||
features: [
|
||||
// ...
|
||||
techDocsReportIssueAddonModule,
|
||||
// ...other techdocs addon modules
|
||||
],
|
||||
});
|
||||
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
|
||||
<TechDocsAddons>
|
||||
<ReportIssue />
|
||||
{/* Other addons can be added here. */}
|
||||
</TechDocsAddons>
|
||||
</Route>;
|
||||
```
|
||||
|
||||
export default app.createRoot();
|
||||
If you are using a custom [TechDocs reader page](./how-to-guides.md#how-to-customize-the-techdocs-reader-page) your setup will be very similar, here's an example:
|
||||
|
||||
```ts
|
||||
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
|
||||
<TechDocsAddons>
|
||||
<ReportIssue />
|
||||
{/* Other addons can be added here. */}
|
||||
</TechDocsAddons>
|
||||
{techDocsPage} // This is your custom TechDocs reader page
|
||||
</Route>
|
||||
```
|
||||
|
||||
The process for configuring Addons on the documentation tab on the entity page
|
||||
is very similar; instead of adding the `<TechDocsAddons>` registry under a
|
||||
`<Route>`, you'd add it as a child of `<EntityTechdocsContent />`:
|
||||
|
||||
```tsx
|
||||
// packages/app/src/components/catalog/EntityPage.tsx
|
||||
|
||||
import { EntityLayout } from '@backstage/plugin-catalog';
|
||||
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
|
||||
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
|
||||
|
||||
// ...
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent>
|
||||
<TechDocsAddons>
|
||||
<ReportIssue />
|
||||
{/* Other addons can be added here. */}
|
||||
</TechDocsAddons>
|
||||
</EntityTechdocsContent>
|
||||
</EntityLayout.Route>;
|
||||
```
|
||||
|
||||
Note that on the entity page, because the Catalog plugin is responsible for the
|
||||
@@ -89,12 +126,12 @@ page header, TechDocs Addons whose location is `Header` will not be rendered.
|
||||
Addons can, in principle, be provided by any plugin! To make it easier to
|
||||
discover available Addons, we've compiled a list of them here:
|
||||
|
||||
| Addon | Package/Plugin | Description |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`techDocsExpandableNavigationAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsExpandableNavigationAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
|
||||
| [`techDocsReportIssueAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsReportIssueAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
|
||||
| [`techDocsTextSizeAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsTextSizeAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
|
||||
| [`techDocsLightBoxAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsLightBoxAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). Images inside links are ignored to avoid blocking navigation. |
|
||||
| Addon | Package/Plugin | Description |
|
||||
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`<ExpandableNavigation />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ExpandableNavigation.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
|
||||
| [`<ReportIssue />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ReportIssue.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
|
||||
| [`<TextSize />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.TextSize.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
|
||||
| [`<LightBox />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.LightBox.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). Images inside links are ignored to avoid blocking navigation. |
|
||||
|
||||
Got an Addon to contribute? Feel free to add a row above!
|
||||
|
||||
@@ -105,32 +142,29 @@ specific locations within a TechDocs site. To package such a react component as
|
||||
an Addon, follow these steps:
|
||||
|
||||
1. Write the component in your plugin like any other component
|
||||
2. Create the addon extension using the `TechDocsAddonBlueprint`
|
||||
3. Create and export the addon module from your plugin
|
||||
2. Create, provide, and export the component from your plugin
|
||||
|
||||
```ts
|
||||
// plugins/your-plugin/src/plugin.ts
|
||||
|
||||
import { TechDocsAddonLocations } from '@backstage/plugin-techdocs-react';
|
||||
import { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';
|
||||
import { CatGifComponent } from './addons';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import {
|
||||
createTechDocsAddonExtension,
|
||||
TechDocsAddonLocations,
|
||||
} from '@backstage/plugin-techdocs-react';
|
||||
import { CatGifComponent, CatGifComponentProps } from './addons';
|
||||
|
||||
// ...
|
||||
|
||||
const techDocsCatGifAddon = AddonBlueprint.make({
|
||||
name: 'cat-gif',
|
||||
params: {
|
||||
// You must "provide" your Addon, just like any extension, via your plugin.
|
||||
export const CatGif = yourPlugin.provide(
|
||||
// This function "creates" the Addon given a component and location. If your
|
||||
// component can be configured via props, pass the prop type here too.
|
||||
createTechDocsAddonExtension<CatGifComponentProps>({
|
||||
name: 'CatGif',
|
||||
location: TechDocsAddonLocations.Header,
|
||||
component: CatGifComponent,
|
||||
},
|
||||
});
|
||||
|
||||
export const techDocsCatGifAddonModule = createFrontendModule({
|
||||
pluginId: 'techdocs',
|
||||
extensions: [techDocsCatGifAddon],
|
||||
});
|
||||
}),
|
||||
);
|
||||
```
|
||||
|
||||
### Addons in the Content location
|
||||
@@ -147,8 +181,7 @@ provided by the Addon framework.
|
||||
|
||||
```tsx
|
||||
// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.tsx
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useShadowRootElements } from '@backstage/plugin-techdocs-react';
|
||||
|
||||
// This is a normal react component; in order to make it an Addon, you would
|
||||
@@ -5,7 +5,7 @@ description: How to find, use, or create TechDocs Addons.
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the old frontend system](./getting-started.md#adding-techdocs-frontend-plugin). If you are on the [new frontend system](../../frontend-system/index.md) you may want to read [its own article](./addons--new.md) instead.
|
||||
This documentation is written for [the new frontend system](../../frontend-system/index.md). If you are on the [old frontend system](./getting-started.md#adding-techdocs-frontend-plugin) you may want to read [its own article](./addons--old.md) instead.
|
||||
:::
|
||||
|
||||
## Concepts
|
||||
@@ -50,9 +50,8 @@ representative of physical spaces in the TechDocs UI:
|
||||
### Addon Registry
|
||||
|
||||
The installation and configuration of Addons happens within a Backstage app's
|
||||
frontend. Addons are imported from plugins and added underneath a registry
|
||||
component called `<TechDocsAddons>`. This registry can be configured for both
|
||||
the TechDocs Reader page as well as the Entity docs page.
|
||||
frontend. Addons are imported from plugins and registered as a plugin extension which
|
||||
are configured for both the TechDocs Reader page as well as the Entity docs page.
|
||||
|
||||
Addons are rendered in the order in which they are registered.
|
||||
|
||||
@@ -60,62 +59,26 @@ Addons are rendered in the order in which they are registered.
|
||||
|
||||
To start using Addons you need to add the `@backstage/plugin-techdocs-module-addons-contrib` package to your app. You can do that by running this command from the root of your project: `yarn --cwd packages/app add @backstage/plugin-techdocs-module-addons-contrib`
|
||||
|
||||
Addons can be installed and configured in much the same way as extensions for
|
||||
other Backstage plugins: by adding them underneath an extension registry
|
||||
component (`<TechDocsAddons>`) under the route representing the TechDocs Reader
|
||||
page in your `App.tsx`:
|
||||
Addons can then be installed as a module in your `App.tsx`:
|
||||
|
||||
```tsx
|
||||
// packages/app/src/App.tsx
|
||||
|
||||
import { TechDocsReaderPage } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
|
||||
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
|
||||
import { createApp } from '@backstage/frontend-defaults';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
import { techDocsReportIssueAddonModule } from '@backstage/plugin-techdocs-module-addons-contrib/alpha';
|
||||
|
||||
// ...
|
||||
|
||||
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
|
||||
<TechDocsAddons>
|
||||
<ReportIssue />
|
||||
{/* Other addons can be added here. */}
|
||||
</TechDocsAddons>
|
||||
</Route>;
|
||||
```
|
||||
const app = createApp({
|
||||
features: [
|
||||
// ...
|
||||
techDocsReportIssueAddonModule,
|
||||
// ...other techdocs addon modules
|
||||
],
|
||||
});
|
||||
|
||||
If you are using a custom [TechDocs reader page](./how-to-guides.md#how-to-customize-the-techdocs-reader-page) your setup will be very similar, here's an example:
|
||||
|
||||
```ts
|
||||
<Route path="/docs/:namespace/:kind/:name/*" element={<TechDocsReaderPage />}>
|
||||
<TechDocsAddons>
|
||||
<ReportIssue />
|
||||
{/* Other addons can be added here. */}
|
||||
</TechDocsAddons>
|
||||
{techDocsPage} // This is your custom TechDocs reader page
|
||||
</Route>
|
||||
```
|
||||
|
||||
The process for configuring Addons on the documentation tab on the entity page
|
||||
is very similar; instead of adding the `<TechDocsAddons>` registry under a
|
||||
`<Route>`, you'd add it as a child of `<EntityTechdocsContent />`:
|
||||
|
||||
```tsx
|
||||
// packages/app/src/components/catalog/EntityPage.tsx
|
||||
|
||||
import { EntityLayout } from '@backstage/plugin-catalog';
|
||||
import { EntityTechdocsContent } from '@backstage/plugin-techdocs';
|
||||
import { TechDocsAddons } from '@backstage/plugin-techdocs-react';
|
||||
import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib';
|
||||
|
||||
// ...
|
||||
|
||||
<EntityLayout.Route path="/docs" title="Docs">
|
||||
<EntityTechdocsContent>
|
||||
<TechDocsAddons>
|
||||
<ReportIssue />
|
||||
{/* Other addons can be added here. */}
|
||||
</TechDocsAddons>
|
||||
</EntityTechdocsContent>
|
||||
</EntityLayout.Route>;
|
||||
export default app.createRoot();
|
||||
```
|
||||
|
||||
Note that on the entity page, because the Catalog plugin is responsible for the
|
||||
@@ -126,12 +89,12 @@ page header, TechDocs Addons whose location is `Header` will not be rendered.
|
||||
Addons can, in principle, be provided by any plugin! To make it easier to
|
||||
discover available Addons, we've compiled a list of them here:
|
||||
|
||||
| Addon | Package/Plugin | Description |
|
||||
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`<ExpandableNavigation />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ExpandableNavigation.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
|
||||
| [`<ReportIssue />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.ReportIssue.html) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
|
||||
| [`<TextSize />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.TextSize.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
|
||||
| [`<LightBox />`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.index.LightBox.html) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). Images inside links are ignored to avoid blocking navigation. |
|
||||
| Addon | Package/Plugin | Description |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| [`techDocsExpandableNavigationAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsExpandableNavigationAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. |
|
||||
| [`techDocsReportIssueAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsReportIssueAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. |
|
||||
| [`techDocsTextSizeAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsTextSizeAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. |
|
||||
| [`techDocsLightBoxAddonModule`](https://backstage.io/api/stable/variables/_backstage_plugin-techdocs-module-addons-contrib.plugins_techdocs-module-addons-contrib_src_alpha.techDocsLightBoxAddonModule.html) | `@backstage/plugin-techdocs-module-addons-contrib/alpha` | This TechDocs addon allows users to open images in a light-box on documentation pages, they can navigate between images if there are several on one page. The image size of the light-box image is the same as the image size on the document page. When clicking on the zoom icon it zooms the image to fit in the screen (similar to `background-size: contain`). Images inside links are ignored to avoid blocking navigation. |
|
||||
|
||||
Got an Addon to contribute? Feel free to add a row above!
|
||||
|
||||
@@ -142,29 +105,32 @@ specific locations within a TechDocs site. To package such a react component as
|
||||
an Addon, follow these steps:
|
||||
|
||||
1. Write the component in your plugin like any other component
|
||||
2. Create, provide, and export the component from your plugin
|
||||
2. Create the addon extension using the `TechDocsAddonBlueprint`
|
||||
3. Create and export the addon module from your plugin
|
||||
|
||||
```ts
|
||||
// plugins/your-plugin/src/plugin.ts
|
||||
|
||||
import {
|
||||
createTechDocsAddonExtension,
|
||||
TechDocsAddonLocations,
|
||||
} from '@backstage/plugin-techdocs-react';
|
||||
import { CatGifComponent, CatGifComponentProps } from './addons';
|
||||
import { TechDocsAddonLocations } from '@backstage/plugin-techdocs-react';
|
||||
import { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';
|
||||
import { CatGifComponent } from './addons';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
|
||||
// ...
|
||||
|
||||
// You must "provide" your Addon, just like any extension, via your plugin.
|
||||
export const CatGif = yourPlugin.provide(
|
||||
// This function "creates" the Addon given a component and location. If your
|
||||
// component can be configured via props, pass the prop type here too.
|
||||
createTechDocsAddonExtension<CatGifComponentProps>({
|
||||
const techDocsCatGifAddon = AddonBlueprint.make({
|
||||
name: 'cat-gif',
|
||||
params: {
|
||||
name: 'CatGif',
|
||||
location: TechDocsAddonLocations.Header,
|
||||
component: CatGifComponent,
|
||||
}),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const techDocsCatGifAddonModule = createFrontendModule({
|
||||
pluginId: 'techdocs',
|
||||
extensions: [techDocsCatGifAddon],
|
||||
});
|
||||
```
|
||||
|
||||
### Addons in the Content location
|
||||
@@ -181,7 +147,8 @@ provided by the Addon framework.
|
||||
|
||||
```tsx
|
||||
// plugins/your-plugin/src/addons/MakeAllImagesCatGifs.tsx
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import { useShadowRootElements } from '@backstage/plugin-techdocs-react';
|
||||
|
||||
// This is a normal react component; in order to make it an Addon, you would
|
||||
|
||||
+25
-51
@@ -1,11 +1,11 @@
|
||||
---
|
||||
id: authentication--new
|
||||
id: authentication--old
|
||||
title: Authentication
|
||||
description: How to setup authentication for your Backstage app
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for [the new frontend system](../../frontend-system/index.md). If you are on the old frontend system you may want to read [its own article](./authentication.md) instead.
|
||||
This documentation is written for the old frontend system. If you are on the [new frontend system](../../frontend-system/index.md) you may want to read [its own article](./authentication.md) instead.
|
||||
:::
|
||||
|
||||
Audience: Admins or Developers
|
||||
@@ -14,7 +14,7 @@ Audience: Admins or Developers
|
||||
|
||||
We'll be walking you through how to setup authentication for your Backstage app using GitHub. After finishing this guide, you'll have both working authentication and users in your Backstage app to match to the users logging in!
|
||||
|
||||
There are multiple authentication providers available for you to use with Backstage, feel free to follow [their instructions for adding authentication](../../auth/index--new.md).
|
||||
There are multiple authentication providers available for you to use with Backstage, feel free to follow [their instructions for adding authentication](../../auth/index.md).
|
||||
|
||||
:::note Note
|
||||
|
||||
@@ -54,63 +54,37 @@ auth:
|
||||
|
||||
The next step is to change the sign-in page. For this, you'll actually need to write some code.
|
||||
|
||||
First let's add the packages we need, do this from the root:
|
||||
|
||||
```shell
|
||||
yarn --cwd packages/app add @backstage/core-plugin-api @backstage/plugin-app-react
|
||||
```
|
||||
|
||||
Then open `packages/app/src/App.tsx` and below the last `import` line, add:
|
||||
Open `packages/app/src/App.tsx` and below the last `import` line, add:
|
||||
|
||||
```typescript title="packages/app/src/App.tsx"
|
||||
import { githubAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
```
|
||||
|
||||
Now below this we are going to use the `SignInPageBlueprint` to create an extension, add this code block to do that:
|
||||
|
||||
```tsx
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
(
|
||||
<SignInPage
|
||||
{...props}
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Search for the `createApp()` function call in this file, and replace:
|
||||
Search for `const app = createApp({` in this file, and replace:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
export default createApp({
|
||||
features: [catalogPlugin, navModule],
|
||||
});
|
||||
components: {
|
||||
SignInPage: props => <SignInPage {...props} auto providers={['guest']} />,
|
||||
},
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
],
|
||||
});
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
auto
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
```
|
||||
|
||||
## Add sign-in resolver(s)
|
||||
@@ -137,7 +111,7 @@ auth:
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get a "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections.
|
||||
What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get an "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections.
|
||||
|
||||
Learn more about this topic in the [Sign-in Resolvers](../../auth/identity-resolver.md#sign-in-resolvers) documentation.
|
||||
|
||||
@@ -170,7 +144,7 @@ Sometimes the frontend starts before the backend resulting in errors on the sign
|
||||
|
||||
The recommended approach for adding Users, and Groups, into your Catalog is to use one of the existing Org Entity Providers - [like this one for GitHub](https://backstage.io/docs/integrations/github/org) - or if those don't work you may need to [create one](https://backstage.io/docs/features/software-catalog/external-integrations#custom-entity-providers) that fits your Organization's needs.
|
||||
|
||||
For the sake of this guide we'll simply step you through adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that:
|
||||
For the sake of this guide we'll simply step you though adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that:
|
||||
|
||||
1. First open the `/examples/org.yaml` file in your text editor of choice
|
||||
2. At the bottom we'll add the following YAML:
|
||||
@@ -192,7 +166,7 @@ Let's restart Backstage from the terminal once more, by stopping it with `Ctrl+C
|
||||
To learn more about Authentication in Backstage, here are some docs you
|
||||
could read:
|
||||
|
||||
- [Authentication in Backstage](../../auth/index--new.md)
|
||||
- [Authentication in Backstage](../../auth/index.md)
|
||||
- [Using organizational data from GitHub](../../integrations/github/org.md)
|
||||
|
||||
## Setting up a GitHub Integration
|
||||
@@ -5,7 +5,7 @@ description: How to setup authentication for your Backstage app
|
||||
---
|
||||
|
||||
:::info
|
||||
This documentation is written for the old frontend system. If you are on the [new frontend system](../../frontend-system/index.md) you may want to read [its own article](./authentication--new.md) instead.
|
||||
This documentation is written for [the new frontend system](../../frontend-system/index.md). If you are on the old frontend system you may want to read [its own article](./authentication--old.md) instead.
|
||||
:::
|
||||
|
||||
Audience: Admins or Developers
|
||||
@@ -14,7 +14,7 @@ Audience: Admins or Developers
|
||||
|
||||
We'll be walking you through how to setup authentication for your Backstage app using GitHub. After finishing this guide, you'll have both working authentication and users in your Backstage app to match to the users logging in!
|
||||
|
||||
There are multiple authentication providers available for you to use with Backstage, feel free to follow [their instructions for adding authentication](../../auth/index.md).
|
||||
There are multiple authentication providers available for you to use with Backstage, feel free to follow [their instructions for adding authentication](../../auth/index--new.md).
|
||||
|
||||
:::note Note
|
||||
|
||||
@@ -54,37 +54,63 @@ auth:
|
||||
|
||||
The next step is to change the sign-in page. For this, you'll actually need to write some code.
|
||||
|
||||
Open `packages/app/src/App.tsx` and below the last `import` line, add:
|
||||
First let's add the packages we need, do this from the root:
|
||||
|
||||
```shell
|
||||
yarn --cwd packages/app add @backstage/core-plugin-api @backstage/plugin-app-react
|
||||
```
|
||||
|
||||
Then open `packages/app/src/App.tsx` and below the last `import` line, add:
|
||||
|
||||
```typescript title="packages/app/src/App.tsx"
|
||||
import { githubAuthApiRef } from '@backstage/core-plugin-api';
|
||||
import { SignInPageBlueprint } from '@backstage/plugin-app-react';
|
||||
import { SignInPage } from '@backstage/core-components';
|
||||
import { createFrontendModule } from '@backstage/frontend-plugin-api';
|
||||
```
|
||||
|
||||
Search for `const app = createApp({` in this file, and replace:
|
||||
Now below this we are going to use the `SignInPageBlueprint` to create an extension, add this code block to do that:
|
||||
|
||||
```tsx
|
||||
const signInPage = SignInPageBlueprint.make({
|
||||
params: {
|
||||
loader: async () => props =>
|
||||
(
|
||||
<SignInPage
|
||||
{...props}
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Search for the `createApp()` function call in this file, and replace:
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
components: {
|
||||
SignInPage: props => <SignInPage {...props} auto providers={['guest']} />,
|
||||
},
|
||||
export default createApp({
|
||||
features: [catalogPlugin, navModule],
|
||||
});
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```tsx title="packages/app/src/App.tsx"
|
||||
components: {
|
||||
SignInPage: props => (
|
||||
<SignInPage
|
||||
{...props}
|
||||
auto
|
||||
provider={{
|
||||
id: 'github-auth-provider',
|
||||
title: 'GitHub',
|
||||
message: 'Sign in using GitHub',
|
||||
apiRef: githubAuthApiRef,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
export default createApp({
|
||||
features: [
|
||||
catalogPlugin,
|
||||
navModule,
|
||||
createFrontendModule({
|
||||
pluginId: 'app',
|
||||
extensions: [signInPage],
|
||||
}),
|
||||
],
|
||||
});
|
||||
```
|
||||
|
||||
## Add sign-in resolver(s)
|
||||
@@ -111,7 +137,7 @@ auth:
|
||||
/* highlight-add-end */
|
||||
```
|
||||
|
||||
What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get an "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections.
|
||||
What this will do is take the user details provided by the auth provider and match that against a User in the Catalog. In this case - `usernameMatchingUserEntityName` - will match the GitHub user name with the `metadata.name` value of a User in the Catalog, if none is found you will get a "Failed to sign-in, unable to resolve user identity" message. We'll cover this in the next few sections.
|
||||
|
||||
Learn more about this topic in the [Sign-in Resolvers](../../auth/identity-resolver.md#sign-in-resolvers) documentation.
|
||||
|
||||
@@ -144,7 +170,7 @@ Sometimes the frontend starts before the backend resulting in errors on the sign
|
||||
|
||||
The recommended approach for adding Users, and Groups, into your Catalog is to use one of the existing Org Entity Providers - [like this one for GitHub](https://backstage.io/docs/integrations/github/org) - or if those don't work you may need to [create one](https://backstage.io/docs/features/software-catalog/external-integrations#custom-entity-providers) that fits your Organization's needs.
|
||||
|
||||
For the sake of this guide we'll simply step you though adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that:
|
||||
For the sake of this guide we'll simply step you through adding a User to the `org.yaml` file that is included when you create a new Backstage instance. Let's do that:
|
||||
|
||||
1. First open the `/examples/org.yaml` file in your text editor of choice
|
||||
2. At the bottom we'll add the following YAML:
|
||||
@@ -166,7 +192,7 @@ Let's restart Backstage from the terminal once more, by stopping it with `Ctrl+C
|
||||
To learn more about Authentication in Backstage, here are some docs you
|
||||
could read:
|
||||
|
||||
- [Authentication in Backstage](../../auth/index.md)
|
||||
- [Authentication in Backstage](../../auth/index--new.md)
|
||||
- [Using organizational data from GitHub](../../integrations/github/org.md)
|
||||
|
||||
## Setting up a GitHub Integration
|
||||
|
||||
Reference in New Issue
Block a user