Criar uma página de início de sessão personalizada

Este artigo mostra como criar a sua própria página de autenticação com identidades externas e IAP. A criação desta página por si confere-lhe controlo total sobre o fluxo de autenticação e a experiência do utilizador.

Se não precisar de personalizar totalmente a IU, pode permitir que a IAP aloje uma página de início de sessão por si ou usar a FirebaseUI para uma experiência mais simplificada.

Vista geral

Para criar a sua própria página de autenticação, siga estes passos:

  1. Ative as identidades externas. Selecione Vou fornecer a minha própria opção de IU durante a configuração.
  2. Instale a biblioteca gcip-iap.
  3. Configure a IU implementando a interface AuthenticationHandler. A sua página de autenticação tem de processar os seguintes cenários:
    • Seleção de inquilinos
    • Autorização do utilizador
    • Início de sessão do utilizador
    • Processamento de erros
  4. Opcional: personalize a sua página de autenticação com funcionalidades adicionais, como barras de progresso, páginas de saída e processamento de utilizadores.
  5. Teste a IU.

Instalar a biblioteca gcip-iap

Para instalar a biblioteca gcip-iap, execute o seguinte comando:

npm install gcip-iap --save

O módulo gcip-iapNPM abstrai as comunicações entre a sua aplicação, a IAP e a Identity Platform. Isto permite-lhe personalizar todo o fluxo de autenticação sem ter de gerir as trocas subjacentes entre a IU e a IAP.

Use as importações corretas para a versão do seu SDK:

gcip-iap v0.1.4 ou anterior

// Import Firebase/GCIP dependencies. These are installed on npm install.
import * as firebase from 'firebase/app';
import 'firebase/auth';
// Import GCIP/IAP module.
import * as ciap from 'gcip-iap';

gcip-iap v1.0.0 para v1.1.0

A partir da versão v1.0.0, o gcip-iap requer a dependência de pares firebase v9 ou superior. Se estiver a migrar para a versão gcip-iap 1.0.0 ou superior, conclua as seguintes ações:

  • Atualize a versão do firebase no ficheiro package.json para v9.6.0 ou superior.
  • Atualize as firebasedeclarações de importação da seguinte forma:
// Import Firebase modules.
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
// Import the gcip-iap module.
import * as ciap from 'gcip-iap';

Não são necessárias alterações adicionais ao código.

gcip-iap v2.0.0

A partir da versão v2.0.0, o gcip-iap requer a reescrita da sua aplicação de IU personalizada através do formato de SDK modular. Se estiver a migrar para a versão gcip-iap 2.0.0 ou superior, conclua as seguintes ações:

  • Atualize a versão do firebase no ficheiro package.json para v9.8.3 ou superior.
  • Atualize as firebasedeclarações de importação da seguinte forma:
  // Import Firebase modules.
  import { initializeApp } from 'firebase/app';
  import { getAuth, GoogleAuthProvider } 'firebase/auth';
  // Import the gcip-iap module.
  import * as ciap from 'gcip-iap';

Configurar a IU

Para configurar a IU, crie uma classe personalizada que implemente a interface AuthenticationHandler:

interface AuthenticationHandler {
  languageCode?: string | null;
  getAuth(apiKey: string, tenantId: string | null): FirebaseAuth;
  startSignIn(auth: FirebaseAuth, match?: SelectedTenantInfo): Promise<UserCredential>;
  selectTenant?(projectConfig: ProjectConfig, tenantIds: string[]): Promise<SelectedTenantInfo>;
  completeSignOut(): Promise<void>;
  processUser?(user: User): Promise<User>;
  showProgressBar?(): void;
  hideProgressBar?(): void;
  handleError?(error: Error | CIAPError): void;
}

Durante a autenticação, a biblioteca chama automaticamente os métodos de AuthenticationHandler.

Selecionar inquilinos

Para selecionar um inquilino, implemente selectTenant(). Pode implementar este método para escolher um inquilino programaticamente ou apresentar uma IU para que o utilizador possa selecionar um.

Em qualquer dos casos, a biblioteca usa o objeto SelectedTenantInfo devolvido para concluir o fluxo de autenticação. Contém o ID do inquilino selecionado, os IDs de fornecedor e o email introduzido pelo utilizador.

Se tiver vários inquilinos no seu projeto, tem de selecionar um antes de poder autenticar um utilizador. Se tiver apenas um inquilino ou estiver a usar a autenticação ao nível do projeto, não precisa de implementar selectTenant().

O IAP suporta os mesmos fornecedores que a Identity Platform, como:

  • Email e palavra-passe
  • OAuth (Google, Facebook, Twitter, GitHub, Microsoft, etc.)
  • SAML
  • OIDC
  • Número de telefone
  • Personalizado
  • Anónimo

Os tipos de autenticação por número de telefone, personalizados e anónimos não são suportados para a multilocação.

Selecionar inquilinos programaticamente

Para selecionar um inquilino de forma programática, tire partido do contexto atual. A classe Authentication contém getOriginalURL() que devolve o URL ao qual o utilizador estava a aceder antes da autenticação.

Use esta opção para localizar uma correspondência numa lista de inquilinos associados:

// Select provider programmatically.
selectTenant(projectConfig, tenantIds) {
  return new Promise((resolve, reject) => {
    // Show UI to select the tenant.
    auth.getOriginalURL()
      .then((originalUrl) => {
        resolve({
          tenantId: getMatchingTenantBasedOnVisitedUrl(originalUrl),
          // If associated provider IDs can also be determined,
          // populate this list.
          providerIds: [],
        });
      })
      .catch(reject);
  });
}

Permitir que os utilizadores selecionem inquilinos

Para permitir que o utilizador selecione um inquilino, apresente uma lista de inquilinos e peça ao utilizador para escolher um ou peça-lhe para introduzir o respetivo endereço de email e, em seguida, localize uma correspondência com base no domínio:

// Select provider by showing UI.
selectTenant(projectConfig, tenantIds) {
  return new Promise((resolve, reject) => {
    // Show UI to select the tenant.
    renderSelectTenant(
        tenantIds,
        // On tenant selection.
        (selectedTenantId) => {
          resolve({
            tenantId: selectedTenantId,
            // If associated provider IDs can also be determined,
            // populate this list.
            providerIds: [],
            // If email is available, populate this field too.
            email: undefined,
          });
        });
  });
}

Autenticação de utilizadores

Depois de ter um fornecedor, implemente getAuth() para devolver uma instância Auth, correspondente à chave da API e ao ID do inquilino fornecidos. Se não for fornecido nenhum ID do inquilino, use fornecedores de identidade ao nível do projeto.

getAuth() acompanha a localização onde o utilizador correspondente à configuração fornecida está armazenado. Também permite atualizar silenciosamente o token de ID da Identity Platform de um utilizador autenticado anteriormente sem exigir que o utilizador introduza novamente as respetivas credenciais.

Se estiver a usar vários recursos de IAP com inquilinos diferentes, recomendamos que use uma instância de autenticação exclusiva para cada recurso. Isto permite que vários recursos com configurações diferentes usem a mesma página de autenticação. Também permite que vários utilizadores iniciem sessão em simultâneo sem terminar a sessão do utilizador anterior.

Segue-se um exemplo de como implementar getAuth():

gcip-iap v1.0.0

getAuth(apiKey, tenantId) {
  let auth = null;
  // Make sure the expected API key is being used.
  if (apiKey !== expectedApiKey) {
    throw new Error('Invalid project!');
  }
  try {
    auth = firebase.app(tenantId || undefined).auth();
    // Tenant ID should be already set on initialization below.
  } catch (e) {
    // Use different App names for every tenant so that
    // multiple users can be signed in at the same time (one per tenant).
    const app = firebase.initializeApp(this.config, tenantId || '[DEFAULT]');
    auth = app.auth();
    // Set the tenant ID on the Auth instance.
    auth.tenantId = tenantId || null;
  }
  return auth;
}

gcip-iap v2.0.0

import {initializeApp, getApp} from 'firebase/app';
import {getAuth} from 'firebase/auth';

getAuth(apiKey, tenantId) {
  let auth = null;
  // Make sure the expected API key is being used.
  if (apiKey !== expectedApiKey)