Este artigo mostrará como configurar o código do aplicativo e modificar seu aplicativo Web para que ele não apenas conecte os usuários, mas também chame APIs da Web. A aplicação que cria utiliza o fluxo de autorização de código OAuth 2.0 para iniciar sessão para o utilizador. Este fluxo tem duas etapas:
Segredos do cliente ou certificados do cliente
Dado que o seu aplicativo Web agora chama uma API Web downstream, forneça um segredo de cliente ou um certificado de cliente no ficheiro appsettings.json. Você também pode adicionar uma seção que especifique:
- A URL da API Web de downstream
- Os escopos necessários para chamar a API
No exemplo a seguir, a GraphBeta seção especifica essas configurações.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "[Enter_the_Application_Id_Here]",
"TenantId": "common",
// To call an API
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret":"[Enter_the_Client_Secret_Here]"
}
]
},
"GraphBeta": {
"BaseUrl": "https://graph.microsoft.com/beta",
"Scopes": ["user.read"]
}
}
Nota
Você pode propor uma coleção de credenciais de cliente, incluindo uma solução sem credenciais, como federação de identidade de carga de trabalho para Kubernetes do Azure.
Versões anteriores do Microsoft.Identity.Web expressavam o segredo do cliente em uma única propriedade "ClientSecret" em vez de "ClientCredentials". Isso ainda é suportado para compatibilidade com versões anteriores, mas não pode utilizar tanto a propriedade "ClientSecret" como a coleção "ClientCredentials".
Em vez de um segredo do cliente, você pode fornecer um certificado de cliente. O trecho de código a seguir mostra o uso de um certificado armazenado no Cofre de Chaves do Azure.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "[Enter_the_Application_Id_Here]",
"TenantId": "common",
// To call an API
"ClientCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://msidentitywebsamples.vault.azure.net",
"KeyVaultCertificateName": "MicrosoftIdentitySamplesCert"
}
]
},
"GraphBeta": {
"BaseUrl": "https://graph.microsoft.com/beta",
"Scopes": ["user.read"]
}
}
Aviso
Se se esquecer de alterar o Scopes para um vetor, quando tentar usar os IDownstreamApi, os escopos aparecerão nulos e o IDownstreamApi tentará uma chamada anónima (não autenticada) para a API a jusante, o que resultará num erro 401/unauthenticated.
Microsoft.Identity.Web fornece várias maneiras de descrever certificados, tanto por configuração quanto por código. Para obter detalhes, consulte Microsoft.Identity.Web - Usando certificados no GitHub.
Modificar o arquivo Startup.cs
Seu aplicativo Web precisa adquirir um token para a API downstream. Para especificar, adicione a .EnableTokenAcquisitionToCallDownstreamApi() linha após .AddMicrosoftIdentityWebApp(Configuration). Esta linha expõe o serviço IAuthorizationHeaderProvider que pode ser utilizado nas suas ações de controlador e página. No entanto, como você vê nas duas opções a seguir, isso pode ser feito de forma mais simples. Você também precisa escolher uma implementação de cache de token, por exemplo .AddInMemoryTokenCaches(), em Startup.cs:
using Microsoft.Identity.Web;
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]{"user.read" })
.AddInMemoryTokenCaches();
// ...
}
// ...
}
Os escopos passados para EnableTokenAcquisitionToCallDownstreamApi são opcionais e permitem que a sua aplicação web solicite os escopos e o consentimento do utilizador para esses escopos quando iniciarem sessão. Se você não especificar os escopos, Microsoft.Identity.Web habilitará uma experiência de consentimento incremental.
Microsoft.Identity.Web oferece dois mecanismos para chamar uma API Web de um aplicativo Web sem que você precise adquirir um token. A opção escolhida depende se você deseja chamar o Microsoft Graph ou outra API.
Opção 1: Chamar o Microsoft Graph
Se você quiser chamar o Microsoft Graph, Microsoft.Identity.Web permite que você use diretamente o GraphServiceClient (exposto pelo SDK do Microsoft Graph) em suas ações de API. Para expor o Microsoft Graph:
Adicione o pacote NuGet Microsoft.Identity.Web.GraphServiceClient ao seu projeto.
Adicione .AddMicrosoftGraph() depois .EnableTokenAcquisitionToCallDownstreamApi() no arquivo Startup.cs .
.AddMicrosoftGraph() tem várias substituições. Usando a substituição que usa uma seção de configuração como parâmetro, o código se torna:
using Microsoft.Identity.Web;
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]{"user.read" })
.AddMicrosoftGraph(Configuration.GetSection("GraphBeta"))
.AddInMemoryTokenCaches();
// ...
}
// ...
}
Opção 2: Chamar uma API da Web downstream diferente do Microsoft Graph
Se você quiser chamar uma API diferente do Microsoft Graph, Microsoft.Identity.Web permitirá que você use a interface em suas ações de IDownstreamApi API. Para usar esta interface:
Adicione o pacote NuGet Microsoft.Identity.Web.DownstreamApi ao seu projeto.
Adicione .AddDownstreamApi() depois .EnableTokenAcquisitionToCallDownstreamApi() no arquivo Startup.cs .
.AddDownstreamApi() tem dois argumentos e é mostrado no seguinte trecho:
- O nome de um serviço (API), que é usado nas ações do controlador para fazer referência à configuração correspondente
- uma seção de configuração que representa os parâmetros usados para chamar a API da Web downstream.
using Microsoft.Identity.Web;
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(new string[]{"user.read" })
.AddDownstreamApi("MyApi", Configuration.GetSection("GraphBeta"))
.AddInMemoryTokenCaches();
// ...
}
// ...
}
Resumo
Assim como nas APIs da Web, você pode escolher várias implementações de cache de token. Para obter detalhes, consulte Microsoft.Identity.Web - Serialização de token cache no GitHub.
A imagem a seguir mostra as várias possibilidades de Microsoft.Identity.Web e seu efeito no arquivo Startup.cs :
Segredos do cliente ou certificados do cliente
Dado que o seu aplicativo Web agora chama uma API Web downstream, forneça um segredo de cliente ou um certificado de cliente no ficheiro appsettings.json. Você também pode adicionar uma seção que especifique:
- A URL da API Web de downstream
- Os escopos necessários para chamar a API
No exemplo a seguir, a GraphBeta seção especifica essas configurações.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "[Enter_the_Application_Id_Here]",
"TenantId": "common",
// To call an API
"ClientCredentials": [
{
"SourceType": "ClientSecret",
"ClientSecret":"[Enter_the_Client_Secret_Here]"
}
]
},
"GraphBeta": {
"BaseUrl": "https://graph.microsoft.com/beta",
"Scopes": ["user.read"]
}
}
Nota
Você pode propor uma coleção de credenciais de cliente, incluindo uma solução sem credenciais, como federação de identidade de carga de trabalho para Kubernetes do Azure.
Versões anteriores do Microsoft.Identity.Web expressavam o segredo do cliente em uma única propriedade "ClientSecret" em vez de "ClientCredentials". Isso ainda é suportado para compatibilidade com versões anteriores, mas não pode utilizar tanto a propriedade "ClientSecret" como a coleção "ClientCredentials".
Em vez de um segredo do cliente, você pode fornecer um certificado de cliente. O trecho de código a seguir mostra o uso de um certificado armazenado no Cofre de Chaves do Azure.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "[Enter_the_Application_Id_Here]",
"TenantId": "common",
// To call an API
"ClientCredentials": [
{
"SourceType": "KeyVault",
"KeyVaultUrl": "https://msidentitywebsamples.vault.azure.net",
"KeyVaultCertificateName": "MicrosoftIdentitySamplesCert"
}
]
},
"GraphBeta": {
"BaseUrl": "https://graph.microsoft.com/beta",
"Scopes": ["user.read"]
}
}
Aviso
Se se esquecer de alterar o Scopes para um vetor, quando tentar usar os IDownstreamApi, os escopos aparecerão nulos e o IDownstreamApi tentará uma chamada anónima (não autenticada) para a API a jusante, o que resultará num erro 401/unauthenticated.
Microsoft.Identity.Web fornece várias maneiras de descrever certificados, tanto por configuração quanto por código. Para obter detalhes, consulte Microsoft.Identity.Web - Usando certificados no GitHub.
Startup.Auth.cs
Seu aplicativo Web precisa adquirir um token para a API downstream, Microsoft.Identity.Web fornece dois mecanismos para chamar uma API Web de um aplicativo Web. A opção escolhida depende se você deseja chamar o Microsoft Graph ou outra API.
Opção 1: Chamar o Microsoft Graph
Se você quiser chamar o Microsoft Graph, Microsoft.Identity.Web permite que você use diretamente o GraphServiceClient (exposto pelo SDK do Microsoft Graph) em suas ações de API. Para expor o Microsoft Graph:
- Adicione o pacote NuGet Microsoft.Identity.Web.GraphServiceClient ao seu projeto.
- Adicione
.AddMicrosoftGraph() à coleção de serviços no arquivo Startup.Auth.cs .
.AddMicrosoftGraph() tem várias substituições. Usando a substituição que usa uma seção de configuração como parâmetro, o código se torna:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Microsoft.Identity.Web.TokenCacheProviders.InMemory;
using Microsoft.IdentityModel.Validators;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Owin;
namespace WebApp
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
// Get an TokenAcquirerFactory specialized for OWIN
OwinTokenAcquirerFactory owinTokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();
// Configure the web app.
app.AddMicrosoftIdentityWebApp(owinTokenAcquirerFactory,
updateOptions: options => {});
// Add the services you need.
owinTokenAcquirerFactory.Services
.Configure<ConfidentialClientApplicationOptions>(options =>
{ options.RedirectUri = "https://localhost:44326/"; })
.AddMicrosoftGraph()
.AddInMemoryTokenCaches();
owinTokenAcquirerFactory.Build();
}
}
}
Opção 2: Chamar uma API da Web downstream diferente do Microsoft Graph
Se você quiser chamar uma API diferente do Microsoft Graph, Microsoft.Identity.Web permitirá que você use a interface em suas ações de IDownstreamApi API. Para usar esta interface:
- Adicione o pacote NuGet Microsoft.Identity.Web.DownstreamApi ao seu projeto.
- Adicione
.AddDownstreamApi() depois .EnableTokenAcquisitionToCallDownstreamApi() no arquivo Startup.cs .
.AddDownstreamApi() tem dois argumentos:
- O nome de um serviço (API): você usa esse nome nas ações do controlador para fazer referência à configuração correspondente
- uma seção de configuração que representa os parâmetros usados para chamar a API da Web downstream.
Aqui está o código:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using Microsoft.Identity.Web.OWIN;
using Microsoft.Identity.Web.TokenCacheProviders.InMemory;
using Microsoft.IdentityModel.Validators;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Owin;
namespace WebApp
{
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
// Get a TokenAcquirerFactory specialized for OWIN.
OwinTokenAcquirerFactory owinTokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance<OwinTokenAcquirerFactory>();
// Configure the web app.
app.AddMicrosoftIdentityWebApp(owinTokenAcquirerFactory,
updateOptions: options => {});
// Add the services you need.
owinTokenAcquirerFactory.Services
.Configure<ConfidentialClientApplicationOptions>(options =>
{ options.RedirectUri = "https://localhost:44326/"; })
.AddDownstreamApi("Graph", owinTokenAcquirerFactory.Configuration.GetSection("GraphBeta"))
.AddInMemoryTokenCaches();
owinTokenAcquirerFactory.Build();
}
}
}
Resumo
Você pode escolher várias implementações de cache de token. Para obter detalhes, consulte Microsoft.Identity.Web - Serialização de token cache no GitHub.
A imagem a seguir mostra as várias possibilidades de Microsoft.Identity.Web e seu efeito no arquivo Startup.cs :
Exemplos de código neste artigo e no seguinte são extraídos do exemplo de aplicativo Web ASP.NET. Talvez você queira consultar esse exemplo para obter detalhes completos da implementação.
Implementar o exemplo de código Java
Exemplos de código neste artigo e no seguinte são extraídos do aplicativo Web Java que chama o Microsoft Graph, um exemplo de aplicativo Web que usa MSAL para Java.
O exemplo atualmente permite que o MSAL for Java produza a URL do código de autorização e gere a navegação até o endpoint de autorização para a plataforma de identidade da Microsoft. Também é possível usar a segurança da Sprint para fazer login no usuário. Talvez você queira consultar o exemplo para obter detalhes completos da implementação.
Implementar o exemplo de código Node.js
Exemplos de código neste artigo e no seguinte são extraídos do aplicativo Web Node.js e Express.js que chama o Microsoft Graph, um exemplo de aplicação web que utiliza o MSAL Node.
O exemplo atualmente permite que o MSAL Node produza a URL do código de autorização e efetua a navegação para o endpoint de autorização na plataforma de identidades da Microsoft. Isso é mostrado abaixo:
/**
* Prepares the auth code request parameters and initiates the first leg of auth code flow
* @param req: Express request object
* @param res: Express response object
* @param next: Express next function
* @param authCodeUrlRequestParams: parameters for requesting an auth code url
* @param authCodeRequestParams: parameters for requesting tokens using auth code
*/
redirectToAuthCodeUrl(authCodeUrlRequestParams, authCodeRequestParams, msalInstance) {
return async (req, res, next) => {
// Generate PKCE Codes before starting the authorization flow
const { verifier, challenge } = await this.cryptoProvider.generatePkceCodes();
// Set generated PKCE codes and method as session vars
req.session.pkceCodes = {
challengeMethod: 'S256',
verifier: verifier,
challenge: challenge,
};
/**
* By manipulating the request objects below before each request, we can obtain
* auth artifacts with desired claims. For more information, visit:
* https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_node.html#authorizationurlrequest
* https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_node.html#authorizationcoderequest
**/
req.session.authCodeUrlRequest = {
...authCodeUrlRequestParams,
responseMode: msal.ResponseMode.FORM_POST, // recommended for confidential clients
codeChallenge: req.session.pkceCodes.challenge,
codeChallengeMethod: req.session.pkceCodes.challengeMethod,
};
req.session.authCodeRequest = {
...authCodeRequestParams,
code: '',
};
try {
const authCodeUrlResponse = await msalInstance.getAuthCodeUrl(req.session.authCodeUrlRequest);
res.redirect(authCodeUrlResponse);
} catch (error) {
next(error);
}
};
}
Implementar o exemplo de código Python
Trechos de código deste artigo e dos seguintes são extraídos da aplicação Web Python que chama o exemplo Microsoft Graph, utilizando o pacote identity (uma camada de abstração sobre o MSAL Python).
O exemplo usa o pacote de identidade para produzir a URL do código de autorização e gera a navegação para o endpoint de autorização da plataforma de identidade Microsoft. Talvez você queira consultar o exemplo para obter detalhes completos da implementação.
Microsoft.Identity.Web simplifica o seu código, definindo as configurações corretas do OpenID Connect, subscrevendo o evento de código recebido e resgatando o código. Nenhum código extra é necessário para resgatar o código de autorização. Consulte o código-fonte Microsoft.Identity.Web para obter detalhes sobre como isso funciona.
Microsoft.Identity.Web.OWIN simplifica o seu código ao definir as configurações do OpenID Connect, subscrever ao evento de receção de código e resgatar o código. Nenhum código extra é necessário para resgatar o código de autorização. Consulte o código-fonte Microsoft.Identity.Web para obter detalhes sobre como isso funciona.
O método handleRedirect na classe AuthProvider processa o código de autorização recebido do Microsoft Entra ID. Isso é mostrado abaixo:
handleRedirect(options = {}) {
return async (req, res, next) => {
if (!req.body || !req.body.state) {
return next(new Error('Error: response not found'));
}
const authCodeRequest = {
...req.session.authCodeRequest,
code: req.body.code,
codeVerifier: req.session.pkceCodes.verifier,
};
try {
const msalInstance = this.getMsalInstance(this.msalConfig);
if (req.session.tokenCache) {
msalInstance.getTokenCache().deserialize(req.session.tokenCache);
}
const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body);
req.session.tokenCache = msalInstance.getTokenCache().serialize();
req.session.idToken = tokenResponse.idToken;
req.session.account = tokenResponse.account;
req.session.isAuthenticated = true;
const state = JSON.parse(this.cryptoProvider.base64Decode(req.body.state));
res.redirect(state.successRedirect);
} catch (error) {
next(error);
}
}
}
Depois de a aplicação receber o código de autorização, o AuthFilter.java#L51-L56:
- Delega algo ao método
AuthHelper.processAuthenticationCodeRedirect em AuthHelper.java#L67-L97.
- Chamadas
getAuthResultByAuthCode.
class AuthHelper {
// Code omitted
void processAuthenticationCodeRedirect(HttpServletRequest httpRequest, String currentUri, String fullUrl)
throws Throwable {
// Code omitted
AuthenticationResponse authResponse = AuthenticationResponseParser.parse(new URI(fullUrl), params);
// Code omitted
IAuthenticationResult result = getAuthResultByAuthCode(
httpRequest,
oidcResponse.getAuthorizationCode(),
currentUri);
// Code omitted
}
}
O getAuthResultByAuthCode método é definido em AuthHelper.java#L176. Ele cria um MSAL ConfidentialClientApplicatione, em seguida, chama acquireToken() com AuthorizationCodeParameters criado a partir do código de autorização.
private IAuthenticationResult getAuthResultByAuthCode(
HttpServletRequest httpServletRequest,
AuthorizationCode authorizationCode,
String currentUri) throws Throwable {
IAuthenticationResult result;
ConfidentialClientApplication app;
try {
app = createClientApplication();
String authCode = authorizationCode.getValue();
AuthorizationCodeParameters parameters = AuthorizationCodeParameters.builder(
authCode,
new URI(currentUri)).
build();
Future<IAuthenticationResult> future = app.acquireToken(parameters);
result = future.get();
} catch (ExecutionException e) {
throw e.getCause();
}
if (result == null) {
throw new ServiceUnavailableException("authentication result was null");
}
SessionManagementHelper.storeTokenCacheInSession(httpServletRequest, app.tokenCache().serialize());
return result;
}
private ConfidentialClientApplication createClientApplication() throws MalformedURLException {
return ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.create(clientSecret)).
authority(authority).
build();
}
Consulte o Tutorial: Iniciar sessão com utilizadores numa aplicação web Python Flask usando a Microsoft Identity Platform
O ecrã de início de sessão da Microsoft envia o código de autorização para o /getAToken URL especificado no registo da aplicação. A auth_response rota manipula essa URL, chamando auth.complete_login para processar o código de autorização e, em seguida, retornando um erro ou redirecionando para a página inicial.
@app.route(app_config.REDIRECT_PATH)
def auth_response():
result = auth.complete_log_in(request.args)
if "error" in result:
return render_template("auth_error.html", result=result)
return redirect(url_for("index"))
Consulte app.py para obter o contexto completo desse código.
Em vez de um segredo do cliente, o aplicativo cliente confidencial também pode provar sua identidade usando um certificado de cliente ou uma declaração de cliente.
O uso de asserções de cliente é um cenário avançado, detalhado em Asserções de cliente.
O tutorial ASP.NET principal usa a injeção de dependência para permitir que você decida a implementação do cache de token no arquivo Startup.cs para seu aplicativo. Microsoft.Identity.Web vem com serializadores de cache de token pré-construídos descritos em Serialização de cache de token. Uma possibilidade interessante é escolher ASP.NET Core caches de memória distribuída:
// Use a distributed token cache by adding:
services.AddMicrosoftIdentityWebAppAuthentication(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi(
initialScopes: new string[] { "user.read" })
.AddDistributedTokenCaches();
// Then, choose your implementation.
// For instance, the distributed in-memory cache (not cleared when you stop the app):
services.AddDistributedMemoryCache();
// Or a Redis cache:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});
// Or even a SQL Server token cache:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = _config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Para obter detalhes sobre os provedores de cache de token, consulte também o artigo Token cache serialization do Microsoft.Identity.Web e a fase de caches de token dos tutoriais de aplicativos Web ASP.NET Core.
O tutorial ASP.NET usa injeção de dependência para permitir que você decida a implementação do cache de token no arquivo Startup.Auth.cs para seu aplicativo.
Microsoft.Identity.Web vem com serializadores de token-cache pré-construídos descritos em Token cache serialization. Uma possibilidade interessante é escolher ASP.NET Core caches de memória distribuída:
var services = owinTokenAcquirerFactory.Services;
// Use a distributed token cache by adding:
services.AddDistributedTokenCaches();
// Then, choose your implementation.
// For instance, the distributed in-memory cache (not cleared when you stop the app):
services.AddDistributedMemoryCache();
// Or a Redis cache:
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost";
options.InstanceName = "SampleInstance";
});
// Or even a SQL Server token cache:
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = _config["DistCache_ConnectionString"];
options.SchemaName = "dbo";
options.TableName = "TestCache";
});
Para obter detalhes sobre os provedores de cache de token, consulte também o artigo sobre o Microsoft.Identity.Web Serialização de cache de token e a fase Tutoriais de aplicativos Web ASP.NET Core | Caches de token do tutorial do aplicativo Web.
Para obter detalhes, consulte Serialização de cache de token para MSAL.NET.
MSAL Java fornece métodos para serializar e desserializar o cache de token. O exemplo Java manipula a serialização da sessão, conforme mostrado no getAuthResultBySilentFlow método em AuthHelper.java#L99-L122:
IAuthenticationResult getAuthResultBySilentFlow(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws Throwable {
IAuthenticationResult result = SessionManagementHelper.getAuthSessionObject(httpRequest);
IConfidentialClientApplication app = createClientApplication();
Object tokenCache = httpRequest.getSession().getAttribute("token_cache");
if (tokenCache != null) {
app.tokenCache().deserialize(tokenCache.toString());
}
SilentParameters parameters = SilentParameters.builder(
Collections.singleton("User.Read"),
result.account()).build();
CompletableFuture<IAuthenticationResult> future = app.acquireTokenSilently(parameters);
IAuthenticationResult updatedResult = future.get();
// Update session with latest token cache.
SessionManagementHelper.storeTokenCacheInSession(httpRequest, app.tokenCache().serialize());
return updatedResult;
}
O detalhe da SessionManagementHelper classe é fornecido no exemplo MSAL para Java.
No exemplo de Node.js, a sessão do aplicativo é usada para armazenar o cache de token. Utilizando métodos de cache do MSAL Node.js, o cache de token na sessão é consultado antes de uma requisição de token ser realizada e depois é atualizado assim que a requisição de token é concluída com sucesso. Isso é mostrado abaixo:
acquireToken(options = {}) {
return async (req, res, next) => {
try {
const msalInstance = this.getMsalInstance(this.msalConfig);
/**
* If a token cache exists in the session, deserialize it and set it as the
* cache for the new MSAL CCA instance. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
*/
if (req.session.tokenCache) {
msalInstance.getTokenCache().deserialize(req.session.tokenCache);
}
const tokenResponse = await msalInstance.acquireTokenSilent({
account: req.session.account,
scopes: options.scopes || [],
});
/**
* On successful token acquisition, write the updated token
* cache back to the session. For more, see:
* https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
*/
req.session.tokenCache = msalInstance.getTokenCache().serialize();
req.session.accessToken = tokenResponse.accessToken;
req.session.idToken = tokenResponse.idToken;
req.session.account = tokenResponse.account;
res.redirect(options.successRedirect);
} catch (error) {
if (error instanceof msal.InteractionRequiredAuthError) {
return this.login({
scopes: options.scopes || [],
redirectUri: options.redirectUri,
successRedirect: options.successRedirect || '/',
})(req, res, next);
}
next(error);
}
};
}
No exemplo de Python, o pacote de identidade cuida do cache de token, usando o objeto global session para armazenamento.
O Flask tem suporte integrado para sessões armazenadas em um cookie, mas devido ao comprimento dos cookies de identidade, a amostra usa o pacote Flask-session . Tudo é inicializado em app.py:
import identity
import identity.web
import requests
from flask import Flask, redirect, render_template, request, session, url_for
from flask_session import Session
import app_config
app = Flask(__name__)
app.config.from_object(app_config)
Session(app)
auth = identity.web.Auth(
session=session,
authority=app.config["AUTHORITY"],
client_id=app.config["CLIENT_ID"],
client_credential=app.config["CLIENT_SECRET"],
)
O pacote Flask-session armazena sessões usando o sistema de arquivos local devido à configuração SESSION_TYPE="filesystem" em app_config.py.
Para produção, você deve usar uma configuração que persista em várias instâncias e implantações do seu aplicativo, como "sqlachemy" ou "redis".
Neste ponto, quando o usuário entra, um token é armazenado no cache de tokens. Vamos ver como ele é usado em outras partes do aplicativo Web.