[Feature] Aggiunto supporto OAuth2 client_credentials per Salesforce
Implementato il flusso OAuth2 grant_type=client_credentials come alternativa al flusso password gia' esistente per l'autenticazione Salesforce server-to-server. La modifica e' completamente retrocompatibile (default rimane Password). ## Dettaglio modifiche ### CredentialManager/Models/CredentialModels.cs - Aggiunto enum SalesforceGrantType con valori Password e ClientCredentials - Aggiunta proprieta' GrantType (default: Password) su RestApiCredential - Aggiunta proprieta' GrantType (default: Password) su SalesforceCredential ### DataConnection/REST/Configuration/RestServiceOptions.cs - Aggiunta proprieta' SalesforceGrantType per passare il tipo di flusso al client ### DataConnection/REST/Implementations/SalesforceServiceClient.cs - Iniettato ILogger<SalesforceServiceClient> con NullLogger come fallback - Sostituiti ~165 Console.WriteLine con chiamate ILogger appropriate (LogDebug per dettagli, LogInformation per eventi, LogWarning/LogError per problemi) - Aggiunto AuthenticateWithPasswordAsync: incapsula il flusso grant_type=password - Aggiunto AuthenticateWithClientCredentialsAsync: implementa grant_type=client_credentials (richiede solo ClientId e ClientSecret, nessun utente, URL My Domain obbligatorio) - Aggiunto SendTokenRequestAsync: helper condiviso per la POST al token endpoint - Aggiornato AuthenticateAsync() override: instrada al flusso corretto in base a GrantType - Rimosso modificatore static da NormalizeNumericValues (usava _logger, causava CS0120) ### Data_Coupler/Services/DataConnectionFactory.cs - Mappatura del campo GrantType dalle opzioni Salesforce a RestServiceOptions - Passaggio dell'ILogger al costruttore di SalesforceServiceClient ### CredentialManager/Services/CredentialService.cs - SaveRestApiCredentialAsync (blocco Salesforce): serializza GrantType in AdditionalParameters - SaveSalesforceCredentialAsync: aggiunto GrantType nel dizionario iniziale - MapToRestApiCredential: deserializza GrantType da AdditionalParameters con Enum.TryParse - MapToSalesforceCredential: idem per il tipo SalesforceCredential ### DataConnection/CredentialManagement/Services/DataConnectionCredentialService.cs - TestSalesforceOAuthLogin aggiornato: per ClientCredentials invia solo client_id e client_secret (senza username/password/security_token); per Password comportamento invariato ### Data_Coupler/Pages/CredentialManagement.razor - Aggiunto dropdown 'Tipo di Autenticazione OAuth2' nella sezione Salesforce - I campi Username, Password e Security Token vengono nascosti quando si seleziona il flusso ClientCredentials - Alert contestuale: warning My Domain URL per ClientCredentials, info per Password - GrantType propagato correttamente in EditRestApiCredential e TestRestApiConnectionFromModal ### AGENTS.md - Aggiunta sezione di documentazione per la nuova funzionalita' OAuth2 client_credentials
This commit is contained in:
@@ -663,11 +663,30 @@ else
|
||||
} <!-- Campi specifici per Salesforce -->
|
||||
@if (currentRestApiCredential.ServiceType == RestServiceType.Salesforce)
|
||||
{
|
||||
<div class="alert alert-info">
|
||||
<strong>Opzioni di Autenticazione:</strong><br/>
|
||||
• <strong>Username/Password + Security Token:</strong> Autenticazione standard<br/>
|
||||
• <strong>Username/Password + Client ID/Secret:</strong> Autenticazione OAuth<br/>
|
||||
• Il Security Token è richiesto solo se non si configura una Connected App (Client ID/Secret)
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<label class="form-label fw-semibold">Tipo di Autenticazione OAuth2</label>
|
||||
<InputSelect class="form-select" @bind-Value="currentRestApiCredential.GrantType">
|
||||
<option value="Password">Password Flow — Username + Password + Security Token (grant_type=password)</option>
|
||||
<option value="ClientCredentials">Client Credentials — Server-to-Server, nessun utente (grant_type=client_credentials)</option>
|
||||
</InputSelect>
|
||||
@if (currentRestApiCredential.GrantType == CredentialManager.Models.SalesforceGrantType.ClientCredentials)
|
||||
{
|
||||
<div class="alert alert-warning mt-2 py-2">
|
||||
<i class="fa fa-exclamation-triangle me-1"></i>
|
||||
<strong>client_credentials</strong>: il <strong>Base URL</strong> deve essere il <strong>My Domain URL</strong> della tua org
|
||||
(es. <code>https://myorg.my.salesforce.com</code>), <strong>non</strong> login.salesforce.com.<br/>
|
||||
Richiede: Connected App con "Enable Client Credentials Flow" attivato e un Integration User assegnato.
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="alert alert-info mt-2 py-2">
|
||||
<i class="fa fa-info-circle me-1"></i>
|
||||
<strong>password flow</strong>: Username, Password + Security Token. Client ID/Secret facoltativi (Connected App).
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@@ -687,11 +706,15 @@ else
|
||||
<div class="form-text">Esempio: 59.0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <div class="mb-3">
|
||||
<label class="form-label">@GetFieldLabel("SecurityToken", currentRestApiCredential.ServiceType)</label>
|
||||
<InputText type="password" class="form-control" @bind-Value="currentRestApiCredential.SecurityToken" />
|
||||
<div class="form-text">Token di sicurezza Salesforce (richiesto solo se non si usa OAuth o Connected App)</div>
|
||||
</div>
|
||||
@if (currentRestApiCredential.GrantType != CredentialManager.Models.SalesforceGrantType.ClientCredentials)
|
||||
{
|
||||
<div class="mb-3">
|
||||
<label class="form-label">@GetFieldLabel("SecurityToken", currentRestApiCredential.ServiceType)</label>
|
||||
<InputText type="password" class="form-control" @bind-Value="currentRestApiCredential.SecurityToken" />
|
||||
<div class="form-text">Token di sicurezza Salesforce (richiesto solo se non si usa OAuth o Connected App)</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
@@ -738,8 +761,9 @@ else
|
||||
}
|
||||
|
||||
<!-- Campi comuni per autenticazione username/password -->
|
||||
@if (currentRestApiCredential.ServiceType != RestServiceType.Generic ||
|
||||
(string.IsNullOrEmpty(currentRestApiCredential.ApiKey) && string.IsNullOrEmpty(currentRestApiCredential.AuthToken)))
|
||||
@if ((currentRestApiCredential.ServiceType != RestServiceType.Generic ||
|
||||
(string.IsNullOrEmpty(currentRestApiCredential.ApiKey) && string.IsNullOrEmpty(currentRestApiCredential.AuthToken))) &&
|
||||
!(currentRestApiCredential.ServiceType == RestServiceType.Salesforce && currentRestApiCredential.GrantType == CredentialManager.Models.SalesforceGrantType.ClientCredentials))
|
||||
{ <div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3">
|
||||
@@ -1312,6 +1336,7 @@ else
|
||||
ApiVersion = credential.ApiVersion,
|
||||
IsSandbox = credential.IsSandbox,
|
||||
UseSoapApi = credential.UseSoapApi,
|
||||
GrantType = credential.GrantType,
|
||||
RefreshToken = credential.RefreshToken,
|
||||
AccessToken = credential.AccessToken,
|
||||
TokenExpiry = credential.TokenExpiry
|
||||
@@ -1533,7 +1558,8 @@ else
|
||||
ClientSecret = currentRestApiCredential.ClientSecret,
|
||||
ApiVersion = currentRestApiCredential.ApiVersion,
|
||||
IsSandbox = currentRestApiCredential.IsSandbox,
|
||||
UseSoapApi = currentRestApiCredential.UseSoapApi
|
||||
UseSoapApi = currentRestApiCredential.UseSoapApi,
|
||||
GrantType = currentRestApiCredential.GrantType
|
||||
}; // Salviamo temporaneamente la credenziale per il test
|
||||
await CredentialService.SaveRestApiCredentialAsync(tempCredential);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user