Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Aplica-se a:
Locatários externos (saiba mais)
Neste tutorial, você aprenderá a criar um aplicativo de página única React que registra usuários utilizando o SDK JavaScript de autenticação nativa.
Neste tutorial, você:
- Crie um projeto do React Next.js.
- Adicione o SDK do JS da MSAL a ele.
- Adicione componentes de interface do usuário do aplicativo.
- Configure o projeto para inscrever usuários.
Pré-requisitos
- Conclua as etapas no Início Rápido: Conectar usuários em um aplicativo de página única do React usando o SDK javaScript de autenticação nativa. Este início rápido demonstra como executar um exemplo de código React.
- Conclua as etapas na configuração do servidor proxy CORS para gerenciar cabeçalhos CORS para autenticação nativa.
- Visual Studio Code ou qualquer outro editor de código.
- Node.js.
Criar um projeto do React e instalar dependências
Em um local de escolha no computador, execute os seguintes comandos para criar um novo projeto react com o nome reactspa, navegue até a pasta do projeto e instale os pacotes:
npx create-next-app@latest
cd reactspa
npm install
Depois de executar os comandos com êxito, você deverá ter um aplicativo com a seguinte estrutura:
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
Adicionar o SDK do JavaScript ao seu projeto
Para usar o SDK javaScript de autenticação nativa em seu aplicativo, use o terminal para instalá-lo usando o seguinte comando:
npm install @azure/msal-browser
Os recursos de autenticação nativa fazem parte da azure-msal-browser biblioteca. Para usar recursos de autenticação nativa, você importa de @azure/msal-browser/custom-auth. Por exemplo:
import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";
Adicionar configuração do cliente
Nesta seção, você definirá uma configuração para o aplicativo cliente público de autenticação nativa para permitir que ele interaja com a interface do SDK. Para fazer isso, crie um arquivo chamado src/config/auth-config.ts e adicione o seguinte código:
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;
}
},
},
},
};
No código, localize o espaço reservado:
Enter_the_Application_Id_Hereem seguida, substitua-o pela ID do aplicativo (cliente) do aplicativo que você registrou anteriormente.Enter_the_Tenant_Subdomain_Hereem seguida, substitua-o pelo subdomínio do inquilino no centro de administração do Microsoft Entra. Por exemplo, se o domínio primário do locatário forcontoso.onmicrosoft.com, usecontoso. Se você não tiver o nome do locatário, saiba como ler os detalhes do locatário.
Criar componentes de interface do usuário
Esse aplicativo coleta detalhes do usuário, como nome de usuário, nome de usuário (email), senha e senha única do usuário. Portanto, o aplicativo precisa ter um formulário que colete essas informações.
Crie uma pasta chamada src/app/sign-up na pasta src .
Crie um arquivo de inscrição/componentes/InitialForm.tsx e cole o código de inscrição/componentes/InitialForm.tsx. Esse componente exibe um formulário que coleta atributos de inscrição do usuário.
Crie um arquivo de inscrição/componentes/CodeForm.tsx e cole o código de inscrição/componentes/CodeForm.tsx. Esse componente exibe um formulário que coleta uma senha única enviada ao usuário. Você precisa desse formulário para email com senha ou email com método de autenticação de senha única.
Se sua opção de método de autenticação for email com senha, crie um arquivo de inscrição/componentes/PasswordForm.tsx e cole o código de inscrição/componentes/PasswordForm.tsx. Esse componente exibe um formulário de entrada de senha.
Gerenciar interação de formulário
Nesta seção, você adicionará um código que lida com interações do formulário de inscrição, como enviar detalhes de cadastro do usuário, um código de uso único ou uma senha.
Crie sign-up/page.tsx para lidar com a lógica de um fluxo de cadastro. Neste arquivo:
Importe os componentes necessários e exiba o formulário adequado com base no estado. Veja um exemplo completo em 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> ); }Esse código também cria uma instância do aplicativo cliente público de autenticação nativa usando a configuração do cliente:
const appInstance = await CustomAuthPublicClientApplication.create(customAuthConfig); setAuthClient(appInstance);Para lidar com o envio do formulário inicial, use o snippet de código a seguir. Veja um exemplo completo em inscreva-se/page.tsx para saber onde colocar o snippet de código:
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); };O método
signUp()de instância do SDK inicia o fluxo de inscrição.Para lidar com o envio de senha única, use o snippet de código a seguir. Veja um exemplo completo em inscreva-se/page.tsx para saber onde colocar o snippet de código:
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); } };Para lidar com o envio de senha, use o trecho de código a seguir. Você manipulará o envio de senha se sua opção de método de autenticação for email com senha. Veja um exemplo completo em inscreva-se/page.tsx para saber onde colocar o snippet de código:
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); };Use o
signUpState instanceof SignUpCompletedStatepara indicar que o usuário foi inscrito e que o fluxo está concluído. Veja um exemplo completo em inscreva-se/page.tsx:if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage/>; }
Tratar erros de inscrição
Durante a inscrição, nem todas as ações são bem-sucedidas. Por exemplo, o usuário pode tentar se inscrever com um endereço de email já usado ou enviar uma senha única de email inválida. Certifique-se de lidar com erros corretamente ao:
Inicie o processo de inscrição no método
signUp().Envie a senha única pelo método
submitCode().Enviar a senha com o método
submitPassword(). Você lidará com esse erro se sua opção de fluxo de inscrição for por email e senha.
Um dos erros que podem resultar do signUp() método é result.error?.isRedirectRequired(). Esse cenário ocorre quando a autenticação nativa não é suficiente para concluir o fluxo de autenticação. Por exemplo, se o servidor de autorização exigir recursos que o cliente não pode fornecer. Saiba mais sobre o fallback de autenticação nativa para a web e como oferecer suporte ao fallback para a web em seu aplicativo React.
Opcional: conectar usuários automaticamente após a inscrição
Depois que um usuário se inscreve com êxito, você pode conectá-lo diretamente ao aplicativo sem iniciar um novo fluxo de entrada. Para fazer isso, use o trecho de código a seguir. Veja um exemplo completo em inscreva-se/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);
}
}
Executar e testar seu aplicativo
Abra uma janela do terminal e navegue até a pasta raiz do aplicativo:
cd reactspaPara iniciar o servidor proxy CORS, execute o seguinte comando em seu terminal:
npm run corsPara iniciar o aplicativo React, abra outra janela do terminal e execute o seguinte comando:
cd reactspa npm startAbra um navegador da Web e navegue até
http://localhost:3000/sign-up. Um formulário de inscrição é exibido.Para se inscrever em uma conta, insira seus detalhes, selecione o botão Continuar e siga os prompts.
Em seguida, você pode atualizar o aplicativo React para conectar um usuário ou redefinir a senha do usuário.
Configurar poweredByHeader como false no next.config.js
Por padrão, o x-powered-by cabeçalho é incluído nas respostas HTTP para indicar que o aplicativo é alimentado por Next.js. No entanto, por motivos de segurança ou personalização, talvez você queira remover ou modificar este cabeçalho:
const nextConfig: NextConfig = {
poweredByHeader: false,
/* other config options here */
};