;
-}) => {
- return (
- <>
-
-
- Connect via Credentials
-
-
- Please provide the information for your Microsoft 365 credentials.
-
-
-
-
-
-
- {" "}
- User and password authentication is being deprecated due to
- Microsoft's on-going MFA enforcement across all tenants (see{" "}
-
- Microsoft docs
-
- ).
-
-
-
-
-
- By October 2025, MFA will be mandatory.
-
-
-
- Due to that change, you must only{" "}
-
- use application authentication
- {" "}
- to maintain all Prowler M365 scan capabilities.
-
-
-
- >
- );
-};
diff --git a/ui/hooks/use-credentials-form.ts b/ui/hooks/use-credentials-form.ts
index 268d714d71..2690b9307a 100644
--- a/ui/hooks/use-credentials-form.ts
+++ b/ui/hooks/use-credentials-form.ts
@@ -40,8 +40,8 @@ export const useCredentialsForm = ({
if (providerType === "gcp" && via === "service-account") {
return addCredentialsServiceAccountFormSchema(providerType);
}
- // For GitHub, we need to pass the via parameter to determine which fields are required
- if (providerType === "github") {
+ // For GitHub and M365, we need to pass the via parameter to determine which fields are required
+ if (providerType === "github" || providerType === "m365") {
return addCredentialsFormSchema(providerType, via);
}
return addCredentialsFormSchema(providerType);
@@ -99,13 +99,27 @@ export const useCredentialsForm = ({
[ProviderCredentialFields.TENANT_ID]: "",
};
case "m365":
+ // M365 credentials based on via parameter
+ if (via === "app_client_secret") {
+ return {
+ ...baseDefaults,
+ [ProviderCredentialFields.CLIENT_ID]: "",
+ [ProviderCredentialFields.CLIENT_SECRET]: "",
+ [ProviderCredentialFields.TENANT_ID]: "",
+ };
+ }
+ if (via === "app_certificate") {
+ return {
+ ...baseDefaults,
+ [ProviderCredentialFields.CLIENT_ID]: "",
+ [ProviderCredentialFields.CERTIFICATE_CONTENT]: "",
+ [ProviderCredentialFields.TENANT_ID]: "",
+ };
+ }
return {
...baseDefaults,
[ProviderCredentialFields.CLIENT_ID]: "",
- [ProviderCredentialFields.CLIENT_SECRET]: "",
[ProviderCredentialFields.TENANT_ID]: "",
- [ProviderCredentialFields.USER]: "",
- [ProviderCredentialFields.PASSWORD]: "",
};
case "gcp":
return {
@@ -146,9 +160,14 @@ export const useCredentialsForm = ({
}
};
+ const defaultValues = getDefaultValues();
+
const form = useForm({
resolver: zodResolver(formSchema),
- defaultValues: getDefaultValues(),
+ defaultValues: defaultValues,
+ mode: "onSubmit",
+ reValidateMode: "onChange",
+ criteriaMode: "all", // Show all errors for each field
});
const { handleServerResponse } = useFormServerErrors(
@@ -169,6 +188,7 @@ export const useCredentialsForm = ({
// Filter out empty values first, then append all remaining values
const filteredValues = filterEmptyValues(values);
+
Object.entries(filteredValues).forEach(([key, value]) => {
formData.append(key, value);
});
@@ -181,9 +201,12 @@ export const useCredentialsForm = ({
}
};
+ const { isSubmitting, errors } = form.formState;
+
return {
form,
- isLoading: form.formState.isSubmitting,
+ isLoading: isSubmitting,
+ errors,
handleSubmit,
handleBackStep,
searchParamsObj,
diff --git a/ui/types/components.ts b/ui/types/components.ts
index 98197ea17b..c02440c2ae 100644
--- a/ui/types/components.ts
+++ b/ui/types/components.ts
@@ -213,15 +213,24 @@ export type AzureCredentials = {
[ProviderCredentialFields.PROVIDER_ID]: string;
};
-export type M365Credentials = {
+export type M365ClientSecretCredentials = {
[ProviderCredentialFields.CLIENT_ID]: string;
[ProviderCredentialFields.CLIENT_SECRET]: string;
[ProviderCredentialFields.TENANT_ID]: string;
- [ProviderCredentialFields.USER]?: string;
- [ProviderCredentialFields.PASSWORD]?: string;
[ProviderCredentialFields.PROVIDER_ID]: string;
};
+export type M365CertificateCredentials = {
+ [ProviderCredentialFields.CLIENT_ID]: string;
+ [ProviderCredentialFields.CERTIFICATE_CONTENT]: string;
+ [ProviderCredentialFields.TENANT_ID]: string;
+ [ProviderCredentialFields.PROVIDER_ID]: string;
+};
+
+export type M365Credentials =
+ | M365ClientSecretCredentials
+ | M365CertificateCredentials;
+
export type GCPDefaultCredentials = {
client_id: string;
client_secret: string;