Exercício – Conectar usuários com a MSAL

Concluído

Neste exercício, você usará a Biblioteca de Autenticação da Microsoft para Java (MSAL4J) para adicionar autenticação em um aplicativo Web Java de exemplo e permitir que os usuários entrem com suas contas do Microsoft Entra.

O aplicativo de exemplo que você usará neste exercício é um aplicativo servlet Java que permite que os usuários entrem e exibam o nome de usuário e as informações básicas do perfil. Ele também permite que você chame a API do Microsoft Graph para mostrar algumas informações do usuário.

Criar um aplicativo web Java

No shell ou na linha de comando:

  1. Crie uma pasta para o aplicativo.

    mkdir ~/javawebapp
    
  2. Clone o aplicativo de exemplo do repositório do GitHub na nova pasta.

    git clone https://github.com/Azure-Samples/ms-identity-java-servlet-webapp-authentication.git ~/javawebapp
    
  3. Vá até a pasta em que o aplicativo de exemplo deste exercício está localizado.

    cd ~/javawebapp/ms-identity-java-servlet-webapp-authentication/2-Authorization-I/call-graph
    

Configurar o aplicativo

Para configurar o código, abra o projeto do aplicativo no IDE de sua preferência, como o IntelliJ ou o VS Code.

  1. Abra o arquivo ./src/main/resources/authentication.properties.

  2. Encontre a cadeia de caracteres {enter-your-tenant-id-here}. Substitua o valor existente pela ID do diretório (locatário) (conforme mostrado na imagem a seguir), porque o aplicativo foi registrado com a opção Somente contas neste diretório organizacional.

  3. Localize a cadeia de caracteres {enter-your-client-id-here} e substitua o valor existente pela ID do aplicativo (cliente) (clientId) do aplicativo registrado copiada do portal do Azure.

    Screenshot highlighting the App ID of an app registered with Microsoft Entra ID on Azure portal.

  4. Localize a cadeia de caracteres {enter-your-client-secret-here} e substitua o valor existente pela chave salva durante a criação do aplicativo no portal do Azure.

Executar o aplicativo

  1. Verifique se o servidor Tomcat está em execução e se você tem privilégios para implantar um aplicativo Web nele. Verifique se o endereço do host do servidor é http://localhost:8080.

  2. Compile e empacote o projeto usando o Maven:

    cd ~/javawebapp/2-Authorization-I/call-graph
    mvn clean package
    
  3. Encontre o arquivo .war resultante em ./target/msal4j-servlet-graph.war. Para implantar no Tomcat, copie esse arquivo .war para o diretório /webapps/ no diretório de instalação do Tomcat e inicie o servidor Tomcat.

  4. Abra o navegador e navegue até http://localhost:8080/msal4j-servlet-graph/. Você será redirecionado para entrar com o Microsoft Entra ID. Ao entrar com êxito, você deverá ver uma página como a seguinte:

    Screenshot showing user name displayed on the page after successfully signing in to sample application.

  5. Selecione o botão Detalhes do token de ID para ver algumas das declarações decodificadas do token de ID.

Visão geral do código de autenticação

Você pode encontrar a maior parte do código de autenticação no aplicativo de exemplo no diretório do projeto java/com/microsoft/azuresamples/msal4j/. Ele contém vários servlets que fornecem os pontos de extremidade de autenticação no aplicativo para entrar, sair e lidar com o retorno de chamada de redirecionamento do Microsoft Entra ID. Esses servlets usam as classes auxiliares no diretório java/com/microsoft/azuresamples/msal4j/helpers/ para chamar os métodos de autenticação fornecidos pela MSAL. Há um filtro de servlet definido em AuthenticationFilter.java que redireciona solicitações não autenticadas para rotas protegidas para uma página de erro HTTP não autorizada 401.

Para adicionar autenticação ao seu aplicativo, você precisará incluir as classes de servlet nos diretórios java/com/microsoft/azuresamples/msal4j/authservlets e java/com/microsoft/azuresamples/msal4j/authwebapp, as classes auxiliares no diretório java/com/microsoft/azuresamples/msal4j/helpers/ e o filtro de servlet de autenticação AuthenticationFilter.java nos seus projetos. Veja mais detalhes do código de autenticação da MSAL.

  1. A MSAL4J está disponível no Maven. Você precisará adicionar a MSAL4J como uma dependência no arquivo pom.xml do projeto:

    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>msal4j</artifactId>
        <version>1.9.1</version>
    </dependency>
    
  2. A primeira etapa do processo de entrada é enviar uma solicitação para o ponto de extremidade /authorize do locatário do Microsoft Entra. A instância ConfidentialClientApplication da MSAL4J é aproveitada para construir uma URL de solicitação de autorização. O aplicativo redireciona o navegador para essa URL, que é onde o usuário se conectará.

    final ConfidentialClientApplication client = getConfidentialClientInstance();
    AuthorizationRequestUrlParameters parameters = AuthorizationRequestUrlParameters
                                                        .builder(Config.REDIRECT_URI, Collections.singleton(Config.SCOPES))
                                                        .responseMode(ResponseMode.QUERY).prompt(Prompt.SELECT_ACCOUNT).state(state).nonce(nonce).build();
    
    final String authorizeUrl = client.getAuthorizationRequestUrl(parameters).toString();
    contextAdapter.redirectUser(authorizeUrl);
    
    • AuthorizationRequestUrlParameters: parâmetros que devem ser definidos para criar uma AuthorizationRequestUrl.
    • REDIRECT_URI: o URI de redirecionamento é o URI para o qual o provedor de identidade enviará os tokens de segurança. O Microsoft Entra ID redirecionará o navegador (juntamente com o código de autenticação) para esse URI após coletar as credenciais do usuário. Ele deve corresponder ao URI de redirecionamento no registro do aplicativo do Microsoft Entra.
    • SCOPES: os escopos são permissões solicitadas pelo aplicativo. Normalmente, os três escopos openid profile offline_access são suficientes para receber uma resposta do token de ID para uma conexão de usuário e são definidos por padrão pela MSAL.
  3. O usuário recebe um prompt de entrada do Microsoft Entra ID. Se a tentativa de conexão for bem-sucedida, o navegador do usuário será redirecionado para o ponto de extremidade de redirecionamento do aplicativo com um código de autorização válido no ponto de extremidade. Em seguida, a instância de ConfidentialClientApplication troca esse código de autorização por um token de ID e um token de acesso do Microsoft Entra ID.

    // First, validate the state, then parse any error codes in response, then extract the authCode. Then:
    // build the auth code params:
    final AuthorizationCodeParameters authParams = AuthorizationCodeParameters
                                                        .builder(authCode, new URI(Config.REDIRECT_URI)).scopes(Collections.singleton(Config.SCOPES)).build();
    
    // Get a client instance and leverage it to acquire the token:
    final ConfidentialClientApplication client = AuthHelper.getConfidentialClientInstance();
    final IAuthenticationResult result = client.acquireToken(authParams).get();
    
    • AuthorizationCodeParameters: parâmetros que devem ser definidos para trocar o código de autorização por uma ID e/ou token de acesso.
    • authCode: o código de autorização recebido no ponto de extremidade de redirecionamento.
    • REDIRECT_URI: o URI de redirecionamento usado na etapa anterior deve ser passado novamente.
    • SCOPES: os escopos usados na etapa anterior devem ser passados novamente.
  4. Se acquireToken for bem-sucedido, as declarações de token serão extraídas. Se a verificação nonce for aprovada, os resultados serão colocados em context (uma instância de IdentityContextData) e salvos na sessão. Em seguida, o aplicativo pode criar uma instância dele com base na sessão (por meio de uma instância de IdentityContextAdapterServlet) sempre que precisar de acesso a ele:

    // parse IdToken claims from the IAuthenticationResult:
    // (the next step - validateNonce - requires parsed claims)
    context.setIdTokenClaims(result.idToken());
    
    // if nonce is invalid, stop immediately! this could be a token replay!
    // if validation fails, throws exception and cancels auth:
    validateNonce(context);
    
    // set user to authenticated:
    context.setAuthResult(result, client.tokenCache().serialize());