Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Aplica-se a:
Inquilinos externos (saiba mais)
Neste tutorial, você aprenderá a criar um aplicativo de página única do React que inscreve usuários usando o SDK JavaScript da autenticação nativa.
Neste tutorial, você:
- Crie um projeto React Next.js.
- Adicione MSAL JS SDK a ele.
- Adicione componentes da interface do usuário do aplicativo.
- Configure o projeto para inscrever usuários.
Pré-requisitos
- Conclua as etapas em Guia de início rápido: entre usuários em um aplicativo de página única do React usando o JavaScript SDK de autenticação nativa. Este guia de início rápido mostra que você executa um exemplo de código React.
- Conclua as etapas em Configurar o servidor proxy CORS para gerenciar cabeçalhos CORS para autenticação nativa.
- Visual Studio Code ou outro editor de código.
- Node.js.
Criar um projeto React e instalar dependências
Em um local de escolha em seu computador, execute os seguintes comandos para criar um novo projeto React com o nome reactspa, navegue até a pasta do projeto e instale pacotes:
npx create-next-app@latest
cd reactspa
npm install
Depois de executar os comandos com êxito, você deve 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 JavaScript SDK ao seu projeto
Para usar o SDK JavaScript de autenticação nativa em seu aplicativo, use seu terminal para instalá-lo usando o seguinte comando:
npm install @azure/msal-browser
Os recursos de autenticação nativos fazem parte da azure-msal-browser biblioteca. Para usar recursos de autenticação nativos, importe do @azure/msal-browser/custom-auth. Por exemplo:
import CustomAuthPublicClientApplication from "@azure/msal-browser/custom-auth";
Adicionar configuração do cliente
Nesta seção, você define 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 pelo ID do aplicativo (cliente) do aplicativo que você registrou anteriormente.Enter_the_Tenant_Subdomain_Hereem seguida, substitua-o pelo subdomínio do locatário no centro de administração do Microsoft Entra. Por exemplo, se o domínio principal do arrendatário forcontoso.onmicrosoft.com, utilizecontoso. Se não tiver o nome do locatário, saiba como ler os detalhes do locatário.
Criar componentes da interface do usuário
Este aplicativo coleta detalhes do usuário, como nome próprio, nome de usuário (e-mail), senha e uma senha única do usuário. Então, o aplicativo precisa ter um formulário que colete essas informações.
Crie uma pasta chamada src/app/sign-up na pasta src .
Crie o arquivo sign-up/components/InitialForm.tsx e cole o código de sign-up/components/InitialForm.tsx. Este componente exibe um formulário que coleta atributos de inscrição do usuário.
Crie um arquivo sign-up/components/CodeForm.tsx e cole o código de sign-up/components/CodeForm.tsx. Este componente exibe um formulário que coleta uma senha única enviada ao usuário. Você precisa deste formulário para e-mail com senha ou e-mail com método de autenticação de senha única.
Se a sua escolha de método de autenticação for e-mail com senha, crie um arquivo de inscrição/components/PasswordForm.tsx e, em seguida, cole o código de sign-up/components/PasswordForm.tsx. Este componente exibe um formulário de entrada de senha.
Manipular a interação do formulário
Nesta seção, você adiciona código que lida com interações de formulário de inscrição, como o envio de detalhes de inscrição de usuário ou uma senha de uso único ou uma senha.
Crie sign-up/page.tsx para lidar com a lógica de um fluxo de inscrição. Neste ficheiro:
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 manipular o envio inicial do formulário, use o trecho de código a seguir. Veja um exemplo completo em sign-up/page.tsx para saber onde colocar o trecho 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 trecho de código a seguir. Veja um exemplo completo em sign-up/page.tsx para saber onde colocar o trecho 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 seguinte trecho de código. Você lida com o envio de senha se sua escolha de método de autenticação for e-mail com senha. Veja um exemplo completo em sign-up/page.tsx para saber onde colocar o trecho 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 o fluxo está concluído. Veja um exemplo completo em sign-up/page.tsx:if (signUpState instanceof SignUpCompletedState) { return <SignUpResultPage/>; }
Lidar com 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 e-mail já usado ou enviar uma senha única de e-mail inválida. Certifique-se de lidar com os erros corretamente quando:
Inicie o
signUp()fluxo de inscrição no método.Envie a senha única no
submitCode()método.Envie a senha no
submitPassword()método. Você lida com esse erro se sua escolha de fluxo de inscrição for por e-mail e senha.
Um dos erros que podem resultar do signUp() método é result.error?.isRedirectRequired(). Esse cenário acontece 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 da Web de autenticação nativa e como dar suporte ao fallback da Web em seu aplicativo React.
Opcional: Iniciar sessão de utilizadores automaticamente após a inscrição
Depois que um usuário se inscrever com êxito, você poderá conectá-lo diretamente ao aplicativo sem iniciar um novo fluxo de entrada. Para fazer isso, use o seguinte trecho de código. Veja um exemplo completo em 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);
}
}
Executar e testar seu aplicativo
Abra uma janela do terminal e navegue até a pasta raiz do seu aplicativo:
cd reactspaPara iniciar o servidor proxy CORS, execute o seguinte comando no 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. É apresentado um formulário de inscrição.Para se inscrever numa conta, introduza os seus dados, selecione o botão Continuar e, em seguida, siga as instruções.
Em seguida, poderá atualizar a aplicação React para autenticar um utilizador ou redefinir a senha do utilizador.
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, convém remover ou modificar este cabeçalho:
const nextConfig: NextConfig = {
poweredByHeader: false,
/* other config options here */
};