Para usar identidades externas com o Identity-Aware Proxy (IAP), a sua app precisa de uma página de início de sessão. O IAP vai redirecionar os utilizadores para esta página para autenticação antes de poderem aceder a recursos seguros.
Este artigo mostra-lhe como criar uma página de autenticação com o FirebaseUI, uma biblioteca de JavaScript de código aberto. A FirebaseUI oferece elementos personalizáveis que ajudam a reduzir o código repetitivo e processa os fluxos para iniciar a sessão dos utilizadores com uma vasta gama de fornecedores de identidade.
Para começar mais rapidamente, deixe que a IAP hospede a IU por si. Isto permite-lhe experimentar identidades externas sem escrever código adicional. Para cenários mais avançados, também pode criar a sua própria página de início de sessão de raiz. Esta opção é mais complexa, mas dá-lhe controlo total sobre o fluxo de autenticação e a experiência do utilizador.
Antes de começar
Ative as identidades externas e selecione a opção Vou fornecer a minha própria IU durante a configuração.
Instalar as bibliotecas
Instale as bibliotecas gcip-iap
, firebase
e firebaseui
. O módulo
gcip-iap
abstrai as comunicações entre a sua app, a
IAP e a Identity Platform. As bibliotecas firebase
e firebaseui
fornecem os componentes fundamentais para a IU de autenticação.
npm install firebase --save
npm install firebaseui --save
npm install gcip-iap --save
Tenha em atenção que o módulo gcip-iap
não está disponível através da CDN.
Em seguida, pode import
os módulos nos ficheiros de origem. Use as importações corretas para a versão do seu SDK:
gcip-iap v0.1.4 ou anterior
// Import firebase modules.
import * as firebase from "firebase/app";
import "firebase/auth";
// Import firebaseui module.
import * as firebaseui from 'firebaseui'
// Import gcip-iap module.
import * as ciap from 'gcip-iap';
gcip-iap v1.0.0 ou posterior
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 as versões
firebase
efirebaseui
no ficheiropackage.json
para v9.6.0+ e v6.0.0+, respetivamente. - Atualize as
firebase
declarações de importação da seguinte forma:
// Import firebase modules.
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
// Import firebaseui module.
import * as firebaseui from 'firebaseui'
// Import gcip-iap module.
Não são necessárias alterações adicionais ao código.
Para ver opções de instalação adicionais, incluindo a utilização de versões localizadas das bibliotecas, consulte as instruções no GitHub.
Configurar a sua aplicação
A FirebaseUI usa um objeto de configuração que especifica os inquilinos e os fornecedores a usar para autenticação. Uma configuração completa pode ser muito longa e ter um aspeto semelhante a este:
// The project configuration.
const configs = {
// Configuration for project identified by API key API_KEY1.
API_KEY1: {
authDomain: 'project-id1.firebaseapp.com',
// Decide whether to ask user for identifier to figure out
// what tenant to select or whether to present all the tenants to select from.
displayMode: 'optionFirst', // Or identifierFirst
// The terms of service URL and privacy policy URL for the page
// where the user select tenant or enter email for tenant/provider
// matching.
tosUrl: 'http://localhost/tos',
privacyPolicyUrl: 'http://localhost/privacypolicy',
callbacks: {
// The callback to trigger when the selection tenant page
// or enter email for tenant matching page is shown.
selectTenantUiShown: () => {
// Show title and additional display info.
},
// The callback to trigger when the sign-in page
// is shown.
signInUiShown: (tenantId) => {
// Show tenant title and additional display info.
},
beforeSignInSuccess: (user) => {
// Do additional processing on user before sign-in is
// complete.
return Promise.resolve(user);
}
},
tenants: {
// Tenant configuration for tenant ID tenantId1.
tenantId1: {
// Full label, display name, button color and icon URL of the
// tenant selection button. Only needed if you are
// using the option first option.
fullLabel: 'ACME Portal',
displayName: 'ACME',
buttonColor: '#2F2F2F',
iconUrl: '<icon-url-of-sign-in-button>',
// Sign-in providers enabled for tenantId1.
signInOptions: [
// Microsoft sign-in.
{
provider: 'microsoft.com',
providerName: 'Microsoft',
buttonColor: '#2F2F2F',
iconUrl: '<icon-url-of-sign-in-button>',
loginHintKey: 'login_hint'
},
// Email/password sign-in.
{
provider: 'password',
// Do not require display name on sign up.
requireDisplayName: false,
disableSignUp: {
// Disable user from signing up with email providers.
status: true,
adminEmail: 'admin@example.com',
helpLink: 'https://www.example.com/trouble_signing_in'
}
},
// SAML provider. (multiple SAML providers can be passed)
{
provider: 'saml.my-provider1',
providerName: 'SAML provider',
fullLabel: 'Employee Login',
buttonColor: '#4666FF',
iconUrl: 'https://www.example.com/photos/my_idp/saml.png'
},
],
// If there is only one sign-in provider eligible for the user,
// whether to show the provider selection page.
immediateFederatedRedirect: true,
signInFlow: 'redirect', // Or popup
// The terms of service URL and privacy policy URL for the sign-in page
// specific to each tenant.
tosUrl: 'http://localhost/tenant1/tos',
privacyPolicyUrl: 'http://localhost/tenant1/privacypolicy'
},
// Tenant configuration for tenant ID tenantId2.
tenantId2: {
fullLabel: 'OCP Portal',
displayName: 'OCP',
buttonColor: '#2F2F2F',
iconUrl: '<icon-url-of-sign-in-button>',
// Tenant2 supports a SAML, OIDC and Email/password sign-in.
signInOptions: [
// Email/password sign-in.
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
// Do not require display name on sign up.
requireDisplayName: false
},
// SAML provider. (multiple SAML providers can be passed)
{
provider: 'saml.my-provider2',
providerName: 'SAML provider',
fullLabel: 'Contractor Portal',
buttonColor: '#4666FF',
iconUrl: 'https://www.example.com/photos/my_idp/saml.png'
},
// OIDC provider. (multiple OIDC providers can be passed)
{
provider: 'oidc.my-provider1',
providerName: 'OIDC provider',
buttonColor: '#4666FF',
iconUrl: 'https://www.example.com/photos/my_idp/oidc.png'
},
],
},
// Tenant configuration for tenant ID tenantId3.
tenantId3: {
fullLabel: 'Tenant3 Portal',
displayName: 'Tenant3',
buttonColor: '#007bff',
iconUrl: '<icon-url-of-sign-in-button>',
// Tenant3 supports a Google and Email/password sign-in.
signInOptions: [
// Email/password sign-in.
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
// Do not require display name on sign up.
requireDisplayName: false
},
// Google provider.
{
provider: 'google.com',
scopes: ['scope1', 'scope2', 'https://example.com/scope3'],
loginHintKey: 'login_hint',
customParameters: {
prompt: 'consent',
},
},
],
// Sets the adminRestrictedOperation configuration for providers
// including federated, email/password, email link and phone number.
adminRestrictedOperation: {
status: true,
adminEmail: 'admin@example.com',
helpLink: 'https://www.example.com/trouble_signing_in'
}
},
},
},
};
As secções seguintes fornecem orientações sobre como configurar alguns dos campos específicos da IAP. Para ver exemplos de definição de outros campos, consulte o fragmento de código acima ou a documentação do FirebaseUI no GitHub.
Definir a chave da API
Uma configuração típica começa com uma chave da API para o seu projeto:
// The project configuration.
const configs = {
// Configuration for API_KEY.
API_KEY: {
// Config goes here
}
}
Na maioria dos casos, só tem de especificar uma única chave da API. No entanto, se quiser usar um único URL de autenticação em vários projetos, pode incluir várias chaves da API:
const configs = {
API_KEY1: {
// Config goes here
},
API_KEY2: {
// Config goes here
},
}
Obter o domínio de autenticação
Defina o campo authdomain
para o domínio aprovisionado para facilitar o início de sessão federado. Pode obter este campo na página do Identity Platform na Google Cloud consola.
Especificar IDs de inquilinos
Uma configuração requer uma lista de inquilinos e fornecedores com os quais os utilizadores se podem autenticar.
Cada inquilino é identificado pelo respetivo ID. Se estiver a usar a autenticação ao nível do projeto (sem inquilinos), use o identificador especial _
como chave da API. Por exemplo:
const configs = {
// Configuration for project identified by API key API_KEY1.
API_KEY1: {
tenants: {
// Project-level IdPs flow.
_: {
// Tenant config goes here
},
// Single tenant flow.
1036546636501: {
// Tenant config goes here
}
}
}
}
Também pode especificar uma configuração de inquilino de caráter universal através do operador *
.
Este inquilino é usado como alternativa se não for encontrado nenhum ID correspondente.
Configurar fornecedores de inquilinos
Cada inquilino tem os seus próprios fornecedores, que são especificados no campo signInOptions
:
tenantId1: {
signInOptions: [
// Options go here
]
}
Consulte o artigo Configurar fornecedores de início de sessão na documentação do FirebaseUI para saber como configurar fornecedores.
Além dos passos descritos na documentação do FirebaseUI, existem vários campos específicos da IAP que dependem do modo de seleção do inquilino que escolher. Consulte a secção seguinte para ver mais informações sobre estes campos.
Escolher um modo de seleção de inquilinos
Os utilizadores podem selecionar um inquilino de duas formas: modo de opções primeiro ou modo de identificador primeiro.
No modo de opções, o utilizador começa por selecionar um inquilino a partir de uma lista e, em seguida, introduz o nome de utilizador e a palavra-passe. No modo de identificador, o utilizador introduz primeiro o respetivo email. Em seguida, o sistema seleciona automaticamente o primeiro inquilino com um fornecedor de identidade que corresponda ao domínio do email.
Para usar o modo de opções, defina displayMode
como optionFirst
. Em seguida, tem de fornecer informações de configuração para o botão de cada inquilino, incluindo displayName
, buttonColor
e iconUrl
. Também pode fornecer um fullLabel
opcional para substituir toda a etiqueta do botão em vez de apenas o nome de apresentação.
Segue-se um exemplo de um inquilino configurado para usar o modo de opções:
tenantId1: {
fullLabel: 'ACME Portal',
displayName: 'ACME',
buttonColor: '#2F2F2F',
iconUrl: '<icon-url-of-sign-in-button>',
// ...
Para usar o modo de identificador, cada opção de início de sessão tem de especificar um campo hd
que indique o domínio que suporta. Pode ser uma regex (como
/@example\.com$/
) ou a string de domínio (por exemplo, example.com
).
O código abaixo mostra um inquilino configurado para usar o modo de identificador:
tenantId1: {
signInOptions: [
// Email/password sign-in.
{
hd: 'acme.com', // using regex: /@acme\.com$/
// ...
},
Ativar redirecionamento imediato
Se a sua app só for compatível com um fornecedor de identidade, a definição de immediateFederatedRedirect
como true
ignora a IU de início de sessão e redireciona o utilizador diretamente para o fornecedor.
Configurar chamadas de retorno
O objeto de configuração contém um conjunto de callbacks que são invocados em vários pontos durante o fluxo de autenticação. Isto permite-lhe personalizar ainda mais a IU. Estão disponíveis os seguintes hooks:
selectTenantUiShown() |
Acionado quando é apresentada a IU para selecionar um inquilino. Use esta opção se quiser modificar a IU com um título ou um tema personalizado. |
signInUiShown(tenantId) |
Acionado quando um inquilino é selecionado e a IU para o utilizador introduzir as respetivas credenciais é apresentada. Use esta opção se quiser modificar a IU com um título ou um tema personalizado. |
beforeSignInSuccess(user) |
Acionado antes de o início de sessão ser concluído. Use esta opção para modificar um utilizador com sessão iniciada antes de redirecionar novamente para o recurso de CAsI. |
O exemplo de código seguinte mostra como pode implementar estes callbacks:
callbacks: {
selectTenantUiShown: () => {
// Show info of the IAP resource.
showUiTitle(
'Select your employer to access your Health Benefits');
},
signInUiShown: (tenantId) => {
// Show tenant title and additional display info.
const tenantName = getTenantNameFromId(tenantId);
showUiTitle(`Sign in to access your ${tenantName} Health Benefits`);
},
beforeSignInSuccess: (user) => {
// Do additional processing on user before sign-in is
// complete.
// For example update the user profile.
return user.updateProfile({
photoURL: 'https://example.com/profile/1234/photo.png',
}).then(function() {
// To reflect updated photoURL in the ID token, force token
// refresh.
return user.getIdToken(true);
}).then(function() {
return user;
});
}
}
A inicializar a biblioteca
Depois de criar um objeto de configuração, siga estes passos para inicializar a biblioteca na sua página de autenticação:
Crie um contentor HTML para renderizar a IU.
<!DOCTYPE html> <html> <head>...</head> <body> <!-- The surrounding HTML is left untouched by FirebaseUI. Your app may use that space for branding, controls and other customizations.--> <h1>Welcome to My Awesome App</h1> <div id="firebaseui-auth-container"></div> </body> </html>
Crie uma instância
FirebaseUiHandler
para renderizar no contentor HTML e transmita-lhe o elementoconfig
que criou.const configs = { // ... } const handler = new firebaseui.auth.FirebaseUiHandler( '#firebaseui-auth-container', configs);
Crie uma nova instância
Authentication
, transmita o controlador para esta e chamestart()
.const ciapInstance = new ciap.Authentication(handler); ciapInstance.start();
Implemente a sua aplicação e navegue para a página de autenticação. Deve ser apresentada uma IU de início de sessão com os seus inquilinos e fornecedores.
O que se segue?
- Saiba como aceder a recursos não pertencentes à Google através de programação.
- Saiba como gerir sessões.
- Compreenda melhor como as identidades externas funcionam com a IAP.