From f65f982b1ce760a9a180c4ab07055c45cb37b5c2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 16 Jun 2020 17:26:49 +0200 Subject: [PATCH] packages/core: added google sign-in provider --- .../src/layout/SignInPage/googleProvider.tsx | 86 +++++++++++++++++++ .../core/src/layout/SignInPage/providers.tsx | 4 +- 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/layout/SignInPage/googleProvider.tsx diff --git a/packages/core/src/layout/SignInPage/googleProvider.tsx b/packages/core/src/layout/SignInPage/googleProvider.tsx new file mode 100644 index 0000000000..2db7e2fd53 --- /dev/null +++ b/packages/core/src/layout/SignInPage/googleProvider.tsx @@ -0,0 +1,86 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { Grid, Typography, Button } from '@material-ui/core'; +import { InfoCard } from '../InfoCard/InfoCard'; +import { ProviderComponent, ProviderLoader, SignInProvider } from './types'; +import { + useApi, + googleAuthApiRef, + errorApiRef, + ProfileInfo, +} from '@backstage/core-api'; + +function parseUserId(profile: ProfileInfo) { + return profile!.email.replace(/@.*/, ''); +} + +const Component: ProviderComponent = ({ onResult }) => { + const googleAuthApi = useApi(googleAuthApiRef); + const errorApi = useApi(errorApiRef); + + const handleLogin = async () => { + try { + const idToken = await googleAuthApi.getIdToken({ instantPopup: true }); + const profile = await googleAuthApi.getProfile(); + + onResult({ + userId: parseUserId(profile!), + idToken, + logout: async () => { + await googleAuthApi.logout(); + }, + }); + } catch (error) { + errorApi.post(error); + } + }; + + return ( + + + Sign In + + } + > + Sign In using Google + + + ); +}; + +const loader: ProviderLoader = async apis => { + const googleAuthApi = apis.get(googleAuthApiRef)!; + + const [idToken, profile] = await Promise.all([ + googleAuthApi.getIdToken({ optional: true }), + googleAuthApi.getProfile({ optional: true }), + ]); + + return { + userId: parseUserId(profile!), + idToken, + logout: async () => { + await googleAuthApi.logout(); + }, + }; +}; + +export const googleProvider: SignInProvider = { Component, loader }; diff --git a/packages/core/src/layout/SignInPage/providers.tsx b/packages/core/src/layout/SignInPage/providers.tsx index 10fb09d082..8e5cc7fc54 100644 --- a/packages/core/src/layout/SignInPage/providers.tsx +++ b/packages/core/src/layout/SignInPage/providers.tsx @@ -16,6 +16,7 @@ import React, { useLayoutEffect, useState, useMemo, useCallback } from 'react'; import { guestProvider } from './guestProvider'; +import { googleProvider } from './googleProvider'; import { SignInPageProps, SignInResult, @@ -28,10 +29,11 @@ import { SignInProvider } from './types'; const PROVIDER_STORAGE_KEY = '@backstage/core:SignInPage:provider'; // Separate list here to avoid exporting internal types -export type SignInProviderId = 'guest'; +export type SignInProviderId = 'guest' | 'google'; const signInProviders: { [id in SignInProviderId]: SignInProvider } = { guest: guestProvider, + google: googleProvider, }; export const useSignInProviders = (