Azure AD B2C: chamar uma API Web de um aplicativo Web .NETAzure AD B2C: Call a .NET web API from a .NET web app

Usando o Azure AD B2C, você pode adicionar recursos poderosos de gerenciamento de identidades a seus aplicativos Web e APIs Web.By using Azure AD B2C, you can add powerful identity management features to your web apps and web APIs. Este artigo descreve como solicitar tokens de acesso e fazer chamadas de um aplicativo Web de “lista de tarefas pendentes” do .NET para uma API Web .NET.This article discusses how to request access tokens and make calls from a .NET "to-do list" web app to a .NET web api.

Este artigo não aborda como implementar conexão, registro e gerenciamento de perfil com o Azure AD B2C.This article does not cover how to implement sign-in, sign-up and profile management with Azure AD B2C. Ele se concentra na chamada a APIs Web depois que o usuário já está autenticado.It focuses on calling web APIs after the user is already authenticated. Se você ainda não fez isto, você deverá:If you haven't already, you should:

Pré-requisitoPrerequisite

Para criar um aplicativo Web que chame uma API Web, você deve:To build a web application that calls a web api, you need to:

  1. Criar um locatário do Azure AD B2C.Create an Azure AD B2C tenant.
  2. Registrar uma api Web.Register a web api.
  3. Registrar um aplicativo Web.Register a web app.
  4. Configurar políticas.Set up policies.
  5. Conceder permissões para usar a API Web ao aplicativo Web.Grant the web app permissions to use the web api.

Importante

O aplicativo cliente e a API Web devem usar o mesmo diretório do Azure AD B2C.The client application and web API must use the same Azure AD B2C directory.

Baixar o códigoDownload the code

O código para este tutorial é mantido no GitHub.The code for this tutorial is maintained on GitHub. Você pode clonar a amostra executando:You can clone the sample by running:

git clone https://github.com/Azure-Samples/active-directory-b2c-dotnet-webapp-and-webapi.git

Depois de baixar o código de exemplo, abra o arquivo .sln do Visual Studio para começar.After you download the sample code, open the Visual Studio .sln file to get started. Agora, sua solução contém dois projetos: TaskWebApp e TaskService.The solution file contains two projects: TaskWebApp and TaskService. TaskWebApp é um aplicativo Web MVC com o qual o usuário interage.TaskWebApp is a MVC web application that the user interacts with. TaskService é API Web back-end do aplicativo que armazena a lista de tarefas de cada usuário.TaskService is the app's back-end web API that stores each user's to-do list. Este artigo não abrange a criação do aplicativo Web TaskWebApp nem da API Web TaskService.This article does not cover building the TaskWebApp web app or the TaskService web api. Para saber como criar um aplicativo Web .NET usando o Azure AD B2C, confira nosso tutorial do aplicativo Web .NET.To learn how to build the .NET web app using Azure AD B2C, see our .NET web app tutorial. Para saber como criar uma API Web .NET protegida usando o Azure AD B2C, confira nosso tutorial da API Web .NET.To learn how to build the .NET web API secured using Azure AD B2C, see our .NET web API tutorial.

Atualizar a configuração do Azure AD B2CUpdate the Azure AD B2C configuration

Nossa amostra é configurada para usar as políticas e a ID do cliente de nosso locatário de demonstração.Our sample is configured to use the policies and client ID of our demo tenant. Se você quiser usar seu próprio locatário:If you would like to use your own tenant:

  1. Abra web.config no projeto TaskService e substitua os valores deOpen web.config in the TaskService project and replace the values for

    • ida:Tenant pelo nome do locatárioida:Tenant with your tenant name
    • ida:ClientId pela ID do aplicativo da API Webida:ClientId with your web api application ID
    • ida:SignUpSignInPolicyId pelo nome da política "Inscrever-se ou Entrar"ida:SignUpSignInPolicyId with your "Sign-up or Sign-in" policy name
  2. Abra web.config no projeto TaskWebApp e substitua os valores deOpen web.config in the TaskWebApp project and replace the values for

    • ida:Tenant pelo nome do locatárioida:Tenant with your tenant name
    • ida:ClientId pela ID de aplicativo do aplicativo Webida:ClientId with your web app application ID
    • ida:ClientSecret pela chave de segredo do aplicativo Webida:ClientSecret with your web app secret key
    • ida:SignUpSignInPolicyId pelo nome da política "Inscrever-se ou Entrar"ida:SignUpSignInPolicyId with your "Sign-up or Sign-in" policy name
    • ida:EditProfilePolicyId pelo nome de política "Editar Perfil"ida:EditProfilePolicyId with your "Edit Profile" policy name
    • ida:ResetPasswordPolicyId pelo nome de política "Redefinir Senha"ida:ResetPasswordPolicyId with your "Reset Password" policy name

Solicitar e salvar um token de acessoRequesting and saving an access token

Especificar as permissõesSpecify the permissions

Para fazer a chamada para a API Web, você precisa autenticar o usuário (usando a política de inscrever-se ou entrar) e receber um token de acesso do Azure AD B2C.In order to make the call to the web API, you need to authenticate the user (using your sign-up/sign-in policy) and receive an access token from Azure AD B2C. Para receber um token de acesso, você deve primeiro especificar as permissões que você deseja que sejam concedidas pelo token de acesso.In order to receive an access token, you first must specify the permissions you would like the access token to grant. As permissões são especificadas no parâmetro scope quando você faz a solicitação para o ponto de extremidade /authorize.The permissions are specified in the scope parameter when you make the request to the /authorize endpoint. Por exemplo, para obter um token de acesso com a permissão de "leitura" para o aplicativo de recurso que tem o URI de ID do aplicativo de https://contoso.onmicrosoft.com/tasks, o escopo seria https://contoso.onmicrosoft.com/tasks/read.For example, to acquire an access token with the “read” permission to the resource application that has the App ID URI of https://contoso.onmicrosoft.com/tasks, the scope would be https://contoso.onmicrosoft.com/tasks/read.

Para especificar o escopo em nosso exemplo, abra o arquivo App_Start\Startup.Auth.cs e defina a variável Scope em OpenIdConnectAuthenticationOptions.To specify the scope in our sample, open the file App_Start\Startup.Auth.cs and define the Scope variable in OpenIdConnectAuthenticationOptions.

// App_Start\Startup.Auth.cs

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            ...

            // Specify the scope by appending all of the scopes requested into one string (seperated by a blank space)
            Scope = $"{OpenIdConnectScopes.OpenId} {ReadTasksScope} {WriteTasksScope}"
        }
    );
}

Permutar o código de autorização de um token de acessoExchange the authorization code for an access token

Após um usuário concluir a experiência de inscrição ou entrada, seu aplicativo receberá um código de autorização do Azure AD B2C.After an user completes the sign-up or sign-in experience, your app will receive an authorization code from Azure AD B2C. O middleware OWIN OpenID Connect armazenará o código, mas não o permutará por um token de acesso.The OWIN OpenID Connect middleware will store the code, but will not exchange it for an access token. Você pode usar a biblioteca MSAL para realizar a permuta.You can use the MSAL library to make the exchange. Em nosso exemplo, configuramos um retorno de chamada de notificação para o middleware OpenID Connect sempre que um código de autorização é recebido.In our sample, we configured a notification callback into the OpenID Connect middleware whenever an authorization code is received. No retorno de chamada, usamos o MSAL para permutar o código por um token e salvar o token no cache.In the callback, we use MSAL to exchange the code for a token and save the token into the cache.

/*
* Callback function when an authorization code is received
*/
private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification notification)
{
    // Extract the code from the response notification
    var code = notification.Code;

    var userObjectId = notification.AuthenticationTicket.Identity.FindFirst(ObjectIdElement).Value;
    var authority = String.Format(AadInstance, Tenant, DefaultPolicy);
    var httpContext = notification.OwinContext.Environment["System.Web.HttpContextBase"] as HttpContextBase;

    // Exchange the code for a token. Make sure to specify the necessary scopes
    ClientCredential cred = new ClientCredential(ClientSecret);
    ConfidentialClientApplication app = new ConfidentialClientApplication(authority, Startup.ClientId,
                                            RedirectUri, cred, new NaiveSessionCache(userObjectId, httpContext));
    var authResult = await app.AcquireTokenByAuthorizationCodeAsync(new string[] { ReadTasksScope, WriteTasksScope }, code, DefaultPolicy);
}

Chamar a API da webCalling the web API

Esta seção discute como usar o token recebido durante a inscrição/entrada com o Azure AD B2C para acessar a API Web.This section discusses how to use the token received during sign-up/sign-in with Azure AD B2C in order to access the web API.

Recuperar o token salvo nos controladoresRetrieve the saved token in the controllers

O TasksController é responsável pela comunicação com a API Web e por enviar solicitações HTTP à API para ler, criar e excluir tarefas.The TasksController is responsible for communicating with the web API and for sending HTTP requests to the API to read, create, and delete tasks. Já que a API é protegida pelo Azure AD B2C, primeiro você precisa recuperar o token que salvou na etapa anterior.Because the API is secured by Azure AD B2C, you need to first retrieve the token you saved in the above step.

// Controllers\TasksController.cs

/*
* Uses MSAL to retrieve the token from the cache
*/
private async void acquireToken(String[] scope)
{
    string userObjectID = ClaimsPrincipal.Current.FindFirst(Startup.ObjectIdElement).Value;
    string authority = String.Format(Startup.AadInstance, Startup.Tenant, Startup.DefaultPolicy);

    ClientCredential credential = new ClientCredential(Startup.ClientSecret);

    // Retrieve the token using the provided scopes
    ConfidentialClientApplication app = new ConfidentialClientApplication(authority, Startup.ClientId,
                                        Startup.RedirectUri, credential,
                                        new NaiveSessionCache(userObjectID, this.HttpContext));
    AuthenticationResult result = await app.AcquireTokenSilentAsync(scope);

    accessToken = result.Token;
}

Ler tarefas da API WebRead tasks from the web API

Quando você tiver um token, poderá anexá-lo à solicitação GET HTTP no cabeçalho Authorization para chamar com segurança o TaskService:When you have a token, you can attach it to the HTTP GET request in the Authorization header to securely call TaskService:

// Controllers\TasksController.cs

public async Task<ActionResult> Index()
{
    try {

        // Retrieve the token with the specified scopes
        acquireToken(new string[] { Startup.ReadTasksScope });

        HttpClient client = new HttpClient();
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, apiEndpoint);

        // Add token to the Authorization header and make the request
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        HttpResponseMessage response = await client.SendAsync(request);

        // Handle response ...
}

Criar e excluir tarefas na API WebCreate and delete tasks on the web API

Siga o mesmo padrão ao enviar solicitações de POST e DELETE à API Web, usando o MSAL para recuperar o token de acesso do cache.Follow the same pattern when you send POST and DELETE requests to the web API, using MSAL to retrieve the access token from the cache.

Executar o aplicativo de exemploRun the sample app

Finalmente, compile e execute ambos os aplicativos.Finally, build and run both the apps. Inscreva-se e entre e crie tarefas para o usuário conectado.Sign up and sign in, and create tasks for the signed-in user. Saia e entre como outro usuário.Sign out and sign in as a different user. Crie tarefas para esse usuário.Create tasks for that user. Observe como as tarefas são armazenados por usuário na API, pois a API extrai a identidade do usuário do token que recebe.Notice how the tasks are stored per-user on the API, because the API extracts the user's identity from the token it receives. Além disso, experimente mudar os escopos.Also try playing with the scopes. Remova a permissão de "gravação" e, em seguida, tente adicionar uma tarefa.Remove the permission to "write" and then try adding a task. Apenas certifique-se de sair sempre que você alterar o escopo.Just make sure to sign out each time you change the scope.