Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Van toepassing op:
Externe tenants (meer informatie)
In deze zelfstudie leert u hoe u een React-app met één pagina bouwt waarmee gebruikers worden geregistreerd met behulp van de JavaScript SDK van systeemeigen verificatie.
In deze handleiding leert u:
- Een React Next.js-project maken.
- Voeg er MSAL JS SDK aan toe.
- Ui-onderdelen van de app toevoegen.
- Stel het project in om gebruikers te registreren.
Vereiste voorwaarden
- Voltooi de stappen in quickstart: Gebruikers aanmelden in een React-app met één pagina met behulp van de JavaScript SDK voor systeemeigen verificatie. In deze quickstart ziet u hoe u een Voorbeeld van React-code uitvoert.
- Voer de stappen uit in CORS-proxyserver instellen om CORS-headers te beheren voor systeemeigen verificatie.
- Visual Studio Code of een andere code-editor.
- Node.js.
- Als u wilt dat gebruikers zich aanmelden met een gebruikersnaam (alias), schakelt u het ingebouwde gebruikerskenmerk gebruikersnaam in uw gebruikersstroom voor registratie in. Zie Gebruikersnaam inschakelen in het aanmeldings-id-beleid voor de stappen.
Een React-project maken en afhankelijkheden installeren
Voer op een locatie naar keuze op uw computer de volgende opdrachten uit om een nieuw React-project te maken met de naam reactspa, navigeer naar de projectmap en installeer vervolgens pakketten:
npx create-next-app@latest
cd reactspa
npm install
Nadat u de opdrachten hebt uitgevoerd, moet u een app met de volgende structuur hebben:
spasample/
└──node_modules/
└──...
└──public/
└──...
└──src/
└──app/
└──favicon.ico
└──globals.css
└──page.tsx
└──layout.tsx
└──postcss.config.mjs
└──package-lock.json
└──package.json
└──tsconfig.json
└──README.md
└──next-env.d.ts
└──next.config.ts
JavaScript SDK toevoegen aan uw project
Als u de JavaScript SDK voor systeemeigen verificatie in uw app wilt gebruiken, gebruikt u de terminal om deze te installeren met behulp van de volgende opdracht:
npm install @azure/msal-browser
De systeemeigen verificatiemogelijkheden maken deel uit van de azure-msal-browser bibliotheek. Als u systeemeigen verificatiefuncties wilt gebruiken, importeert u uit @azure/msal-browser/custom-auth. Voorbeeld:
import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";
Clientconfiguratie toevoegen
In deze sectie definieert u een configuratie voor een openbare clienttoepassing voor systeemeigen verificatie, zodat deze kan communiceren met de interface van de SDK. Maak hiervoor een bestand met de naam src/config/auth-config.ts en voeg vervolgens de volgende code toe:
export const customAuthConfig: CustomAuthConfiguration = {
customAuth: {
challengeTypes: ["password", "oob", "redirect"],
authApiProxyUrl: "http://localhost:3001/api",
},
auth: {
clientId: "Enter_the_Application_Id_Here",
authority: "https://Enter_the_Tenant_Subdomain_Here.ciamlogin.com",
redirectUri: "/",
postLogoutRedirectUri: "/",
navigateToLoginRequestUrl: false,
},
cache: {
cacheLocation: "sessionStorage",
},
system: {
loggerOptions: {
loggerCallback: (
level: LogLevel,
message: string,
containsPii: boolean
) => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
}
},
},
},
};
Zoek in de code de plaatsaanduiding:
Enter_the_Application_Id_Herevervang deze vervolgens door de toepassings-id (client) van de app die u eerder hebt geregistreerd.Enter_the_Tenant_Subdomain_Herevervang dit vervolgens door het tenantsubdomein in uw Microsoft Entra-beheercentrum. Als uw primaire tenantdomein bijvoorbeeld iscontoso.onmicrosoft.com, gebruikt ucontoso. Indien u uw tenantnaam niet hebt, leer dan hoe u de details van uw tenant kunt lezen.
UI-onderdelen maken
Deze app verzamelt gebruikersgegevens, zoals de opgegeven naam, de gebruikersnaam (e-mail), het wachtwoord en een eenmalige wachtwoordcode van de gebruiker. De app moet dus een formulier hebben waarmee deze gegevens worden verzameld.
Maak een map met de naam src/app/sign-up in de src-map .
Maak het bestand sign-up/components/InitialForm.tsx en plak de code uit sign-up/components/InitialForm.tsx. In dit onderdeel wordt een formulier weergegeven waarin gebruikersaanmeldingskenmerken worden verzameld.
Maak een registratie/components/CodeForm.tsx-bestand en plak de code uit registratie/onderdelen/CodeForm.tsx. In dit onderdeel wordt een formulier weergegeven waarin een eenmalige wachtwoordcode wordt verzameld die naar de gebruiker wordt verzonden. U hebt dit formulier nodig voor e-mail met een wachtwoord of e-mail met een eenmalige verificatiemethode voor wachtwoordcodes.
Als uw keuze voor de verificatiemethode e-mail is met een wachtwoord, maakt u een registratie-/onderdelen-/PasswordForm.tsx-bestand en plakt u de code uit registratie/components/PasswordForm.tsx. In dit onderdeel wordt een wachtwoordinvoerformulier weergegeven.
Formulierinteracties afhandelen
In deze sectie voegt u code toe die interactie tussen registratieformulieren afhandelt, zoals het verzenden van gebruikersgegevens of een eenmalige wachtwoordcode of een wachtwoord.
Maak sign-up/page.tsx aan om de logica voor een aanmeldproces af te handelen. In dit bestand:
Importeer de benodigde onderdelen en geef het juiste formulier weer op basis van de status. Bekijk een volledig voorbeeld in registratie/page.tsx:
import { useEffect, useState } from "react"; import { customAuthConfig } from "../../config/auth-config"; import { styles } from "./styles/styles"; import { InitialFormWithPassword } from "./components/InitialFormWithPassword"; import { CustomAuthPublicClientApplication, ICustomAuthPublicClientApplication, SignUpCodeRequiredState, // Uncomment if your choice of authentication method is email with password // SignUpPasswordRequiredState, SignUpCompletedState, AuthFlowStateBase, } from "@azure/msal-browser/custom-auth"; import { SignUpResultPage } from "./components/SignUpResult"; import { CodeForm } from "./components/CodeForm"; import { PasswordForm } from "./components/PasswordForm"; export default function SignUpPassword() { const [authClient, setAuthClient] = useState<ICustomAuthPublicClientApplication | null>(null); const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [jobTitle, setJobTitle] = useState(""); const [city, setCity] = useState(""); const [country, setCountry] = useState(""); const [email, setEmail] = useState(""); //Uncomment if your choice of authentication method is email with password //const [password, setPassword] = useState(""); const [code, setCode] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(false); const [signUpState, setSignUpState] = useState<AuthFlowStateBase | null>(null); const [loadingAccountStatus, setLoadingAccountStatus] = useState(true); const [isSignedIn, setSignInState] = useState(false); useEffect(() => { const initializeApp = async () => { const appInstance = await CustomAuthPublicClientApplication.create(customAuthConfig); setAuthClient(appInstance); }; initializeApp(); }, []); useEffect(() => { const checkAccount = async () => { if (!authClient) return; const accountResult = authClient.getCurrentAccount(); if (accountResult.isCompleted()) { setSignInState(true); } setLoadingAccountStatus(false); }; checkAccount(); }, [authClient]); const renderForm = () => { if (loadingAccountStatus) { return; } if (isSignedIn) { return ( <div style={styles.signed_in_msg}>Please sign out before processing the sign up.</div> ); } if (signUpState instanceof SignUpCodeRequiredState) { return ( <CodeForm onSubmit={handleCodeSubmit} code={code} setCode={setCode} loading={loading} /> ); } //Uncomment the following block of code if your choice of authentication method is email with password /* else if(signUpState instanceof SignUpPasswordRequiredState) { return <PasswordForm onSubmit={handlePasswordSubmit} password={password} setPassword={setPassword} loading={loading} />; } */ else if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage />; } else { return ( <InitialForm onSubmit={handleInitialSubmit} firstName={firstName} setFirstName={setFirstName} lastName={lastName} setLastName={setLastName} jobTitle={jobTitle} setJobTitle={setJobTitle} city={city} setCity={setCity} country={country} setCountry={setCountry} email={email} setEmail={setEmail} loading={loading} /> ); } } return ( <div style={styles.container}> <h2 style={styles.h2}>Sign Up</h2> {renderForm()} {error && <div style={styles.error}>{error}</div>} </div> ); }Met deze code wordt ook een exemplaar van de openbare client-app voor systeemeigen verificatie gemaakt met behulp van de clientconfiguratie:
const appInstance = await CustomAuthPublicClientApplication.create(customAuthConfig); setAuthClient(appInstance);Gebruik het volgende codefragment om de inzending van het formulier af te handelen. Zie een volledig voorbeeld op sign-up/page.tsx voor meer informatie over het plaatsen van het codefragment:
const handleInitialSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); if (!authClient) return; const attributes: UserAccountAttributes = { displayName: `${firstName} ${lastName}`, givenName: firstName, surname: lastName, jobTitle: jobTitle, city: city, country: country, }; const result = await authClient.signUp({ username: email, attributes }); const state = result.state; if (result.isFailed()) { if (result.error?.isUserAlreadyExists()) { setError("An account with this email already exists"); } else if (result.error?.isInvalidUsername()) { setError("Invalid uername"); } else if (result.error?.isInvalidPassword()) { setError("Invalid password"); } else if (result.error?.isAttributesValidationFailed()) { setError("Invalid attributes"); } else if (result.error?.isMissingRequiredAttributes()) { setError("Missing required attributes"); } else { setError(result.error?.errorData.errorDescription || "An error occurred while signing up"); } } else { setSignUpState(state); } setLoading(false); };De instantiemethode
signUp()van de SDK start de registratiestroom.Gebruik het volgende codefragment om de eenmalige wachtwoordcode te verwerken. Zie een volledig voorbeeld op sign-up/page.tsx voor meer informatie over het plaatsen van het codefragment:
const handleCodeSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); try { if (signUpState instanceof SignUpCodeRequiredState) { const result = await signUpState.submitCode(code); if (result.error) { if (result.error.isInvalidCode()) { setError("Invalid verification code"); } else { setError("An error occurred while verifying the code"); } return; } if (result.state instanceof SignUpCompletedState) { setSignUpState(result.state); } } } catch (err) { setError("An unexpected error occurred"); console.error(err); } finally { setLoading(false); } };Gebruik het volgende codefragment om het verzenden van wachtwoorden af te handelen. U kunt het verzenden van wachtwoorden afhandelen als uw keuze voor verificatiemethode e-mail is met een wachtwoord. Zie een volledig voorbeeld op sign-up/page.tsx voor meer informatie over het plaatsen van het codefragment:
const handlePasswordSubmit = async (e: React.FormEvent) => { e.preventDefault(); setError(""); setLoading(true); if (signUpState instanceof SignUpPasswordRequiredState) { const result = await signUpState.submitPassword(password); const state = result.state; if (result.isFailed()) { if (result.error?.isInvalidPassword()) { setError("Invalid password"); } else { setError(result.error?.errorData.errorDescription || "An error occurred while submitting the password"); } } else { setSignUpState(state); } } setLoading(false); };Gebruik de
signUpState instanceof SignUpCompletedStatefunctie om aan te geven dat de gebruiker is geregistreerd en dat de stroom is voltooid. Bekijk een volledig voorbeeld op sign-up/page.tsx:if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage/>; }
Een gebruikersnaam (alias) verzamelen tijdens het registreren
U kunt gebruikers zich laten registreren met een gebruikersnaam (alias) naast hun e-mailadres. De gebruikersnaam (alias) is een alternatieve aanmeldings-id, zoals een klant-id, accountnummer of een andere waarde die u kiest.
Tijdens het registreren is de gebruikersnaam (e-mail) altijd vereist als primaire id en vervangt de gebruikersnaam (alias) deze niet. De gebruikersnaam (alias) is standaard optioneel, hoewel een beheerder deze naar behoefte kan configureren. Uw app verzamelt altijd de gebruikersnaam (e-mail) en verzamelt de alias als een kenmerk naast de e-mail. Bij het aanmelden kan de gebruiker zich vervolgens aanmelden met de gebruikersnaam (e-mail) of de gebruikersnaam (alias). Zie Gebruikersinvoertypen en pagina-indeling configureren voor meer informatie over hoe het kenmerk Gebruikersnaam is geconfigureerd als optioneel of vereist.
Een gebruikersnaam (alias) verzamelen tijdens het registreren:
Zorg ervoor dat het ingebouwde gebruikerskenmerk gebruikersnaam is ingeschakeld in de gebruikersstroom voor registratie. Zie Gebruikersnaam inschakelen in het aanmeldings-id-beleid voor de stappen.
Voeg een
flatUsernamestatus toe aan de aanmeldpagina en neem vervolgens hetflatusername-kenmerk op in deUserAccountAttributesdie je doorgeeft aansignUp():const [flatUsername, setFlatUsername] = useState(""); const attributes: UserAccountAttributes = { displayName: `${firstName} ${lastName}`, //... flatusername: flatUsername, };Voeg een aliasinvoer toe aan InitialForm.tsx om de gebruikersnaamwaarde (alias) te verzamelen:
<input type="text" placeholder="Username (alias)" value={flatUsername} onChange={(e) => setFlatUsername(e.target.value)} style={styles.input} />Omgaan met fouten met betrekking tot de gebruikersnaam (alias):
-
result.error?.isUserAlreadyExists()behandelt een dubbele e-mail of een dubbele gebruikersnaam (alias). Werk het bericht dienovereenkomstig bij, bijvoorbeeld een account met deze e-mail of gebruikersnaam bestaat al. - Een ongeldige gebruikersnaam (alias) wordt weergegeven via
result.error?.isAttributesValidationFailed()in plaats van viaresult.error?.isInvalidUsername(). Maak in deze methode onderscheid om een bericht specifiek voor de gebruikersnaam weer te geven.
-
Registratiefouten afhandelen
Tijdens het registreren slagen niet alle acties. De gebruiker kan bijvoorbeeld proberen zich aan te melden met een al gebruikt e-mailadres of een ongeldige wachtwoordcode voor eenmalige e-mail verzenden. Zorg ervoor dat u fouten correct afhandelt wanneer u het volgende doet:
Start het registratieproces in de
signUp()methode.Verzend de eenmalige wachtwoordcode in de
submitCode()methode.Dien een wachtwoord in de
submitPassword()methode in. U kunt deze fout afhandelen als uw keuze voor registratiestroom per e-mail en wachtwoord is.
Een van de fouten die kunnen voortvloeien uit de signUp() methode is result.error?.isRedirectRequired(). Dit scenario treedt op wanneer systeemeigen verificatie niet voldoende is om de verificatiestroom te voltooien. Als de autorisatieserver bijvoorbeeld mogelijkheden vereist die de client niet kan bieden. Meer informatie over webfallback voor systeemeigen verificatie en hoe u webfallback kunt ondersteunen in uw React-app.
Optioneel: Gebruikers automatisch aanmelden na aanmelding
Nadat een gebruiker zich heeft geregistreerd, kunt u deze rechtstreeks aanmelden bij de app zonder een nieuwe aanmeldingsstroom te starten. Gebruik hiervoor het volgende codefragment. Bekijk een volledig voorbeeld op sign-up/page.tsx:
if (signUpState instanceof SignUpCompletedState) {
const result = await signUpState.signIn();
const state = result.state;
if (result.isFailed()) {
setError(result.error?.errorData?.errorDescription || "An error occurred during auto sign-in");
}
if (result.isCompleted()) {
setData(result.data);
setSignUpState(state);
}
}
Uw app uitvoeren en testen
Open een terminalvenster en navigeer naar de hoofdmap van uw app:
cd reactspaVoer de volgende opdracht uit in de terminal om de CORS-proxyserver te starten:
npm run corsAls u de React-app wilt starten, opent u een ander terminalvenster en voert u vervolgens de volgende opdracht uit:
cd reactspa npm startOpen een webbrowser en navigeer naar
http://localhost:3000/sign-up. Er wordt een registratieformulier weergegeven.Als u zich wilt registreren voor een account, voert u uw gegevens in, selecteert u de knop Doorgaan en volgt u de aanwijzingen.
Vervolgens kunt u de React-app bijwerken om u aan te melden bij een gebruiker of het wachtwoord van de gebruiker opnieuw in te stellen.
PoweredByHeader instellen op false in next.config.js
De header is standaard x-powered-by opgenomen in de HTTP-antwoorden om aan te geven dat de toepassing wordt aangedreven door Next.js. Om veiligheids- of aanpassingsredenen wilt u deze header echter verwijderen of wijzigen:
const nextConfig: NextConfig = {
poweredByHeader: false,
/* other config options here */
};