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. A CNA requer 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, a IAP deteta uma alteração do estado da Conta Google em alguns minutos. Uma vez detetado, o 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 permanecer funcionais se a origem e o destino dos pedidos AJAX forem do mesmo site.

Para 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.

Assim que 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 401 AJAX 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 só estabelece a sessão de CAs no 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;
  }
}