Skip to content

Commit ef78a07

Browse files
authored
feat: expose mfa setting for limiting aal1 sessions to 15 mins (supabase#35886)
* feat: expose mfa setting for limiting aal1 sessions to 15 mins * fix * fix types
1 parent 6490f6e commit ef78a07

File tree

1 file changed

+91
-2
lines changed

1 file changed

+91
-2
lines changed

apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
33
import { useEffect, useState } from 'react'
44
import { useForm } from 'react-hook-form'
55
import { toast } from 'sonner'
6-
import { number, object, string } from 'yup'
6+
import { number, object, string, boolean } from 'yup'
77

88
import { useParams } from 'common'
99
import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold'
@@ -32,6 +32,7 @@ import {
3232
SelectTrigger_Shadcn_,
3333
SelectValue_Shadcn_,
3434
Select_Shadcn_,
35+
Switch,
3536
WarningIcon,
3637
} from 'ui'
3738
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
@@ -79,6 +80,10 @@ const phoneSchema = object({
7980
MFA_PHONE_TEMPLATE: string().required('SMS template is required.'),
8081
})
8182

83+
const securitySchema = object({
84+
MFA_ALLOW_LOW_AAL: boolean().required(),
85+
})
86+
8287
const MfaAuthSettingsForm = () => {
8388
const { ref: projectRef } = useParams()
8489
const { data: authConfig, error: authConfigError, isError } = useAuthConfigQuery({ projectRef })
@@ -87,6 +92,7 @@ const MfaAuthSettingsForm = () => {
8792
// Separate loading states for each form
8893
const [isUpdatingTotpForm, setIsUpdatingTotpForm] = useState(false)
8994
const [isUpdatingPhoneForm, setIsUpdatingPhoneForm] = useState(false)
95+
const [isUpdatingSecurityForm, setIsUpdatingSecurityForm] = useState(false)
9096

9197
const [isConfirmationModalVisible, setIsConfirmationModalVisible] = useState(false)
9298

@@ -126,6 +132,13 @@ const MfaAuthSettingsForm = () => {
126132
},
127133
})
128134

135+
const securityForm = useForm({
136+
resolver: yupResolver(securitySchema),
137+
defaultValues: {
138+
MFA_ALLOW_LOW_AAL: false,
139+
},
140+
})
141+
129142
useEffect(() => {
130143
if (authConfig) {
131144
if (!isUpdatingTotpForm) {
@@ -150,8 +163,14 @@ const MfaAuthSettingsForm = () => {
150163
MFA_PHONE_TEMPLATE: authConfig?.MFA_PHONE_TEMPLATE || 'Your code is {{ .Code }}',
151164
})
152165
}
166+
167+
if (!isUpdatingSecurityForm) {
168+
securityForm.reset({
169+
MFA_ALLOW_LOW_AAL: authConfig?.MFA_ALLOW_LOW_AAL ?? true,
170+
})
171+
}
153172
}
154-
}, [authConfig, isUpdatingTotpForm, isUpdatingPhoneForm])
173+
}, [authConfig, isUpdatingTotpForm, isUpdatingPhoneForm, isUpdatingSecurityForm])
155174

156175
const onSubmitTotpForm = (values: any) => {
157176
const { verifyEnabled: MFA_TOTP_VERIFY_ENABLED, enrollEnabled: MFA_TOTP_ENROLL_ENABLED } =
@@ -181,6 +200,26 @@ const MfaAuthSettingsForm = () => {
181200
)
182201
}
183202

203+
const onSubmitSecurityForm = (values: any) => {
204+
const payload = { ...values }
205+
206+
setIsUpdatingSecurityForm(true)
207+
208+
updateAuthConfig(
209+
{ projectRef: projectRef!, config: payload },
210+
{
211+
onError: (error) => {
212+
toast.error(`Failed to update phone MFA settings: ${error?.message}`)
213+
setIsUpdatingSecurityForm(false)
214+
},
215+
onSuccess: () => {
216+
toast.success('Successfully updated phone MFA settings')
217+
setIsUpdatingSecurityForm(false)
218+
},
219+
}
220+
)
221+
}
222+
184223
const onSubmitPhoneForm = (values: any) => {
185224
let payload = { ...values }
186225

@@ -461,6 +500,7 @@ const MfaAuthSettingsForm = () => {
461500
</form>
462501
</Form_Shadcn_>
463502
</ScaffoldSection>
503+
464504
<ConfirmationModal
465505
visible={isConfirmationModalVisible}
466506
title="Confirm SMS MFA"
@@ -480,6 +520,55 @@ const MfaAuthSettingsForm = () => {
480520
customers are using SMS MFA.
481521
</p>
482522
</ConfirmationModal>
523+
524+
<ScaffoldSection isFullWidth>
525+
<ScaffoldSectionTitle className="mb-4">Enhanced MFA Security</ScaffoldSectionTitle>
526+
527+
<Form_Shadcn_ {...securityForm}>
528+
<form onSubmit={securityForm.handleSubmit(onSubmitSecurityForm)} className="space-y-4">
529+
<Card>
530+
<CardContent className="pt-6">
531+
<FormField_Shadcn_
532+
control={securityForm.control}
533+
name="MFA_ALLOW_LOW_AAL"
534+
render={({ field }) => (
535+
<FormItemLayout
536+
layout="flex-row-reverse"
537+
label="Limit duration of AAL1 sessions"
538+
description="A user's session will be terminated unless they verify one of their factors within 15 minutes of initial sign in. Recommendation: ON"
539+
>
540+
<FormControl_Shadcn_>
541+
<Switch
542+
checked={!field.value}
543+
onCheckedChange={(value) => field.onChange(!value)}
544+
disabled={!canUpdateConfig}
545+
/>
546+
</FormControl_Shadcn_>
547+
</FormItemLayout>
548+
)}
549+
/>
550+
</CardContent>
551+
<CardFooter className="justify-end space-x-2">
552+
{securityForm.formState.isDirty && (
553+
<Button type="default" onClick={() => securityForm.reset()}>
554+
Cancel
555+
</Button>
556+
)}
557+
<Button
558+
type="primary"
559+
htmlType="submit"
560+
disabled={
561+
!canUpdateConfig || isUpdatingSecurityForm || !securityForm.formState.isDirty
562+
}
563+
loading={isUpdatingPhoneForm}
564+
>
565+
Save changes
566+
</Button>
567+
</CardFooter>
568+
</Card>
569+
</form>
570+
</Form_Shadcn_>
571+
</ScaffoldSection>
483572
</>
484573
)
485574
}

0 commit comments

Comments
 (0)