Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a: cerchio bianco tenant della forza lavoro
tenant esterni (altre)
Questa esercitazione illustra come reimpostare la password in un'app a pagina singola React usando l'autenticazione nativa.
In questa esercitazione, tu:
- Aggiornare l'app React per reimpostare la password dell'utente.
- Testare il flusso di reimpostazione della password
Prerequisiti
- Completare i passaggi descritti in Esercitazione: Configurare il server proxy CORS per gestire le intestazioni CORS per l'autenticazione nativa.
Definire i tipi di chiamate effettuate dall'app all'API di autenticazione nativa
Durante il flusso di reimpostazione della password, l'app effettua più chiamate all'API di autenticazione nativa, ad esempio l'avvio di una richiesta di reimpostazione della password e l'invio di un modulo di reimpostazione della password.
Per definire queste chiamate, aprire il file scr/client/RequestTypes.ts, quindi aggiungere il frammento di codice seguente:
export interface ResetPasswordStartRequest {
username: string;
challenge_type: string;
client_id: string;
}
export interface ResetPasswordSubmitRequest {
client_id: string;
continuation_token: string;
new_password: string;
}
export interface ResetPasswordSubmitForm {
continuation_token: string;
new_password: string;
}
Definire il tipo di risposte che l'app riceve dall'API di autenticazione nativa
Per definire il tipo di risposte che l'app può ricevere dall'API di autenticazione nativa per l'operazione di reimpostazione della password, aprire il file src/client/ResponseTypes.ts, quindi aggiungere il frammento di codice seguente:
export interface ChallengeResetResponse {
continuation_token: string;
expires_in: number;
}
export interface ResetPasswordSubmitResponse {
continuation_token: string;
poll_interval: number;
}
Elaborare le richieste di reimpostazione della password
In questa sezione viene aggiunto codice che elabora le richieste di flusso di reimpostazione della password. Esempi di queste richieste sono l'avvio di una richiesta di reimpostazione della password e l'invio di un modulo di reimpostazione della password.
A tale scopo, creare un file denominato src/client/ResetPasswordService.ts, quindi aggiungere il frammento di codice seguente:
import { CLIENT_ID, ENV } from "../config";
import { postRequest } from "./RequestClient";
import { ChallengeForm, ChallengeRequest, ResetPasswordStartRequest, ResetPasswordSubmitForm, ResetPasswordSubmitRequest } from "./RequestTypes";
import { ChallengeResetResponse, ChallengeResponse, ResetPasswordSubmitResponse } from "./ResponseTypes";
export const resetStart = async ({ username }: { username: string }) => {
const payloadExt: ResetPasswordStartRequest = {
username,
client_id: CLIENT_ID,
challenge_type: "password oob redirect",
};
return await postRequest(ENV.urlResetPwdStart, payloadExt);
};
export const resetChallenge = async ({ continuation_token }: { continuation_token: string }): Promise<ChallengeResponse> => {
const payloadExt: ChallengeRequest = {
continuation_token,
client_id: CLIENT_ID,
challenge_type: "oob redirect",
};
return await postRequest(ENV.urlResetPwdChallenge, payloadExt);
};
export const resetSubmitOTP = async (payload: ChallengeForm): Promise<ChallengeResetResponse> => {
const payloadExt = {
client_id: CLIENT_ID,
continuation_token: payload.continuation_token,
oob: payload.oob,
grant_type: "oob",
};
return await postRequest(ENV.urlResetPwdContinue, payloadExt);
};
export const resetSubmitNewPassword = async (payload: ResetPasswordSubmitForm): Promise<ResetPasswordSubmitResponse> => {
const payloadExt: ResetPasswordSubmitRequest = {
client_id: CLIENT_ID,
continuation_token: payload.continuation_token,
new_password: payload.new_password,
};
return await postRequest(ENV.urlResetPwdSubmit, payloadExt);
};
export const resetPoll = async (continuation_token: string): Promise<ChallengeResetResponse> => {
const payloadExt = {
client_id: CLIENT_ID,
continuation_token,
};
return await postRequest(ENV.urlResetPwdPollComp, payloadExt);
};
La proprietà challenge_type
mostra i metodi di autenticazione supportati dall'app client. Maggiori informazioni sui tipi di sfida .
Creare componenti dell'interfaccia utente
Durante il flusso di reimpostazione della password, questa app, in diverse schermate, raccoglie il nome utente dell'utente (posta elettronica), un passcode monouso e una nuova password utente.
Creare una cartella denominata /pages/resetpassword nella cartella src.
Per creare, visualizzare e inviare i moduli di reimpostazione della password, creare un file src/pages/resetpassword/ResetPassword.tsx, quindi aggiungere il codice seguente:
// ResetPassword.tsx import React, { useState } from "react"; import { resetChallenge, resetStart, resetSubmitNewPassword, resetSubmitOTP } from "../../client/ResetPasswordService"; import { ChallengeResetResponse, ChallengeResponse, ErrorResponseType } from "../../client/ResponseTypes"; export const ResetPassword: React.FC = () => { const [username, setUsername] = useState<string>(""); const [otp, setOTP] = useState<string>(""); const [newPassword, setNewPassword] = useState<string>(""); const [error, setError] = useState<string>(""); const [step, setStep] = useState<number>(1); const [isLoading, setIsloading] = useState<boolean>(false); const [tokenRes, setTokenRes] = useState<ChallengeResponse>({ binding_method: "", challenge_channel: "", challenge_target_label: "", challenge_type: "", code_length: 0, continuation_token: "", interval: 0, }); const [otpRes, setOTPRes] = useState<ChallengeResetResponse>({ expires_in: 0, continuation_token: "", }); const handleResetPassword = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); if (!username) { setError("Username is required"); return; } setError(""); try { setIsloading(true); const res1 = await resetStart({ username }); const tokenRes = await resetChallenge({ continuation_token: res1.continuation_token }); setTokenRes(tokenRes); setStep(2); } catch (err) { setError("An error occurred during password reset " + (err as ErrorResponseType).error_description); } finally { setIsloading(false); } }; const handleSubmitCode = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); if (!otp) { setError("All fields are required"); return; } setError(""); try { setIsloading(true); const res = await resetSubmitOTP({ continuation_token: tokenRes.continuation_token, oob: otp, }); setOTPRes(res); setStep(3); } catch (err) { setError("An error occurred while submitting the otp code " + (err as ErrorResponseType).error_description); } finally { setIsloading(false); } }; const handleSubmitNewPassword = async (e: React.FormEvent<HTMLFormElement>) => { e.preventDefault(); if (!newPassword) { setError('All fields are required'); return; } setError(''); try { setIsloading(true); await resetSubmitNewPassword({ continuation_token: otpRes.continuation_token, new_password: newPassword, }); setStep(4); } catch (err) { setError("An error occurred while submitting the new password " + (err as ErrorResponseType).error_description); } finally { setIsloading(false); } }; return ( <div className="reset-password-form"> //collect username to initiate password reset flow {step === 1 && ( <form onSubmit={handleResetPassword}> <h2>Reset Password</h2> <div className="form-group"> <label>Username:</label> <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} required /> </div> {error && <div className="error">{error}</div>} {isLoading && <div className="warning">Sending request...</div>} <button type="submit">Reset Password</button> </form> )} //collect OTP {step === 2 && ( <form onSubmit={handleSubmitCode}> <h2>Submit one time code received via email at {tokenRes.challenge_target_label}</h2> <div className="form-group"> <label>One time code:</label> <input type="text" maxLength={tokenRes.code_length} value={otp} onChange={(e) => setOTP(e.target.value)} required /> </div> {error && <div className="error">{error}</div>} {isLoading && <div className="warning">Sending request...</div>} <button type="submit">Submit code</button> </form> )} //Collect new password {step === 3 && ( <form onSubmit={handleSubmitNewPassword}> <h2>Submit New Password</h2> <div className="form-group"> <label>New Password:</label> <input type="password" value={newPassword} onChange={(e) => setNewPassword(e.target.value)} required /> </div> {error && <div className="error">{error}</div>} {isLoading && <div className="warning">Sending request...</div>} <button type="submit">Submit New Password</button> </form> )} //report success after password reset is successful {step === 4 && ( <div className="reset-password-success"> <h2>Password Reset Successful</h2> <p>Your password has been reset successfully. You can now log in with your new password.</p> </div> )} </div> ); };
Aggiungere percorsi dell'app
Aprire il file src/AppRoutes.tsx, quindi scommentare le righe di codice seguenti:
//uncomment
import { ResetPassword } from "./pages/ResetAccount/ResetPassword";
//...
export const AppRoutes = () => {
return (
<Routes>
//uncomment
<Route path="/reset" element={<ResetPassword />} />
</Routes>
);
};
Eseguire e testare l'app
Usare i passaggi descritti in Eseguire e testare l'app per eseguire l'app. Tuttavia, testate il flusso di reimpostazione della password solo usando l'account utente al quale ti sei registrato in precedenza.
Contenuto correlato
- Configurare un proxy inverso per un'app a pagina singola che usa l'API di autenticazione nativa usando l'app per le funzioni di Azure.
- Usare Azure Front Door come proxy inverso nell'ambiente di produzione per un'applicazione a pagina singola che utilizza l'autenticazione nativa.
- Riferimento all'API nativa di autenticazione.