Gerir sessões de CNA

Esta página descreve como o Identity-Aware Proxy (IAP) processa um pedido com uma sessão expirada e como garantir que os pedidos de apps AJAX e os pedidos WebSocket são bem-sucedidos.

Fluxo de sessão de IAP

Quando usa o fluxo de início de sessão de IAP padrão, o utilizador recebe um cookie de sessão que faz referência à respetiva sessão de início de sessão do Google. O IAP usa este cookie para confirmar que o utilizador ainda tem sessão iniciada. As CNA exigem que um utilizador inicie sessão antes de aceder a uma app protegida por CNA.

As sessões de IAP são atualizadas periodicamente. No entanto, se o utilizador estiver a usar uma conta Google para iniciar sessão, as sessões de IAP também estão associadas à sessão de início de sessão do utilizador na Google. Neste caso, a IAP só exige que o utilizador inicie sessão novamente numa das seguintes situações:

  • O utilizador terminou sessão na respetiva conta
  • A conta foi suspensa
  • A conta requer uma reposição da palavra-passe

Se um utilizador tiver sessão terminada, o IAP deteta uma alteração do estado da Conta Google em alguns minutos. Uma vez detetada, a IAP invalida a sessão.

A IAP volta a verificar a autorização da gestão de identidade e de acesso (IAM) para todos os pedidos durante as sessões válidas. As atualizações à política de acesso de IAM de uma app protegida por IAP podem demorar alguns minutos a entrar em vigor.

Expiração da sessão de IAP

Para um fluxo de início de sessão que use uma Conta Google, a sessão de IAP está associada à sessão de início de sessão da Google subjacente e expira apenas quando essa sessão expira, independentemente da reivindicação exp no JWT enviado no cabeçalho de autorização.

Para a autenticação programática, a IAP respeita a reivindicação exp no JWT enviado no cabeçalho de autorização.

Para o fluxo de início de sessão da Identity Platform, a sessão do IAP permanece válida durante, no máximo, uma hora após o utilizador ter terminado sessão.

Pedido de início de sessão para Contas Google

O valor loginHint definido através de IapSettings tem de corresponder ao domínio do utilizador com sessão iniciada. Se estes valores não corresponderem, é apresentado o pedido de início de sessão se o cookie de IAP for limpo ou expirar.

Pedidos WebSocket

O IAP só suporta WebSocket para pedidos iniciais e não verifica continuamente a autorização. Quando é recebido um pedido WebSocket, este começa com um pedido HTTP Upgrade. O IAP avalia isto como um pedido HTTP GET padrão. Após a autorização do pedido, a IAP transmite o pedido ao servidor, abrindo uma ligação persistente. Depois disso, a IAP não monitoriza os pedidos nem atualiza a sessão.

Respostas de sessões expiradas

As IAPs devolvem respostas diferentes para sessões expiradas com base no tipo de pedido.

Pedidos não AJAX

Para pedidos não AJAX, o utilizador é redirecionado para o fluxo de início de sessão para atualizar a sessão. Se o utilizador ainda tiver sessão iniciada, este redirecionamento é transparente.

Pedidos AJAX

O Chrome e outros navegadores estão a remover os cookies de terceiros. As recomendações para fazer pedidos AJAX nesta página não funcionam se os cookies de terceiros estiverem desativados. No entanto, as recomendações fornecidas vão continuar a funcionar se a origem e o destino dos pedidos AJAX forem do mesmo site.

Para obter instruções sobre como gerir cookies de terceiros no Chrome, consulte o artigo Elimine, permita e faça a gestão de cookies no Chrome.

A IAP baseia-se em cookies para gerir as sessões dos utilizadores. Também depende de uma sequência de redirecionamentos para estabelecer uma sessão como parte de um fluxo de início de sessão. Nem sempre é possível estabelecer uma sessão se a aplicação estiver a usar o Cross-Origin Resource Sharing (CORS) para fazer pedidos AJAX a uma aplicação protegida pelo IAP.

Para fazer um pedido CORS com êxito a uma aplicação protegida pelo IAP, tem de estabelecer uma sessão do IAP fora da banda. Tenha em atenção que, para um pedido AJAX que envia um pedido CORS de source_domain->target_domain, onde target_domain aloja a aplicação protegida pelo IAP, tem de existir uma sessão estabelecida em target_domain. Não existe forma de partilhar cookies entre source_domain e target_domain.

Quando a sessão em target_domain estiver estabelecida, o programador tem de ativar o envio de credenciais no pedido. Por predefinição, os métodos JavaScript não anexam cookies a pedidos. Para ativar as credenciais no pedido, os pedidos enviados com um objeto XMLHttpRequest precisam da propriedade withCredentials definida como verdadeira, enquanto os pedidos enviados com o Fetch API precisam da opção credentials definida como include ou same-origin.

O seguinte guia recomenda um padrão para que os programadores Web possam estabelecer e atualizar uma sessão de CAs com êxito.

Compreender a resposta da CNA

Para pedidos AJAX, o IAP devolve um código de estado HTTP.401: Unauthorized Tenha em atenção que a deteção de pedidos AJAX não pode ser feita na perfeição. Se receber uma resposta com o código de estado 302 em vez do código de estado 401 para pedidos AJAX, pode adicionar um cabeçalho X-Requested-With com o valor "XMLHttpRequest" aos pedidos AJAX. Isto indica à IAP que o pedido tem origem no JavaScript.

Processar uma resposta 401AJAX HTTP

Para estabelecer uma sessão de IAP depois de a aplicação receber HTTP 401, a aplicação pode abrir uma nova janela para o URL target_domain + ?gcp-iap-mode=DO_SESSION_REFRESH. Este é um controlador especial que apenas estabelece a sessão de IAP em target_domain. Se a janela permanecer aberta, vai continuar a atualizar a sessão periodicamente, pedindo a introdução de dados do utilizador conforme necessário. Opcionalmente, o utilizador pode optar por fechar a janela e o controlador do estado HTTP 401 no código do programador deve apresentar novamente uma janela para a atualização da sessão, conforme necessário.

Passo 1: modifique o código da app

O exemplo seguinte mostra como modificar o código da sua app para processar o código de estado HTTP 401 e fornecer um link de atualização da sessão ao utilizador:

if (response.status === 401) {
  statusElm.innerHTML = 'Login stale. <input type="button" value="Refresh" onclick="sessionRefreshClicked();"/>';
}
Passo 2: instale um controlador onclick

O exemplo de código abaixo instala um controlador onclick que fecha a janela após a atualização da sessão:

var iapSessionRefreshWindow = null;

function sessionRefreshClicked() {
  if (iapSessionRefreshWindow == null) {
    iapSessionRefreshWindow = window.open("/?gcp-iap-mode=DO_SESSION_REFRESH");
    window.setTimeout(checkSessionRefresh, 500);
  }
  return false;
}

function checkSessionRefresh() {
  if (iapSessionRefreshWindow != null && !iapSessionRefreshWindow.closed) {
    // Attempting to start a new session.
    // XMLHttpRequests is used by the server to identify AJAX requests
    fetch('/favicon.ico', {
          method: "GET",
          credentials: 'include',
          headers: {
              'X-Requested-With': 'XMLHttpRequest'
          }
    .then((response) => {
      // Checking if browser has a session for the requested app
      if (response.status === 401) {
        // No new session detected. Try to get a session again
        window.setTimeout(checkSessionRefresh, 500);
      } else {
        // Session retrieved.
        iapSessionRefreshWindow.close();
        iapSessionRefreshWindow = null;
      }
    })
    });
  } else {
    iapSessionRefreshWindow = null;
  }
}