Editar o perfil em um aplicativo Web Node.js
Aplica-se a: Locatários da força de trabalho Locatários externos (saiba mais)
Esse artigo é a parte 2 de uma série que demonstra como adicionar a lógica de edição de perfil em um aplicativo Web Node.js. Na parte 1 dessa série, você configurou seu aplicativo para edição de perfil.
Neste guia de instruções, você aprenderá a chamar a API do Microsoft Graph para edição de perfil.
Pré-requisitos
- Complete as etapas na segunda parte desta série de guias, Configurar um aplicativo Web Node.js para edição de perfil.
Concluir o aplicativo Web cliente
Nesta seção, você adicionará o código relacionado à identidade para o aplicativo Web cliente.
Atualizar o arquivo authConfig.js
Atualize o arquivo authConfig.js para o aplicativo Web cliente:
No seu editor de código, abra o arquivo App/authConfig.js, depois adicione três novas variáveis,
GRAPH_API_ENDPOINT
,GRAPH_ME_ENDPOINT
eeditProfileScope
. Certifique-se de exportar as três variáveis://... const GRAPH_API_ENDPOINT = process.env.GRAPH_API_ENDPOINT || "https://graph.microsoft.com/"; // https://learn.microsoft.com/graph/api/user-update?tabs=http const GRAPH_ME_ENDPOINT = GRAPH_API_ENDPOINT + "v1.0/me"; const editProfileScope = process.env.EDIT_PROFILE_FOR_CLIENT_WEB_APP || 'api://{clientId}/EditProfileService.ReadWrite'; module.exports = { //... editProfileScope, GRAPH_API_ENDPOINT, GRAPH_ME_ENDPOINT, //... };
A variável
editProfileScope
representa o recurso protegido por MFA, que é o aplicativo de nível intermediário (aplicativo EditProfileService).O
GRAPH_ME_ENDPOINT
é o ponto de extremidade da API do Microsoft Graph.
Substitua o espaço reservado
{clientId}
pela ID do aplicativo (cliente) do aplicativo de nível intermediário (aplicativo EditProfileService) que você registrou anteriormente.
Adquirir o token de acesso no aplicativo Web cliente
No seu editor de código, abra o arquivo App/auth/AuthProvider.js, depois atualize o método getToken
na classe AuthProvider
:
class AuthProvider {
//...
getToken(scopes, redirectUri = "http://localhost:3000/") {
return async function (req, res, next) {
const msalInstance = authProvider.getMsalInstance(authProvider.config.msalConfig);
try {
msalInstance.getTokenCache().deserialize(req.session.tokenCache);
const silentRequest = {
account: req.session.account,
scopes: scopes,
};
const tokenResponse = await msalInstance.acquireTokenSilent(silentRequest);
req.session.tokenCache = msalInstance.getTokenCache().serialize();
req.session.accessToken = tokenResponse.accessToken;
next();
} catch (error) {
if (error instanceof msal.InteractionRequiredAuthError) {
req.session.csrfToken = authProvider.cryptoProvider.createNewGuid();
const state = authProvider.cryptoProvider.base64Encode(
JSON.stringify({
redirectTo: redirectUri,
csrfToken: req.session.csrfToken,
})
);
const authCodeUrlRequestParams = {
state: state,
scopes: scopes,
};
const authCodeRequestParams = {
state: state,
scopes: scopes,
};
authProvider.redirectToAuthCodeUrl(
req,
res,
next,
authCodeUrlRequestParams,
authCodeRequestParams,
msalInstance
);
}
next(error);
}
};
}
}
//...
O método getToken
usa o escopo especificado para adquirir um token de acesso. O parâmetro redirectUri
é a URL de redirecionamento depois que o aplicativo adquire um token de acesso.
Atualizar o arquivo users.js
No seu editor de código, abra o arquivo App/routes/users.js, depois adicione as seguintes rotas:
//...
var { fetch } = require("../fetch");
const { GRAPH_ME_ENDPOINT, editProfileScope } = require('../authConfig');
//...
router.get(
"/gatedUpdateProfile",
isAuthenticated,
authProvider.getToken(["User.Read"]), // check if user is authenticated
async function (req, res, next) {
const graphResponse = await fetch(
GRAPH_ME_ENDPOINT,
req.session.accessToken,
);
if (!graphResponse.id) {
return res
.status(501)
.send("Failed to fetch profile data");
}
res.render("gatedUpdateProfile", {
profile: graphResponse,
});
},
);
router.get(
"/updateProfile",
isAuthenticated, // check if user is authenticated
authProvider.getToken(
["User.Read", editProfileScope],
"http://localhost:3000/users/updateProfile",
),
async function (req, res, next) {
const graphResponse = await fetch(
GRAPH_ME_ENDPOINT,
req.session.accessToken,
);
if (!graphResponse.id) {
return res
.status(501)
.send("Failed to fetch profile data");
}
res.render("updateProfile", {
profile: graphResponse,
});
},
);
router.post(
"/update",
isAuthenticated,
authProvider.getToken([editProfileScope]),
async function (req, res, next) {
try {
if (!!req.body) {
let body = req.body;
fetch(
"http://localhost:3001/updateUserInfo",
req.session.accessToken,
"POST",
{
displayName: body.displayName,
givenName: body.givenName,
surname: body.surname,
},
)
.then((response) => {
if (response.status === 204) {
return res.redirect("/");
} else {
next("Not updated");
}
})
.catch((error) => {
console.log("error,", error);
});
} else {
throw { error: "empty request" };
}
} catch (error) {
next(error);
}
},
);
//...
Você disparará a rota
/gatedUpdateProfile
quando o usuário cliente seleciona o link Edição de perfil. O aplicativo:- Adquirir um token de acesso com a permissão User.Read.
- Faz uma chamada à API do Microsoft Graph para ler o perfil do usuário conectado.
- Exibe os detalhes do usuário na interface do usuário gatedUpdateProfile.hbs.
Você acionará a rota
/updateProfile
quando o usuário desejar atualizar o nome de exibição, ou seja, selecionar o botão Editar perfil. O aplicativo:- Faz uma chamada para o aplicativo de nível intermediário (aplicativo EditProfileService) usando o escopo editProfileScope. Ao fazer uma chamada para o aplicativo de nível intermediário (aplicativo EditProfileService), o usuário deverá concluir um desafio de MFA se ainda não tiver feito isso.
- Exibe os detalhes do usuário na interface do usuário updateProfile.hbs.
Dispare a rota
/update
quando o usuário selecionar o botão Salvar em gatedUpdateProfile.hbs ou updateProfile.hbs. O aplicativo:- Recupera o token de acesso para a sessão do aplicativo. Você aprenderá como o aplicativo de nível intermediário (aplicativo EditProfileService) adquire o token de acesso na próxima seção.
- Coleta todos os detalhes do usuário.
- Faz uma chamada à API do Microsoft Graph para atualizar o perfil do usuário.
Atualizar o arquivo fetch.js
O aplicativo usa o arquivo App/fetch.js para fazer as chamadas à API reais.
No seu editor de código, abra o arquivo App/fetch.js, depois adicione a opção de operação PATCH. Após atualizar o arquivo, o arquivo resultante deverá ser semelhante ao seguinte código:
var axios = require('axios');
var authProvider = require("./auth/AuthProvider");
/**
* Makes an Authorization "Bearer" request with the given accessToken to the given endpoint.
* @param endpoint
* @param accessToken
* @param method
*/
const fetch = async (endpoint, accessToken, method = "GET", data = null) => {
const options = {
headers: {
Authorization: `Bearer ${accessToken}`,
},
};
console.log(`request made to ${endpoint} at: ` + new Date().toString());
switch (method) {
case 'GET':
const response = await axios.get(endpoint, options);
return await response.data;
case 'POST':
return await axios.post(endpoint, data, options);
case 'DELETE':
return await axios.delete(endpoint + `/${data}`, options);
case 'PATCH':
return await axios.patch(endpoint, ReqBody = data, options);
default:
return null;
}
};
module.exports = { fetch };
Concluir o aplicativo de nível intermediário
Nesta seção, você adicionará o código relacionado à identidade para o aplicativo de nível intermediário (aplicativo EditProfileService).
No seu editor de código, abra o arquivo Api/authConfig.js, depois adicione o seguinte código:
require("dotenv").config({ path: ".env.dev" }); const TENANT_SUBDOMAIN = process.env.TENANT_SUBDOMAIN || "Enter_the_Tenant_Subdomain_Here"; const TENANT_ID = process.env.TENANT_ID || "Enter_the_Tenant_ID_Here"; const REDIRECT_URI = process.env.REDIRECT_URI || "http://localhost:3000/auth/redirect"; const POST_LOGOUT_REDIRECT_URI = process.env.POST_LOGOUT_REDIRECT_URI || "http://localhost:3000"; /** * Configuration object to be passed to MSAL instance on creation. * For a full list of MSAL Node configuration parameters, visit: * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md */ const msalConfig = { auth: { clientId: process.env.CLIENT_ID || "Enter_the_Edit_Profile_Service_Application_Id_Here", // 'Application (client) ID' of the Edit_Profile Service App registration in Microsoft Entra admin center - this value is a GUID authority: process.env.AUTHORITY || `https://${TENANT_SUBDOMAIN}.ciamlogin.com/`, // Replace the placeholder with your external tenant name }, system: { loggerOptions: { loggerCallback(loglevel, message, containsPii) { console.log(message); }, piiLoggingEnabled: false, logLevel: "Info", }, }, }; const GRAPH_API_ENDPOINT = process.env.GRAPH_API_ENDPOINT || "graph_end_point"; // Refers to the user that is single user singed in. // https://learn.microsoft.com/en-us/graph/api/user-update?tabs=http const GRAPH_ME_ENDPOINT = GRAPH_API_ENDPOINT + "v1.0/me"; module.exports = { msalConfig, REDIRECT_URI, POST_LOGOUT_REDIRECT_URI, TENANT_SUBDOMAIN, GRAPH_API_ENDPOINT, GRAPH_ME_ENDPOINT, TENANT_ID, };
Localize o espaço reservado:
Enter_the_Tenant_Subdomain_Here
e substitua-o pelo subdomínio do Diretório (locatário). 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.Enter_the_Tenant_ID_Here
e substitua-o pela ID do Locatário. Se você não tiver sua ID do Locatário, saiba como ler os detalhes do seu locatário.Enter_the_Edit_Profile_Service_Application_Id_Here
e substitua-o pelo valor da ID do aplicativo (cliente) do EditProfileService que você registrou anteriormente.Enter_the_Client_Secret_Here
e substitua-o pelo valor do segredo do aplicativo EditProfileService que você copiou anteriormente.graph_end_point
e substitua pelo ponto de extremidade da API do Microsoft Graph, ou sejahttps://graph.microsoft.com/
.
No seu editor de código, abra o arquivo Api/fetch.js, depois cole o código do arquivo Api/fetch.js. A função
fetch
usa um token de acesso e o ponto de extremidade do recurso para fazer a chamada à API real.No seu editor de código, abra o arquivo Api/index.js, depois cole o código do arquivo Api/index.js.
Adquirir um token de acesso usando acquireTokenOnBehalfOf
No arquivo Api/index.js, o aplicativo de nível intermediário (aplicativo EditProfileService) adquire um token de acesso usando a função acquireTokenOnBehalfOf, que ele usa para atualizar o perfil em nome desse usuário.
async function getAccessToken(tokenRequest) {
try {
const response = await cca.acquireTokenOnBehalfOf(tokenRequest);
return response.accessToken;
} catch (error) {
console.error("Error acquiring token:", error);
throw error;
}
}
O parâmetro tokenRequest
é definido conforme mostrado no código a seguir:
const tokenRequest = {
oboAssertion: req.headers.authorization.replace("Bearer ", ""),
authority: `https://${TENANT_SUBDOMAIN}.ciamlogin.com/${TENANT_ID}`,
scopes: ["User.ReadWrite"],
correlationId: `${uuidv4()}`,
};
No mesmo arquivo, API/index.js, o aplicativo de nível intermediário (aplicativo EditProfileService) faz uma chamada à API do Microsoft Graph para atualizar o perfil dos usuários:
let accessToken = await getAccessToken(tokenRequest);
fetch(GRAPH_ME_ENDPOINT, accessToken, "PATCH", req.body)
.then((response) => {
if (response.status === 204) {
res.status(response.status);
res.json({ message: "Success" });
} else {
res.status(502);
res.json({ message: "Failed, " + response.body });
}
})
.catch((error) => {
res.status(502);
res.json({ message: "Failed, " + error });
});
Testar seu aplicativo
Para testar seu aplicativo, use as seguintes etapas:
Para executar o aplicativo cliente, a partir da janela do terminal, navegue até o diretório App, depois execute o seguinte comando:
npm start
Para executar o aplicativo cliente, a partir da janela do terminal, navegue até o diretório API, depois execute o seguinte comando:
npm start
Abra o navegador e acesse http://localhost:3000. Se houver erros de certificado SSL, crie um arquivo
.env
e adicione a seguinte configuração:# Use this variable only in the development environment. # Remove the variable when you move the app to the production environment. NODE_TLS_REJECT_UNAUTHORIZED='0'
Selecione o botão Entrar e, em seguida, conecte-se.
Na página de entrada, digite seu Endereço de email, selecione Avançar, digite sua Senha e selecione Entrar. Se você não tiver uma conta, selecione o link Não tem uma conta? Crie uma, que iniciará o fluxo de inscrição.
Para atualizar o perfil, selecione o link Edição de perfil. Você verá uma página semelhante à seguinte captura de tela:
Para editar o perfil, selecione o botão Editar Perfil. Se você ainda não fez isso, o aplicativo solicitará que você conclua um desafio de MFA.
Faça alterações em qualquer um dos detalhes do perfil, depois selecione o botão Salvar.
Conteúdo relacionado
- Saiba mais sobre a plataforma de identidade da Microsoft e o fluxo On-Behalf-Of OAuth 2.0 .