Depois de compilar um objeto de aplicativo cliente, use-o para adquirir um token que você pode usar para chamar uma API Web.
Microsoft.Identity.Web adiciona métodos de extensão que fornecem serviços de conveniência para chamar o Microsoft Graph ou uma API Web downstream. Esses métodos são explicados em detalhes em Um aplicativo Web que chama APIs Web: chamar uma API. Com esses métodos auxiliares, não será necessário adquirir um token manualmente.
No entanto, se você quiser adquirir um token manualmente, o código a seguir mostra um exemplo de como usar Microsoft.Identity.Web para fazer isso em um controlador doméstico. Ele chama o Microsoft Graph usando a API REST (em vez do SDK do Microsoft Graph). Normalmente, você não precisa obter um token, você precisa criar um cabeçalho de autorização para adicionar à sua solicitação. Para obter um cabeçalho de autorização, injete o serviço IAuthorizationHeaderProvider
por dependência em seu construtor do controlador (ou seu construtor de página, se você usar o Blazor) e use-o em suas ações de controlador. Essa interface tem métodos que produzem uma cadeia de caracteres que contém o protocolo (Portador, Pop, ...) e um token. Para obter um cabeçalho de autorização para chamar uma API em nome do usuário, use (CreateAuthorizationHeaderForUserAsync
). Para obter um cabeçalho de autorização para chamar uma API downstream em nome do próprio aplicativo, em um cenário de daemon, use (CreateAuthorizationHeaderForAppAsync
).
Os métodos do controlador são protegidos por um atributo [Authorize]
que garante que somente chamadas autenticadas possam usar o aplicativo Web.
[Authorize]
public class MyApiController : Controller
{
/// <summary>
/// The web API will accept only tokens 1) for users, 2) that have the `access_as_user` scope for
/// this API.
/// </summary>
static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };
static readonly string[] scopesToAccessDownstreamApi = new string[] { "api://MyTodolistService/access_as_user" };
readonly IAuthorizationHeaderProvider authorizationHeaderProvider;
public MyApiController(IAuthorizationHeaderProvider authorizationHeaderProvider)
{
this.authorizationHeaderProvider = authorizationHeaderProvider;
}
[RequiredScopes(Scopes = scopesToAccessDownstreamApi)]
public IActionResult Index()
{
// Get an authorization header.
IAuthorizationHeaderProvider authorizationHeaderProvider = this.GetAuthorizationHeaderProvider();
string[] scopes = new string[]{"user.read"};
string authorizationHeader = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
return await callTodoListService(authorizationHeader);
}
}
Para saber mais sobre o método callTodoListService
, confira Uma API Web que chama APIs Web: chamar uma API.
O código para ASP.NET é semelhante ao código mostrado para ASP.NET Core:
- Uma ação do controlador, protegida por um atributo [Authorize], extrai a ID de locatário e a ID de usuário do membro
ClaimsPrincipal
do controlador. (ASP.NET usa HttpContext.User
.) Microsoft.Identity.Web.OWIN adiciona métodos de extensão ao Controlador que fornecem serviços de conveniência para chamar o Microsoft Graph ou uma API Web downstream, ou para obter um cabeçalho de autorização ou até mesmo um token. Esses métodos usados para chamar uma API diretamente são explicados em detalhes em Um aplicativo Web que chama APIs Web: chamar uma API. Com esses métodos auxiliares, não será necessário adquirir um token manualmente.
No entanto, se você quiser adquirir um token manualmente ou compilar um cabeçalho de autorização, o código a seguir mostra como usar Microsoft.Identity.Web para fazer isso em um controlador. Ele chama uma API (Microsoft Graph) usando a API REST em vez do SDK do Microsoft Graph.
Para obter um cabeçalho de autorização, você obtém um IAuthorizationHeaderProvider
serviço do controlador usando um método de extensão GetAuthorizationHeaderProvider
. Para obter um cabeçalho de autorização para chamar uma API em nome do usuário, use (CreateAuthorizationHeaderForUserAsync
). Para obter um cabeçalho de autorização para chamar uma API downstream em nome do próprio aplicativo, em um cenário de daemon, use (CreateAuthorizationHeaderForAppAsync
).
Os métodos do controlador são protegidos por um atributo [Authorize]
que garante que somente usuários autenticados possam usar o aplicativo Web.
O trecho de código a seguir mostra a ação do HomeController
, que obtém um cabeçalho de autorização para chamar o Microsoft Graph como uma API REST:
[Authorize]
public class MyApiController : Controller
{
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Get an authorization header.
IAuthorizationHeaderProvider authorizationHeaderProvider = this.GetAuthorizationHeaderProvider();
string[] scopes = new string[]{"user.read"};
string authorizationHeader = await authorizationHeaderProvider.CreateAuthorizationHeaderForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", authorizationHeader);
string json = await client.GetStringAsync(url);
}
}
O snippet a seguir mostra a ação do MyApiController
, que obtém um token de acesso para chamar o Microsoft Graph como uma API REST:
[Authorize]
public class HomeController : Controller
{
[AuthorizeForScopes(Scopes = new[] { "user.read" })]
public async Task<IActionResult> Profile()
{
// Get an authorization header.
ITokenAcquirer tokenAcquirer = TokenAcquirerFactory.GetDefaultInstance().GetTokenAcquirer();
string[] scopes = new string[]{"user.read"};
string token = await await tokenAcquirer.GetTokenForUserAsync(scopes);
// Use the access token to call a protected web API.
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");
string json = await client.GetStringAsync(url);
}
}
Aqui está um exemplo de código que é chamado nas ações dos controladores de API. Ele chama a API downstream - Microsoft Graph.
@RestController
public class ApiController {
@Autowired
MsalAuthHelper msalAuthHelper;
@RequestMapping("/graphMeApi")
public String graphMeApi() throws MalformedURLException {
String oboAccessToken = msalAuthHelper.getOboToken("https://graph.microsoft.com/.default");
return callMicrosoftGraphMeEndpoint(oboAccessToken);
}
}
Uma API Web do Python requer o uso de algum middleware para validar o token de portador recebido do cliente. A API Web pode obter o token de acesso para uma API downstream usando a biblioteca MSAL do Python chamando o método acquire_token_on_behalf_of
.
Aqui está um exemplo de código que adquire um token de acesso usando o método acquire_token_on_behalf_of
e a estrutura Flask. Ele chama a API downstream - o ponto de extremidade de Assinaturas de Gerenciamento do Azure.
def get(self):
_scopes = ["https://management.azure.com/user_impersonation"]
_azure_management_subscriptions_uri = "https://management.azure.com/subscriptions?api-version=2020-01-01"
current_access_token = request.headers.get("Authorization", None)
#This example only uses the default memory token cache and should not be used for production
msal_client = msal.ConfidentialClientApplication(
client_id=os.environ.get("CLIENT_ID"),
authority=os.environ.get("AUTHORITY"),
client_credential=os.environ.get("CLIENT_SECRET"))
#acquire token on behalf of the user that called this API
arm_resource_access_token = msal_client.acquire_token_on_behalf_of(
user_assertion=current_access_token.split(' ')[1],
scopes=_scopes
)
headers = {'Authorization': arm_resource_access_token['token_type'] + ' ' + arm_resource_access_token['access_token']}
subscriptions_list = req.get(_azure_management_subscriptions_uri), headers=headers).json()
return jsonify(subscriptions_list)
(Avançado) Acessar o cache de token do usuário conectado a partir de aplicativos, APIs e serviços em segundo plano
Você pode usar a implementação de cache de token do MSAL para permitir que aplicativos, APIs e serviços em segundo plano usem o cache de token de acesso para continuar atuando em nome dos usuários na sua ausência. Fazer isso é especialmente útil quando os aplicativos e serviços em segundo plano precisam continuar a trabalhar em nome do usuário depois que este sai do aplicativo Web de front-end.
Atualmente, a maioria dos processos em segundo plano usa permissões de aplicativo quando precisam trabalhar com os dados de um usuário sem que este esteja presente para se autenticar ou reautenticar. Como as permissões de aplicativo geralmente exigem o consentimento do administrador, o que requer elevação de privilégio, ocorre um conflito desnecessário porque o desenvolvedor não pretendia obter outra permissão além da que o usuário originalmente concedeu para seu aplicativo.
Este exemplo de código do GitHub mostra como evitar esse conflito desnecessário pelo acesso ao cache de token do MSAL a partir de aplicativos em segundo plano:
Acessar o cache de token do usuário conectado a partir de aplicativos, APIs e serviços em segundo plano