Accesso e token

Come seguire questo capitolo

Dati richiesti: clientEmail, clientPassword e il codice di verifica ricevuto.

Passaggi e risultato atteso: Il primo fattore richiede la verifica; il secondo restituisce la sessione del cliente. Conserva entrambi i token dopo accesso o rinnovo. La disconnessione termina la sessione corrente.

Alternative e operazioni successive: Usa l’accesso per avviare una sessione. Rinnovo e disconnessione sono operazioni successive di gestione della sessione.

Codice sorgente dei DTO: AccessTokenOutputModel, AuthenticationSecondFactorOutputModel

Le variabili assegnate in un blocco precedente vengono riutilizzate nei successivi. I dati inseriti dal cliente provengono dalla tua interfaccia. Conserva identificativi e valori di riferimento nel contesto del cliente; non ricreare il contesto a ogni passaggio.

Gli esempi utilizzano classi helper condivise. Consulta Classi helper condivise: codice C# e Java completo prima di copiare un esempio.
Prima di iniziare: clientEmail e clientPassword esistenti. Inizia con un token GUEST e raccogli authenticationCode dal canale configurato per il secondo fattore.
Da conservare per il passaggio successivo: userId e i valori attuali accessToken, refreshToken e validUntil. Salva entrambi i nuovi token dopo ogni rinnovo.
Questo capitolo descrive l’autenticazione a due fattori. Il risultato è un token con il ruolo dell’utente (CLIENT, SELLER, ADMIN o SUPERADMIN). Conserva AccessToken, RefreshToken, Id e ValidUntil. Scadenza e periodo di rinnovo dipendono dal servizio.

Autenticazione a due fattori

Dati richiesti: E-mail e password del cliente, quindi authenticationCode ricevuto.
Operazione: Completa i due fattori di autenticazione.
Da conservare / risultato atteso: Conserva userId, accessToken, refreshToken e validUntil della risposta finale.
Usa un token GUEST nell’header Authorization. Dopo il primo fattore, raccogli il codice dal canale configurato per il conto. Una configurazione di test isolata può anche restituire il codice nella risposta. Per il conto cliente mostrato, il secondo fattore restituisce un token CLIENT per le chiamate successive.
								
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", guestToken);
// First factor authentication
var payload = JsonConvert.SerializeObject(new { AccountNumber = clientEmail, Password = clientPassword });
(await httpClient.PostAsync("api/v1/users/authentication/first-factor", new StringContent(payload, Encoding.UTF8, "application/json"))).EnsureSuccessStatusCode();
// Collect authenticationCode from the configured second-factor channel.
// Second factor authentication
payload = JsonConvert.SerializeObject(new { AccountNumber = clientEmail, Token = authenticationCode });
var httpResponseMessage = await httpClient.PostAsync("api/v1/users/authentication/second-factor", new StringContent(payload, Encoding.UTF8, "application/json"));
httpResponseMessage.EnsureSuccessStatusCode();
var resultAsString = await httpResponseMessage.Content.ReadAsStringAsync();
var authenticationResult = JsonConvert.DeserializeObject<AuthenticationSecondFactorOutputModel>(resultAsString);
// Now, set the CLIENT token for the next requests
var userId = authenticationResult.Id;
var accessToken = authenticationResult.AccessToken;
var refreshToken = authenticationResult.RefreshToken;
var validUntil = authenticationResult.ValidUntil;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

								
// First factor authentication
JsonObject firstFactorPayload = new JsonObject();
firstFactorPayload.addProperty("AccountNumber", clientEmail);
firstFactorPayload.addProperty("Password", clientPassword);

HttpRequest firstFactorRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("users/authentication/first-factor"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(firstFactorPayload.toString()))
    .build();

var firstFactorResponse = httpClient.send(firstFactorRequest, BodyHandlers.ofString());
Api.requireSuccess(firstFactorResponse);
// Collect authenticationCode from the configured second-factor channel.

// Second factor authentication
JsonObject secondFactorPayload = new JsonObject();
secondFactorPayload.addProperty("AccountNumber", clientEmail);
secondFactorPayload.addProperty("Token", authenticationCode);

HttpRequest secondFactorRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("users/authentication/second-factor"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(secondFactorPayload.toString()))
    .build();

var response = httpClient.send(secondFactorRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
AuthenticationSecondFactorOutputModel authenticationResult = new Gson().fromJson(response.body(), AuthenticationSecondFactorOutputModel.class);

// Now, set the CLIENT token for the next requests
var userId = authenticationResult.Id;
var accessToken = authenticationResult.AccessToken;
var refreshToken = authenticationResult.RefreshToken;
var validUntil = authenticationResult.ValidUntil;

Il canale del secondo fattore è configurato per il conto e l’ambiente. Usa il codice ricevuto dal cliente.

Disconnessione

Dati richiesti: Il token CLIENT attuale.
Operazione: Termina la sessione corrente.
Da conservare / risultato atteso: Elimina la sessione salvata dopo una disconnessione riuscita.
Questa operazione rende non valido il token di autenticazione.
								
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
(await httpClient.PostAsync("api/v1/users/authentication/logout", null)).EnsureSuccessStatusCode();

								
HttpRequest theRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("users/authentication/logout"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + accessToken)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

var response = httpClient.send(theRequest, BodyHandlers.ofString());
Api.requireSuccess(response);

Un token invalidato dalla disconnessione non può più essere rinnovato; è necessario un nuovo accesso.

Rinnovo del token di autenticazione

Dati richiesti: userId e la coppia attuale di access token e refresh token.
Operazione: Richiedi una sessione rinnovata.
Da conservare / risultato atteso: Sostituisci entrambi i token salvati e validUntil con i valori ricevuti.
Alla scadenza del token, le richieste protette restituiscono HTTP 401; il servizio può includere TOKEN-EXPIRED: true. Il rinnovo richiede la coppia attuale e l’ID dell’utente. La durata consentita è definita a partire dalla data di creazione salvata del token; non è una finestra fissa di cinque minuti dopo la scadenza.
Autorizza la richiesta con un token GUEST valido. Invia la coppia attuale nel payload, quindi sostituisci entrambi i token salvati con quelli ricevuti. In caso di errore, accedi nuovamente; non ripetere indefinitamente la richiesta con una coppia non valida.

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", guestToken);
payload = JsonConvert.SerializeObject(new
{
    UserId = userId,
    RefreshToken = refreshToken,
    AccessToken = accessToken
});
httpResponseMessage = await httpClient.PostAsync("api/v1/users/authentication/access-token/refresh", new StringContent(payload, Encoding.UTF8, "application/json"));
httpResponseMessage.EnsureSuccessStatusCode();
resultAsString = await httpResponseMessage.Content.ReadAsStringAsync();
var accessTokenOutputModel = JsonConvert.DeserializeObject<AccessTokenOutputModel>(resultAsString);
// Set new CLIENT token for the next HTTP requests
accessToken = accessTokenOutputModel.AccessToken;
refreshToken = accessTokenOutputModel.RefreshToken;
validUntil = accessTokenOutputModel.ValidUntil;
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

								
JsonObject thePayload = new JsonObject();
thePayload.addProperty("UserId", userId);
thePayload.addProperty("RefreshToken", refreshToken);
thePayload.addProperty("AccessToken", accessToken);

HttpRequest theRequest = HttpRequest.newBuilder()
    .timeout(Duration.ofMinutes(1))
    .uri(Settings.wmsUri("users/authentication/access-token/refresh"))
    .header("Accept-Language", "de-DE")
    .header("Authorization", "Bearer " + Settings.GUEST_TOKEN)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(thePayload.toString()))
    .build();

var response = httpClient.send(theRequest, BodyHandlers.ofString());
Api.requireSuccess(response);
AccessTokenOutputModel accessTokenOutputModel = new Gson().fromJson(response.body(), AccessTokenOutputModel.class);

// New CLIENT token for the next HTTP requests
accessToken = accessTokenOutputModel.AccessToken;
refreshToken = accessTokenOutputModel.RefreshToken;
validUntil = accessTokenOutputModel.ValidUntil;

Riconoscere il risultato

Dopo il secondo fattore o il rinnovo: sostituisci la coppia salvata. Si tratta di un estratto della risposta.

{"id":123,"accessToken":"<access-token>","refreshToken":"<refresh-token>","validUntil":"2026-10-13T12:00:00Z"}

Il catalogo DTO contiene le altre proprietà della risposta. Gestisci una richiesta non riuscita prima di proseguire; consulta Gestione degli errori.