Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Gäller för:
Externa klienter (läs mer)
I den här självstudien får du lära dig hur du skapar en React-ensidesapp som registrerar användare med hjälp av den interna autentiseringens JavaScript SDK.
I den här handledningen kommer du att:
- Skapa ett React-Next.js projekt.
- Lägg till MSAL JS SDK i det.
- Lägg till UI-komponenter i appen.
- Konfigurera projektet för att registrera användare.
Förutsättningar
- Slutför stegen i Snabbstart: Logga in användare i en React-ensidesapp med hjälp av inbyggd autentisering med JavaScript SDK. Den här snabbstarten visar hur du kör ett exempel på React-kodexempel.
- Slutför stegen i Konfigurera CORS-proxyserver för att hantera CORS-huvuden för intern autentisering.
- Visual Studio Code eller någon annan kodredigerare.
- Node.js.
Skapa ett React-projekt och installera beroenden
På en valfri plats på datorn kör du följande kommandon för att skapa ett nytt React-projekt med namnet reactspa, navigera till projektmappen och installera paket:
npx create-next-app@latest
cd reactspa
npm install
När du har kört kommandona bör du ha en app med följande struktur:
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
Lägga till JavaScript SDK i projektet
Om du vill använda javascript-SDK för inbyggd autentisering i din app använder du terminalen för att installera den med hjälp av följande kommando:
npm install @azure/msal-browser
De inbyggda autentiseringsfunktionerna ingår i azure-msal-browser biblioteket. Om du vill använda inbyggda autentiseringsfunktioner importerar du från @azure/msal-browser/custom-auth. Till exempel:
import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";
Lägga till klientkonfiguration
I det här avsnittet definierar du en konfiguration för offentligt klientprogram för intern autentisering så att det kan interagera med SDK:ts gränssnitt. Det gör du genom att skapa en fil med namnet src/config/auth-config.ts och sedan lägga till följande kod:
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;
}
},
},
},
};
Leta rätt på platshållaren i koden:
Enter_the_Application_Id_Hereersätt den sedan med program-ID:t (klient) för den app som du registrerade tidigare.Enter_the_Tenant_Subdomain_Hereersätt den sedan med klientunderdomänen i administrationscentret för Microsoft Entra. Om din primära klientdomän till exempel ärcontoso.onmicrosoft.comanvänder ducontoso. Om du inte har namnet på din hyresgäst, lär hur du kan läsa detaljerna om din hyresgäst.
Skapa gränssnittskomponenter
Den här appen samlar in användarinformation som förnamn, användarnamn (e-post), lösenord och ett engångslösenord från användaren. Därför måste appen ha ett formulär som samlar in den här informationen.
Skapa en mapp med namnet src/app/sign-up i mappen src .
Skapa filen sign-up/components/InitialForm.tsx och klistra sedan in koden från sign-up/components/InitialForm.tsx. Den här komponenten visar ett formulär som samlar in användarinloggningsattribut.
Skapa en registrerings-/komponenter/CodeForm.tsx-fil och klistra sedan in koden från sign-up/components/CodeForm.tsx. Den här komponenten visar ett formulär som samlar in ett engångslösenord som skickas till användaren. Du behöver det här formuläret för e-post med lösenord eller e-post med engångsautentiseringsmetod för lösenord.
Om ditt val av autentiseringsmetod är e-post med lösenord skapar du en registrerings-/komponenter/PasswordForm.tsx-fil och klistrar sedan in koden från sign-up/components/PasswordForm.tsx. Den här komponenten visar ett formulär för lösenordsinmatning.
Hantera formulärinteraktion
I det här avsnittet lägger du till kod som hanterar interaktioner med registreringsformulär, till exempel att skicka information om användarregistrering eller ett engångslösenord eller ett lösenord.
Skapa sign-up/page.tsx för att hantera logik för ett registreringsflöde. I den här filen:
Importera nödvändiga komponenter och visa rätt formulär baserat på tillståndet. Se ett fullständigt exempel i sign-up/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> ); }Den här koden skapar också en instans av den offentliga klientappen för intern autentisering med hjälp av klientkonfigurationen:
const appInstance = await CustomAuthPublicClientApplication.create(customAuthConfig); setAuthClient(appInstance);Använd följande kodfragment för att hantera den inledande formuläröverföringen. Se ett fullständigt exempel på sign-up/page.tsx för att lära dig var kodfragmentet ska placeras:
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); };SDK:ts instansmetod
signUp()startar registreringsflödet.Använd följande kodfragment för att hantera sändning av engångslösenord. Se ett fullständigt exempel på sign-up/page.tsx för att lära dig var kodfragmentet ska placeras:
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); } };Använd följande kodfragment för att hantera lösenordsöverföring. Du hanterar lösenordsöverföring om ditt val av autentiseringsmetod är e-post med lösenord. Se ett fullständigt exempel på sign-up/page.tsx för att lära dig var kodfragmentet ska placeras:
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); };Använd för
signUpState instanceof SignUpCompletedStateatt ange att användaren har registrerats och att flödet är klart. Se ett fullständigt exempel på sign-up/page.tsx:if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage/>; }
Hantera problem med registrering
Under registreringen lyckas inte alla åtgärder. Användaren kan till exempel försöka registrera sig med en e-postadress som redan används eller skicka ett ogiltigt engångslösenord för e-post. Kontrollera att du hanterar fel korrekt när du:
Starta registreringsflödet i
signUp()metoden.Skicka engångslösenordet
submitCode()i metoden.Skicka lösenord i
submitPassword()-metoden. Du hanterar det här felet om ditt val av registreringsflöde sker via e-post och lösenord.
Ett av de fel som kan uppstå från signUp() metoden är result.error?.isRedirectRequired(). Det här scenariot inträffar när intern autentisering inte räcker för att slutföra autentiseringsflödet. Om auktoriseringsservern till exempel kräver funktioner som klienten inte kan tillhandahålla. Läs mer om webbåterställning för intern autentisering och hur du stöder webbåterställning i react-appen.
Valfritt: Logga in användare automatiskt efter registrering
När en användare har registrerat sig kan du logga in dem direkt i appen utan att initiera ett nytt inloggningsflöde. Om du vill göra det använder du följande kodfragment. Se ett fullständigt exempel på 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);
}
}
Köra och testa din app
Öppna ett terminalfönster och navigera till appens rotmapp:
cd reactspaStarta CORS-proxyservern genom att köra följande kommando i terminalen:
npm run corsStarta React-appen genom att öppna ett annat terminalfönster och sedan köra följande kommando:
cd reactspa npm startÖppna en webbläsare och navigera till
http://localhost:3000/sign-up. Ett registreringsformulär visas.Om du vill registrera dig för ett konto anger du din information, väljer knappen Fortsätt och följer sedan anvisningarna.
Sedan kan du uppdatera React-appen för att logga in på en användare eller återställa användarens lösenord.
Konfigurera poweredByHeader till false i next.config.js
Som standard x-powered-by ingår huvudet i HTTP-svaren för att indikera att programmet drivs av Next.js. Men av säkerhets- eller anpassningsskäl kanske du vill ta bort eller ändra det här huvudet:
const nextConfig: NextConfig = {
poweredByHeader: false,
/* other config options here */
};