From ed32ccbc89b9924a81d66ccf8f69e997306283f4 Mon Sep 17 00:00:00 2001 From: "alex.opoku" Date: Wed, 1 Feb 2023 09:42:44 +0100 Subject: [PATCH 01/15] feat: acn mircosoft login --- .env.example | 3 ++ packages/frontend/package.json | 3 ++ .../src/components/ms-sign-in-button.tsx | 20 +++++++++ packages/frontend/src/frontend.tsx | 12 +++++- packages/frontend/src/hooks/ms-auth.ts | 23 ++++++++++ packages/frontend/src/pages/login-page.tsx | 24 ++++++----- yarn.lock | 43 +++++++++++++++++-- 7 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 packages/frontend/src/components/ms-sign-in-button.tsx create mode 100644 packages/frontend/src/hooks/ms-auth.ts diff --git a/.env.example b/.env.example index 1190c35..6baa929 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,9 @@ GOOGLE_API_KEY = secret GOOGLE_CLIENT_ID = secret +MICROSOFT_API_KEY = secret +MICROSOFT_CLIENT_ID = secret + AUTH_HEADER = secret URL_ORIGIN = lara.exampleCompany DEBUG = true diff --git a/packages/frontend/package.json b/packages/frontend/package.json index d391ec6..00c692a 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -15,7 +15,10 @@ }, "dependencies": { "@apollo/client": "^3.2.2", + "@azure/msal-browser": "^2.32.2", + "@azure/msal-react": "^1.5.2", "@lara/components": "^1.0.0", + "@microsoft/microsoft-graph-client": "^3.0.4", "@rebass/grid": "^6.1.0", "apollo-link-token-refresh": "^0.4.0", "date-fns": "^2.16.1", diff --git a/packages/frontend/src/components/ms-sign-in-button.tsx b/packages/frontend/src/components/ms-sign-in-button.tsx new file mode 100644 index 0000000..b7a0fc7 --- /dev/null +++ b/packages/frontend/src/components/ms-sign-in-button.tsx @@ -0,0 +1,20 @@ +import React from 'react' +import { useMsal } from '@azure/msal-react' +import { loginRequest } from '../hooks/ms-auth' +import { PrimaryButton } from './button' + +/** + * Renders a button which, when selected, will redirect the page to the login prompt + */ +export const SignInButton = () => { + const { instance } = useMsal() + + const handleLogin = (loginType: any) => { + if (loginType === 'redirect') { + instance.loginRedirect(loginRequest).catch((e) => { + console.log(e) + }) + } + } + return handleLogin('redirect')}>sign in with ACN +} diff --git a/packages/frontend/src/frontend.tsx b/packages/frontend/src/frontend.tsx index 0a0dd3a..64f3534 100644 --- a/packages/frontend/src/frontend.tsx +++ b/packages/frontend/src/frontend.tsx @@ -1,9 +1,19 @@ import React from 'react' import ReactDOM from 'react-dom' +import { MsalProvider } from '@azure/msal-react' +import { msalConfig } from './hooks/ms-auth' import { App } from './app' +import { PublicClientApplication } from '@azure/msal-browser' -ReactDOM.render(, document.getElementById('app')) +const msalInstance = new PublicClientApplication(msalConfig) + +ReactDOM.render( + + + , + document.getElementById('app') +) if (module.hot && ENVIRONMENT.debug) { module.hot.accept() diff --git a/packages/frontend/src/hooks/ms-auth.ts b/packages/frontend/src/hooks/ms-auth.ts new file mode 100644 index 0000000..b432f9c --- /dev/null +++ b/packages/frontend/src/hooks/ms-auth.ts @@ -0,0 +1,23 @@ +import { PublicClientApplication } from '@azure/msal-browser' + +const redirectDomain = 'localhost:8080' +const redirectUrl = redirectDomain +const tenantId = 'e0793d39-0939-496d-b129-198edd916feb' + +export const msalConfig = { + auth: { + clientId: 'test', + authority: 'https://login.microsoftonline.com/' + tenantId, + redirectUri: redirectUrl, + }, + cache: { + cacheLocation: 'sessionStorage', + storeAuthStateInCookie: false, + }, +} + +export const loginRequest = { + scopes: ['User.Read', 'openid', 'profile'], +} + +export const MyMSALObj = new PublicClientApplication(msalConfig) diff --git a/packages/frontend/src/pages/login-page.tsx b/packages/frontend/src/pages/login-page.tsx index 99953a7..75dee2e 100644 --- a/packages/frontend/src/pages/login-page.tsx +++ b/packages/frontend/src/pages/login-page.tsx @@ -9,6 +9,7 @@ import { useLoginPageLoginMutation } from '../graphql' import { useAuthentication } from '../hooks/use-authentication' import { Template } from '../templates/template' import { SplashPage } from './splash-page' +import { SignInButton } from '../components/ms-sign-in-button' const LoginPage: React.FunctionComponent = () => { const { login } = useAuthentication() @@ -57,16 +58,19 @@ const LoginPage: React.FunctionComponent = () => { - ( - - sign in with Google - - )} - clientId={ENVIRONMENT.googleClientID} - onSuccess={onLoginSuccess} - onFailure={onLoginFailure} - /> + + ( + + sign in with Google + + )} + clientId={ENVIRONMENT.googleClientID} + onSuccess={onLoginSuccess} + onFailure={onLoginFailure} + /> + + diff --git a/yarn.lock b/yarn.lock index a02eee6..587a72c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1048,6 +1048,23 @@ dependencies: tslib "^2.3.1" +"@azure/msal-browser@^2.32.2": + version "2.32.2" + resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-2.32.2.tgz#b2284773c95656ed52710e82aedd7fe3e86fa38d" + integrity sha512-1YqGzXtPG3QrZPFBKaMWr2WQdukDj+PelqUCv351+p+hlw/AhdRrb8haY73/iqkhT6Cdrbnh7sL4gikVsF4O1g== + dependencies: + "@azure/msal-common" "^9.0.2" + +"@azure/msal-common@^9.0.2": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-9.0.2.tgz#b01c0faef18125987682e669494163da06449a20" + integrity sha512-qzwxuF8kZAp+rNUactMCgJh8fblq9D4lSqrrIxMDzLjgSZtjN32ix7r/HBe8QdOr76II9SVVPcMkX4sPzPfQ7w== + +"@azure/msal-react@^1.5.2": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@azure/msal-react/-/msal-react-1.5.2.tgz#9d945af2a140e00c3950c1c3fafd1dddb533d12a" + integrity sha512-YgtonunuNR00Td/Z+taMKd9df+EnstbEzNd3nS+6oX4AL6kxwkDybF+1EqJEQdofOwGZl3xvifiFpyZZsnr4tA== + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -1548,6 +1565,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.12.5": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd" + integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/template@^7.18.10", "@babel/template@^7.3.3": version "7.18.10" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" @@ -3476,6 +3500,14 @@ npmlog "^6.0.2" write-file-atomic "^4.0.1" +"@microsoft/microsoft-graph-client@^3.0.4": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@microsoft/microsoft-graph-client/-/microsoft-graph-client-3.0.4.tgz#6fc409336574521734379f033787af153828bf5d" + integrity sha512-K7GIg/inDukZC2iBhFEvOSoq5ShnlIl8JSRUv8Ksw1iXTtu6kxLmBwF6xY8RZN7CTSJh+5N91aMKu5KeF0/9fA== + dependencies: + "@babel/runtime" "^7.12.5" + tslib "^2.2.0" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -4558,9 +4590,9 @@ "@types/react" "*" "@types/react@*", "@types/react@^17", "@types/react@^17.0.4", "@types/react@^17.0.9": - version "17.0.50" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.50.tgz#39abb4f7098f546cfcd6b51207c90c4295ee81fc" - integrity sha512-ZCBHzpDb5skMnc1zFXAXnL3l1FAdi+xZvwxK+PkglMmBrwjpp9nKaWuEvrGnSifCJmBFGxZOOFuwC6KH/s0NuA== + version "17.0.53" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.53.tgz#10d4d5999b8af3d6bc6a9369d7eb953da82442ab" + integrity sha512-1yIpQR2zdYu1Z/dc1OxC+MA6GR240u3gcnP4l6mvj/PJiVaqHsQPmWttsvHsfnhfPbU2FuGmo0wSITPygjBmsw== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -13842,6 +13874,11 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regenerator-runtime@^0.13.4: version "0.13.10" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee" From 665e6380ee7c871edeb5c36825b1e86bf3d09d8d Mon Sep 17 00:00:00 2001 From: "alex.opoku" Date: Tue, 11 Apr 2023 09:22:38 +0200 Subject: [PATCH 02/15] feat: add microsoft login --- .../src/components/ms-sign-in-button.tsx | 55 ++++++++++++++++--- packages/frontend/src/hooks/ms-auth.ts | 13 ++--- packages/frontend/src/pages/login-page.tsx | 6 +- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/packages/frontend/src/components/ms-sign-in-button.tsx b/packages/frontend/src/components/ms-sign-in-button.tsx index b7a0fc7..655240f 100644 --- a/packages/frontend/src/components/ms-sign-in-button.tsx +++ b/packages/frontend/src/components/ms-sign-in-button.tsx @@ -1,20 +1,57 @@ -import React from 'react' -import { useMsal } from '@azure/msal-react' -import { loginRequest } from '../hooks/ms-auth' +import React, {ButtonHTMLAttributes, useState} from 'react' +import AppHistory from '../app-history' import { PrimaryButton } from './button' +import {useMsal} from "@azure/msal-react"; +import {loginRequest} from "../hooks/ms-auth"; +import {useAuthentication} from "../hooks/use-authentication"; +import {useLoginPageLoginMutation} from "../graphql"; +import {useIsAuthenticated } from "@azure/msal-react"; -/** - * Renders a button which, when selected, will redirect the page to the login prompt - */ -export const SignInButton = () => { - const { instance } = useMsal() +export interface ButtonProps extends ButtonHTMLAttributes { + fullsize?: boolean +} +export const SignInButton: React.FunctionComponent = () => { + const { instance, accounts } = useMsal(); + const [msalAccessToken, setAccessToken] = useState(""); + const { login } = useAuthentication() + const [mutate] = useLoginPageLoginMutation() + const isAuthenticated = useIsAuthenticated(); + const RequestMsalAccessToken = () => { + const request = { + ...loginRequest, + account: accounts[0] + }; + // Silently acquires an access token which is then attached to a request for Microsoft Graph data + instance.acquireTokenSilent(request).then((response) => { + setAccessToken(response.accessToken); + }).catch(() => { + instance.acquireTokenPopup(request).then((response) => { + setAccessToken(response.accessToken); + }); + }); + } const handleLogin = (loginType: any) => { if (loginType === 'redirect') { instance.loginRedirect(loginRequest).catch((e) => { console.log(e) }) } - } + + if(isAuthenticated){ + RequestMsalAccessToken() + + const accessToken = msalAccessToken + console.log(accessToken) + + mutate({ variables: { token: accessToken } }).then((response) => { + const { data } = response + if (!data?.login) { + return AppHistory.getInstance().push('/no-user-found') + } + login(data.login) + }) + } + } return handleLogin('redirect')}>sign in with ACN } diff --git a/packages/frontend/src/hooks/ms-auth.ts b/packages/frontend/src/hooks/ms-auth.ts index b432f9c..6f219b0 100644 --- a/packages/frontend/src/hooks/ms-auth.ts +++ b/packages/frontend/src/hooks/ms-auth.ts @@ -1,13 +1,12 @@ -import { PublicClientApplication } from '@azure/msal-browser' - -const redirectDomain = 'localhost:8080' +const redirectDomain = 'http://localhost:8080' const redirectUrl = redirectDomain -const tenantId = 'e0793d39-0939-496d-b129-198edd916feb' +const { MICROSOFT_API_KEY } = process.env +const { MICROSOFT_TENANT_ID } = process.env export const msalConfig = { auth: { - clientId: 'test', - authority: 'https://login.microsoftonline.com/' + tenantId, + clientId: MICROSOFT_API_KEY, + authority: 'https://login.microsoftonline.com/' + MICROSOFT_TENANT_ID, redirectUri: redirectUrl, }, cache: { @@ -19,5 +18,3 @@ export const msalConfig = { export const loginRequest = { scopes: ['User.Read', 'openid', 'profile'], } - -export const MyMSALObj = new PublicClientApplication(msalConfig) diff --git a/packages/frontend/src/pages/login-page.tsx b/packages/frontend/src/pages/login-page.tsx index 75dee2e..69ff712 100644 --- a/packages/frontend/src/pages/login-page.tsx +++ b/packages/frontend/src/pages/login-page.tsx @@ -23,12 +23,10 @@ const LoginPage: React.FunctionComponent = () => { if (!('getAuthResponse' in googleResponse)) { return } - - const accessToken = googleResponse.getAuthResponse().access_token - + const accessToken = googleResponse.getAuthResponse().access_token + console.log(accessToken) mutate({ variables: { token: accessToken } }).then((response) => { const { data } = response - if (!data?.login) { return AppHistory.getInstance().push('/no-user-found') } From 8db4b4035a6fbc10331bdac57434cf1215bf4309 Mon Sep 17 00:00:00 2001 From: "alex.opoku" Date: Fri, 2 Jun 2023 17:22:27 +0200 Subject: [PATCH 03/15] feat: email as param for login and removed google login --- .env.example | 3 - .github/workflows/reusable-build-job.yml | 2 + .github/workflows/reusable-deploy-job.yml | 2 + packages/api/schema.gql | 4 +- packages/api/src/graphql.ts | 4 +- packages/backend/src/google-auth.ts | 15 ----- .../backend/src/resolvers/auth.resolver.ts | 5 +- packages/backend/src/test/getEnv.js | 3 +- packages/frontend/src/app.tsx | 17 +++-- .../src/components/ms-sign-in-button.tsx | 67 ++++++++----------- packages/frontend/src/frontend.tsx | 12 +--- packages/frontend/src/global.d.ts | 3 + packages/frontend/src/graphql/index.tsx | 8 +-- .../graphql/mutations/login-page-login.gql | 4 +- packages/frontend/src/hooks/ms-auth.ts | 11 +-- packages/frontend/src/pages/login-page.tsx | 55 +-------------- packages/frontend/src/routes.tsx | 1 - packages/frontend/webpack.config.js | 21 +++++- readme.md | 6 +- 19 files changed, 89 insertions(+), 154 deletions(-) delete mode 100644 packages/backend/src/google-auth.ts diff --git a/.env.example b/.env.example index 6baa929..f007afc 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,3 @@ -GOOGLE_API_KEY = secret -GOOGLE_CLIENT_ID = secret - MICROSOFT_API_KEY = secret MICROSOFT_CLIENT_ID = secret diff --git a/.github/workflows/reusable-build-job.yml b/.github/workflows/reusable-build-job.yml index 09c9136..2406abb 100644 --- a/.github/workflows/reusable-build-job.yml +++ b/.github/workflows/reusable-build-job.yml @@ -26,6 +26,8 @@ jobs: MODE: ${{ inputs.mode }} AUTH_HEADER: ${{ secrets.AUTH_HEADER }} GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }} + MICROSOFT_CLIENT_ID = ${{ secrets.MICROSOFT_CLIENT_ID }} + MICROSOFT_TENANT_ID = ${{ secrets.MICROSOFT_TENANT_ID }} SUPPORT_MAIL: ${{ secrets.SUPPORT_MAIL }} URL_ORIGIN: ${{ secrets.URL_ORIGIN }} COMPANY_ABBREVIATION: ${{ secrets.COMPANY_ABBREVIATION }} diff --git a/.github/workflows/reusable-deploy-job.yml b/.github/workflows/reusable-deploy-job.yml index cafe368..d97def8 100644 --- a/.github/workflows/reusable-deploy-job.yml +++ b/.github/workflows/reusable-deploy-job.yml @@ -31,6 +31,8 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }} + MICROSOFT_CLIENT_ID = ${{ secrets.MICROSOFT_CLIENT_ID }} + MICROSOFT_TENANT_ID = ${{ secrets.MICROSOFT_TENANT_ID }} LARA_SECRET: ${{ secrets.LARA_SECRET }} SES_EMAIL: ${{ secrets.SES_EMAIL }} SUPPORT_MAIL: ${{ secrets.SUPPORT_MAIL }} diff --git a/packages/api/schema.gql b/packages/api/schema.gql index f89bc98..26c2a79 100644 --- a/packages/api/schema.gql +++ b/packages/api/schema.gql @@ -140,9 +140,9 @@ type Mutation { deleteEntry(id: ID!): MutateEntryPayload! """ - Login via google. + Login via microsoft """ - login(googleToken: String!): OAuthPayload + login(email: String!): OAuthPayload """ Unclaims a Trainee by the current Trainer diff --git a/packages/api/src/graphql.ts b/packages/api/src/graphql.ts index d30f8fa..3026d89 100644 --- a/packages/api/src/graphql.ts +++ b/packages/api/src/graphql.ts @@ -256,7 +256,7 @@ export type GqlMutationLinkAlexaArgs = { export type GqlMutationLoginArgs = { - googleToken: Scalars['String']; + email: Scalars['String']; }; @@ -770,7 +770,7 @@ export type GqlMutationResolvers, ParentType, ContextType, RequireFields>; deleteEntry?: Resolver>; linkAlexa?: Resolver, ParentType, ContextType, RequireFields>; - login?: Resolver, ParentType, ContextType, RequireFields>; + login?: Resolver, ParentType, ContextType, RequireFields>; markUserForDeletion?: Resolver, ParentType, ContextType, RequireFields>; unclaimTrainee?: Resolver, ParentType, ContextType, RequireFields>; unlinkAlexa?: Resolver, ParentType, ContextType>; diff --git a/packages/backend/src/google-auth.ts b/packages/backend/src/google-auth.ts deleted file mode 100644 index 804a378..0000000 --- a/packages/backend/src/google-auth.ts +++ /dev/null @@ -1,15 +0,0 @@ -import fetch from 'node-fetch' - -const { GOOGLE_API_KEY } = process.env -if (!GOOGLE_API_KEY) { - throw new Error("Missing Environment Variable: 'GOOGLE_API_KEY'") -} - -export const validateToken = async (token: string): Promise => { - const url = 'https://www.googleapis.com/oauth2/v2/tokeninfo' - const params = `?key=${GOOGLE_API_KEY}&access_token=${token}` - - return fetch(url + params) - .then((res) => res.json()) - .then((json) => json.email) -} diff --git a/packages/backend/src/resolvers/auth.resolver.ts b/packages/backend/src/resolvers/auth.resolver.ts index 2d90b9f..fbed342 100644 --- a/packages/backend/src/resolvers/auth.resolver.ts +++ b/packages/backend/src/resolvers/auth.resolver.ts @@ -4,7 +4,6 @@ import { GraphQLError } from 'graphql' import { GqlResolvers } from '@lara/api' -import { validateToken } from '../google-auth' import { t } from '../i18n' import { isDebug } from '../permissions' import { saveUser, userByEmail, userById } from '../repositories/user.repo' @@ -27,9 +26,7 @@ const createMockUser = async (email: string) => { export const authResolver: GqlResolvers = { Mutation: { - login: async (_parent, { googleToken }) => { - const email = await validateToken(googleToken) - + login: async (_parent, { email }) => { if (!email) { return } diff --git a/packages/backend/src/test/getEnv.js b/packages/backend/src/test/getEnv.js index 7afe322..7146c9d 100644 --- a/packages/backend/src/test/getEnv.js +++ b/packages/backend/src/test/getEnv.js @@ -12,7 +12,8 @@ process.env = { GOOGLE_API_KEY: 'secret', GOOGLE_CLIENT_ID: 'secret', - + MICROSOFT_CLIENT_ID: 'secret', + MICROSOFT_TENANT_ID: 'secret', AUTH_HEADER: 'secret', DEBUG: true, diff --git a/packages/frontend/src/app.tsx b/packages/frontend/src/app.tsx index 4d1979c..906e723 100644 --- a/packages/frontend/src/app.tsx +++ b/packages/frontend/src/app.tsx @@ -11,16 +11,23 @@ import { AuthenticatedState, AuthenticationContext } from './hooks/use-authentic import { SplashPage } from './pages/splash-page' import Routes from './routes' import ThemeProvider from './theme-provider' +import { MsalProvider } from '@azure/msal-react' +import { msalConfig } from './hooks/ms-auth' +import { PublicClientApplication } from '@azure/msal-browser' + +const msalInstance = new PublicClientApplication(msalConfig) export const App: React.FunctionComponent = () => { const [authenticated, setAuthenticated] = React.useState('loading') return ( - - - - - + + + + + + + ) } diff --git a/packages/frontend/src/components/ms-sign-in-button.tsx b/packages/frontend/src/components/ms-sign-in-button.tsx index 655240f..0479285 100644 --- a/packages/frontend/src/components/ms-sign-in-button.tsx +++ b/packages/frontend/src/components/ms-sign-in-button.tsx @@ -1,57 +1,48 @@ -import React, {ButtonHTMLAttributes, useState} from 'react' +import React, { ButtonHTMLAttributes } from 'react' import AppHistory from '../app-history' import { PrimaryButton } from './button' -import {useMsal} from "@azure/msal-react"; -import {loginRequest} from "../hooks/ms-auth"; -import {useAuthentication} from "../hooks/use-authentication"; -import {useLoginPageLoginMutation} from "../graphql"; -import {useIsAuthenticated } from "@azure/msal-react"; +import { useMsal } from '@azure/msal-react' +import { loginRequest } from '../hooks/ms-auth' +import { useAuthentication } from '../hooks/use-authentication' +import { useLoginPageLoginMutation } from '../graphql' +import { useIsAuthenticated } from '@azure/msal-react' export interface ButtonProps extends ButtonHTMLAttributes { fullsize?: boolean } export const SignInButton: React.FunctionComponent = () => { - const { instance, accounts } = useMsal(); - const [msalAccessToken, setAccessToken] = useState(""); + const { instance, accounts } = useMsal() const { login } = useAuthentication() const [mutate] = useLoginPageLoginMutation() - const isAuthenticated = useIsAuthenticated(); + const isAuthenticated = useIsAuthenticated() - const RequestMsalAccessToken = () => { - const request = { - ...loginRequest, - account: accounts[0] - }; - // Silently acquires an access token which is then attached to a request for Microsoft Graph data - instance.acquireTokenSilent(request).then((response) => { - setAccessToken(response.accessToken); - }).catch(() => { - instance.acquireTokenPopup(request).then((response) => { - setAccessToken(response.accessToken); - }); - }); - } - const handleLogin = (loginType: any) => { + const handleLogin = async (loginType: any) => { if (loginType === 'redirect') { instance.loginRedirect(loginRequest).catch((e) => { console.log(e) }) } - - if(isAuthenticated){ - RequestMsalAccessToken() - - const accessToken = msalAccessToken - console.log(accessToken) - - mutate({ variables: { token: accessToken } }).then((response) => { - const { data } = response - if (!data?.login) { - return AppHistory.getInstance().push('/no-user-found') - } - login(data.login) - }) + if (isAuthenticated) { + const request = { + ...loginRequest, + account: accounts[0], } + instance + .acquireTokenSilent(request) + .then((response) => { + console.log(response) + mutate({ variables: { email: response.account?.username ?? '' } }).then((response) => { + const { data } = response + if (!data?.login) { + return AppHistory.getInstance().push('/no-user-found') + } + login(data.login) + }) + }) + .catch((e) => { + console.log(e) + }) } + } return handleLogin('redirect')}>sign in with ACN } diff --git a/packages/frontend/src/frontend.tsx b/packages/frontend/src/frontend.tsx index 64f3534..0a0dd3a 100644 --- a/packages/frontend/src/frontend.tsx +++ b/packages/frontend/src/frontend.tsx @@ -1,19 +1,9 @@ import React from 'react' import ReactDOM from 'react-dom' -import { MsalProvider } from '@azure/msal-react' -import { msalConfig } from './hooks/ms-auth' import { App } from './app' -import { PublicClientApplication } from '@azure/msal-browser' -const msalInstance = new PublicClientApplication(msalConfig) - -ReactDOM.render( - - - , - document.getElementById('app') -) +ReactDOM.render(, document.getElementById('app')) if (module.hot && ENVIRONMENT.debug) { module.hot.accept() diff --git a/packages/frontend/src/global.d.ts b/packages/frontend/src/global.d.ts index 8df0f2d..aef311f 100644 --- a/packages/frontend/src/global.d.ts +++ b/packages/frontend/src/global.d.ts @@ -23,8 +23,11 @@ declare const ENVIRONMENT: { name: string debug: boolean googleClientID: string + microsoftClientID: string + microsoftTenantID: string authHeader: string backendUrl: string + frontendUrl: string supportMail: string } diff --git a/packages/frontend/src/graphql/index.tsx b/packages/frontend/src/graphql/index.tsx index 6af9264..7fe4f3c 100644 --- a/packages/frontend/src/graphql/index.tsx +++ b/packages/frontend/src/graphql/index.tsx @@ -255,7 +255,7 @@ export type MutationLinkAlexaArgs = { export type MutationLoginArgs = { - googleToken: Scalars['String']; + email: Scalars['String']; }; @@ -637,7 +637,7 @@ export type LinkAlexaMutationVariables = Exact<{ export type LinkAlexaMutation = { __typename?: 'Mutation', linkAlexa?: { __typename?: 'Admin', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainee', id: string, alexaSkillLinked?: boolean | undefined } | { __typename?: 'Trainer', id: string, alexaSkillLinked?: boolean | undefined } | undefined }; export type LoginPageLoginMutationVariables = Exact<{ - token: Scalars['String']; + email: Scalars['String']; }>; @@ -1136,8 +1136,8 @@ export function useLinkAlexaMutation(baseOptions?: Apollo.MutationHookOptions
  • ; export const LoginPageLoginDocument = gql` - mutation LoginPageLogin($token: String!) { - login(googleToken: $token) { + mutation LoginPageLogin($email: String!) { + login(email: $email) { accessToken refreshToken expiresIn diff --git a/packages/frontend/src/graphql/mutations/login-page-login.gql b/packages/frontend/src/graphql/mutations/login-page-login.gql index f960d88..5963147 100644 --- a/packages/frontend/src/graphql/mutations/login-page-login.gql +++ b/packages/frontend/src/graphql/mutations/login-page-login.gql @@ -1,5 +1,5 @@ -mutation LoginPageLogin($token: String!) { - login(googleToken: $token) { +mutation LoginPageLogin($email: String!) { + login(email: $email) { accessToken refreshToken expiresIn diff --git a/packages/frontend/src/hooks/ms-auth.ts b/packages/frontend/src/hooks/ms-auth.ts index 6f219b0..0397b67 100644 --- a/packages/frontend/src/hooks/ms-auth.ts +++ b/packages/frontend/src/hooks/ms-auth.ts @@ -1,13 +1,8 @@ -const redirectDomain = 'http://localhost:8080' -const redirectUrl = redirectDomain -const { MICROSOFT_API_KEY } = process.env -const { MICROSOFT_TENANT_ID } = process.env - export const msalConfig = { auth: { - clientId: MICROSOFT_API_KEY, - authority: 'https://login.microsoftonline.com/' + MICROSOFT_TENANT_ID, - redirectUri: redirectUrl, + clientId: ENVIRONMENT.microsoftClientID ?? '', + authority: 'https://login.microsoftonline.com/' + ENVIRONMENT.microsoftTenantID, + redirectUri: ENVIRONMENT.frontendUrl, }, cache: { cacheLocation: 'sessionStorage', diff --git a/packages/frontend/src/pages/login-page.tsx b/packages/frontend/src/pages/login-page.tsx index 69ff712..b8c1c36 100644 --- a/packages/frontend/src/pages/login-page.tsx +++ b/packages/frontend/src/pages/login-page.tsx @@ -1,73 +1,22 @@ -import React, { useState } from 'react' -import { GoogleLogin, GoogleLoginResponse, GoogleLoginResponseOffline } from 'react-google-login' - +import React from 'react' import { Container, Paragraph, Spacer, StyledLogo } from '@lara/components' -import AppHistory from '../app-history' -import { PrimaryButton } from '../components/button' -import { useLoginPageLoginMutation } from '../graphql' -import { useAuthentication } from '../hooks/use-authentication' import { Template } from '../templates/template' -import { SplashPage } from './splash-page' import { SignInButton } from '../components/ms-sign-in-button' const LoginPage: React.FunctionComponent = () => { - const { login } = useAuthentication() - const [mutate] = useLoginPageLoginMutation() - - const [authLoading, setAuthLoading] = useState(false) - - const onLoginSuccess = (googleResponse: GoogleLoginResponse | GoogleLoginResponseOffline) => { - setAuthLoading(true) - - if (!('getAuthResponse' in googleResponse)) { - return - } - const accessToken = googleResponse.getAuthResponse().access_token - console.log(accessToken) - mutate({ variables: { token: accessToken } }).then((response) => { - const { data } = response - if (!data?.login) { - return AppHistory.getInstance().push('/no-user-found') - } - - login(data.login) - }) - } - - const onLoginFailure = (error: string) => { - console.log('Login error', error) - return - } - - if (authLoading) { - return - } - return (