diff --git a/backend/src/controllers/v3/authController.ts b/backend/src/controllers/v3/authController.ts index 08ef7fa8d..69aa8874e 100644 --- a/backend/src/controllers/v3/authController.ts +++ b/backend/src/controllers/v3/authController.ts @@ -56,7 +56,10 @@ export const login1 = async (req: Request, res: Response) => { if (!user) throw new Error("Failed to find user"); - if (user.authProvider && user.authProvider !== AuthProvider.EMAIL) { + const shouldValidateProviderAuth = (user.authProvider && user.authProvider !== AuthProvider.EMAIL) + || (user.authProviders && !user.authProviders?.includes(AuthProvider.EMAIL)) + + if (shouldValidateProviderAuth) { await validateProviderAuthToken({ email, user, @@ -116,7 +119,10 @@ export const login2 = async (req: Request, res: Response) => { if (!user) throw new Error("Failed to find user"); - if (user.authProvider && user.authProvider !== AuthProvider.EMAIL) { + const shouldValidateProviderAuth = (user.authProvider && user.authProvider !== AuthProvider.EMAIL) + || (user.authProviders && !user.authProviders?.includes(AuthProvider.EMAIL)) + + if (shouldValidateProviderAuth) { await validateProviderAuthToken({ email, user, diff --git a/backend/src/helpers/auth.ts b/backend/src/helpers/auth.ts index eb6eeb4d2..f6b676a36 100644 --- a/backend/src/helpers/auth.ts +++ b/backend/src/helpers/auth.ts @@ -390,10 +390,13 @@ export const validateProviderAuthToken = async ({ jwt.verify(providerAuthToken, await getJwtProviderAuthSecret()) ); + const doesProviderMatch = (user.authProvider && user.authProvider === decodedToken.authProvider) + || (user.authProviders && user.authProviders.includes(decodedToken.authProvider)); + if ( - decodedToken.authProvider !== user.authProvider || + !doesProviderMatch || decodedToken.email !== email ) { throw new Error("Invalid authentication credentials.") } -} \ No newline at end of file +} diff --git a/backend/src/models/user.ts b/backend/src/models/user.ts index 77b8f522f..9251c487d 100644 --- a/backend/src/models/user.ts +++ b/backend/src/models/user.ts @@ -44,6 +44,9 @@ const userSchema = new Schema( type: String, enum: AuthProvider, }, + authProviders: [{ + type: String, + }], email: { type: String, required: true, diff --git a/backend/src/utils/auth.ts b/backend/src/utils/auth.ts index 8faba80bf..3fdd5915f 100644 --- a/backend/src/utils/auth.ts +++ b/backend/src/utils/auth.ts @@ -119,6 +119,7 @@ const initializePassport = async () => { firstName: user.firstName, lastName: user.lastName, authProvider: user.authProvider, + authProviders: user.authProviders, isUserCompleted, ...(req.query.state ? { callbackPort: req.query.state as string @@ -173,6 +174,7 @@ const initializePassport = async () => { firstName: user.firstName, lastName: user.lastName, authProvider: user.authProvider, + authProviders: user.authProviders, isUserCompleted, ...(req.query.state ? { callbackPort: req.query.state as string @@ -302,6 +304,7 @@ const initializePassport = async () => { lastName, organizationName: organization?.name, authProvider: user.authProvider, + authProviders: user.authProviders, isUserCompleted, ...(req.body.RelayState ? { callbackPort: req.body.RelayState as string diff --git a/frontend/src/views/Settings/PersonalSettingsPage/AuthMethodSection/AuthMethodSection.tsx b/frontend/src/views/Settings/PersonalSettingsPage/AuthMethodSection/AuthMethodSection.tsx index 6d874de0e..6e3b006e3 100644 --- a/frontend/src/views/Settings/PersonalSettingsPage/AuthMethodSection/AuthMethodSection.tsx +++ b/frontend/src/views/Settings/PersonalSettingsPage/AuthMethodSection/AuthMethodSection.tsx @@ -33,6 +33,10 @@ export const AuthMethodSection = () => { const { user } = useUser(); const { mutateAsync, isLoading } = useUpdateUserAuthProviders(); + const defaultAuthMethods = user.authProviders?.length ? + user.authProviders : + [user?.authProvider ?? "email"]; + const { reset, handleSubmit, @@ -40,7 +44,7 @@ export const AuthMethodSection = () => { watch, } = useForm({ defaultValues: { - authMethods: [user?.authProvider ?? "email"] + authMethods: defaultAuthMethods, }, resolver: yupResolver(schema) }); @@ -50,7 +54,7 @@ export const AuthMethodSection = () => { useEffect(() => { if (user) { reset({ - authMethods: [user?.authProvider ?? "email"] + authMethods: defaultAuthMethods, }); } }, [user]);