From e1e650e12a04345ff18d3e1072a3290595e3c98d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Jan 2021 19:02:32 +0100 Subject: [PATCH 1/6] core-api: if loginPopup is rejected, throw PopupRejectedError --- packages/core-api/src/lib/loginPopup.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core-api/src/lib/loginPopup.ts b/packages/core-api/src/lib/loginPopup.ts index 2e14447882..425998f4bc 100644 --- a/packages/core-api/src/lib/loginPopup.ts +++ b/packages/core-api/src/lib/loginPopup.ts @@ -82,7 +82,9 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { let targetOrigin = ''; if (!popup || typeof popup.closed === 'undefined' || popup.closed) { - reject(new Error('Failed to open auth popup.')); + const error = new Error('Failed to open auth popup.'); + error.name = 'PopupRejectedError'; + reject(error); return; } From a68827420942f5a13f478fc54c7401bcbf2dbfa0 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Jan 2021 19:03:26 +0100 Subject: [PATCH 2/6] core-api: fix check to determine whether popup was closed or the messaging was misconfigured --- packages/core-api/src/lib/loginPopup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-api/src/lib/loginPopup.ts b/packages/core-api/src/lib/loginPopup.ts index 425998f4bc..716c4f9651 100644 --- a/packages/core-api/src/lib/loginPopup.ts +++ b/packages/core-api/src/lib/loginPopup.ts @@ -122,7 +122,7 @@ export function showLoginPopup(options: LoginPopupOptions): Promise { const intervalId = setInterval(() => { if (popup.closed) { const errMessage = `Login failed, ${ - targetOrigin !== window.location.origin + targetOrigin && targetOrigin !== window.location.origin ? `Incorrect app origin, expected ${targetOrigin}` : 'popup was closed' }`; From 32c95605fbc3170a241582797a559797005e774b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Jan 2021 19:06:05 +0100 Subject: [PATCH 3/6] add popup fix changeset --- .changeset/shiny-rabbits-unite.md | 5 +++++ .github/styles/vocab.txt | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/shiny-rabbits-unite.md diff --git a/.changeset/shiny-rabbits-unite.md b/.changeset/shiny-rabbits-unite.md new file mode 100644 index 0000000000..dca9ee0dd9 --- /dev/null +++ b/.changeset/shiny-rabbits-unite.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Fix check that determines whether popup was closed or the messaging was misconfigured. diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 425e6eea6f..d545b380f5 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -130,6 +130,7 @@ middleware minikube Minikube misconfiguration +misconfigured misgendering mkdocs Mkdocs From 01058d486c074c3874243562786370010b85a605 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Jan 2021 19:13:01 +0100 Subject: [PATCH 4/6] core: add separate prop union for SignInPage for using a single provider --- .../core/src/layout/SignInPage/SignInPage.tsx | 105 ++++++++++++++++-- 1 file changed, 98 insertions(+), 7 deletions(-) diff --git a/packages/core/src/layout/SignInPage/SignInPage.tsx b/packages/core/src/layout/SignInPage/SignInPage.tsx index 83ef8fe8a8..c3e5b75bb7 100644 --- a/packages/core/src/layout/SignInPage/SignInPage.tsx +++ b/packages/core/src/layout/SignInPage/SignInPage.tsx @@ -14,30 +14,38 @@ * limitations under the License. */ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Page } from '../Page'; import { Header } from '../Header'; import { Content } from '../Content/Content'; import { ContentHeader } from '../ContentHeader/ContentHeader'; -import { Grid } from '@material-ui/core'; +import { Grid, Button, Typography } from '@material-ui/core'; import { SignInPageProps, useApi, configApiRef } from '@backstage/core-api'; import { useSignInProviders, getSignInProviders } from './providers'; -import { IdentityProviders } from './types'; +import { IdentityProviders, SignInConfig } from './types'; import { Progress } from '../../components/Progress'; -import { useStyles } from './styles'; +import { GridItem, useStyles } from './styles'; +import { InfoCard } from '../InfoCard'; -export type Props = SignInPageProps & { +type MultiSignInPageProps = SignInPageProps & { providers: IdentityProviders; title?: string; align?: 'center' | 'left'; }; -export const SignInPage = ({ +type SingleSignInPageProps = SignInPageProps & { + provider: SignInConfig; + auto?: boolean; +}; + +export type Props = MultiSignInPageProps | SingleSignInPageProps; + +export const MultiSignInPage = ({ onResult, providers = [], title, align = 'left', -}: Props) => { +}: MultiSignInPageProps) => { const configApi = useApi(configApiRef); const classes = useStyles(); @@ -69,3 +77,86 @@ export const SignInPage = ({ ); }; + +export const SingleSignInPage = ({ + onResult, + provider, + auto, +}: SingleSignInPageProps) => { + const classes = useStyles(); + const authApi = useApi(provider.apiRef); + const configApi = useApi(configApiRef); + + const [retry, setRetry] = useState<{} | boolean | undefined>(auto); + const [error, setError] = useState(); + + useEffect(() => { + const login = async () => { + const identity = await authApi.getBackstageIdentity({ + instantPopup: true, + }); + + const profile = await authApi.getProfile(); + onResult({ + userId: identity!.id, + profile: profile!, + getIdToken: () => { + return authApi.getBackstageIdentity().then(i => i!.idToken); + }, + signOut: async () => { + await authApi.signOut(); + }, + }); + }; + + if (retry) { + login().catch(setError); + } + }, [onResult, authApi, retry]); + + return ( + +
+ + + + setRetry({})} + > + Sign In + + } + > + {provider.message} + {error && error.name !== 'PopupRejectedError' && ( + + {error.message} + + )} + + + + + + ); +}; + +export const SignInPage = (props: Props) => { + if ('provider' in props) { + return ; + } + + return ; +}; From 23381386d6ee7a659ca24fc166356f70ae8c6a00 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Jan 2021 19:25:58 +0100 Subject: [PATCH 5/6] docs: update auth docs to mention and prefer single-provider `SignInPage` --- docs/auth/index.md | 3 ++- docs/tutorials/quickstart-app-auth.md | 28 ++++++++++++--------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/docs/auth/index.md b/docs/auth/index.md index cf468c7bb7..a8ddf17c6b 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -86,7 +86,8 @@ to a `guest` identity for all users, without any ID token. To enable sign-in, a `SignInPage` needs to be configured, which in turn has to supply a user to the app. The `@backstage/core` package provides a basic sign-in page that allows both the user and the app developer to choose between a couple of different -sign-in methods. +sign-in methods, or to designate a single provider that may also be logged in to +automatically. ## Further Reading diff --git a/docs/tutorials/quickstart-app-auth.md b/docs/tutorials/quickstart-app-auth.md index 1c661d274c..d322e2ec3c 100644 --- a/docs/tutorials/quickstart-app-auth.md +++ b/docs/tutorials/quickstart-app-auth.md @@ -349,22 +349,18 @@ const app = createApp({ apis, plugins: Object.values(plugins), components: { - SignInPage: props => { - return ( - - ); - }, + SignInPage: props => ( + + ), }, }); ``` From da9f53c605d6850daa88d53b22256c4a2987e04e Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 28 Jan 2021 19:31:31 +0100 Subject: [PATCH 6/6] add auto SignInPage changeset --- .changeset/ninety-keys-serve.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/ninety-keys-serve.md diff --git a/.changeset/ninety-keys-serve.md b/.changeset/ninety-keys-serve.md new file mode 100644 index 0000000000..d15884b1c4 --- /dev/null +++ b/.changeset/ninety-keys-serve.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Add a `prop` union for `SignInPage` that allows it to be used for just a single provider, with inline errors, and optionally with automatic sign-in.