Creating a sign-in page with FirebaseUI
Stay organized with collections
Save and categorize content based on your preferences.
To use external identities with Identity-Aware Proxy (IAP), your app needs a sign-in page. IAP will redirect users to this page to authenticate before they can access secure resources.
This article shows you how to build an authentication page using FirebaseUI, an open-source JavaScript library. FirebaseUI provides customizable elements that help reduce boilerplate code, and handles the flows for signing in users with a wide range of identity providers.
To get started faster, let IAP host the UI for you. This lets you try external identities without writing any additional code. For more advanced scenarios, you can also build your own sign-in page from scratch. This option is more complex, but gives you full control over the authentication flow and user experience.
Before you begin
Enable external identities, and select the I'll provide my own UI option during setup.
Installing the libraries
Install the gcip-iap, firebase, and firebaseui libraries. The
gcip-iap module abstracts communications between your app,
IAP, and Identity Platform. The firebase and firebaseui libraries provide the building blocks for your authentication UI.
npm install firebase --save
npm install firebaseui --save
npm install gcip-iap --save
Note that the gcip-iap module is not available using CDN.
You can then import the modules in your source files. Use the correct imports for your SDK version:
gcip-iap v0.1.4 or earlier
// 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 or later
Starting with version v1.0.0, gcip-iap requires the firebase v9 peer dependency or greater.
If you are migrating to gcip-iap v1.0.0 or above, complete the following
actions:
- Update the
firebaseandfirebaseuiversions in yourpackage.jsonfile to v9.6.0+ and v6.0.0+ respectively. - Update the
firebaseimport statements as follows:
// Import firebase modules.
importfirebase from'firebase/compat/app';
import'firebase/compat/auth';
// Import firebaseui module.
import* as firebaseui from'firebaseui'
// Import gcip-iap module.
No additional code changes are needed.
For additional installation options, including using localized versions of the libraries, refer to the instructions on GitHub.
Configuring your application
FirebaseUI uses a configuration object that specifies the tenants and providers to use for authentication. A full configuration can be very long, and might look something like this:
//Theprojectconfiguration.
constconfigs={
//ConfigurationforprojectidentifiedbyAPIkeyAPI_KEY1.
API_KEY1:{
authDomain:'project-id1.firebaseapp.com',
//Decidewhethertoaskuserforidentifiertofigureout
//whattenanttoselectorwhethertopresentallthetenantstoselectfrom.
displayMode:'optionFirst',//OridentifierFirst
//ThetermsofserviceURLandprivacypolicyURLforthepage
//wheretheuserselecttenantorenteremailfortenant/provider
//matching.
tosUrl:'http://localhost/tos',
privacyPolicyUrl:'http://localhost/privacypolicy',
callbacks:{
//Thecallbacktotriggerwhentheselectiontenantpage
//orenteremailfortenantmatchingpageisshown.
selectTenantUiShown:()=>{
//Showtitleandadditionaldisplayinfo.
},
//Thecallbacktotriggerwhenthesign-inpage
//isshown.
signInUiShown:(tenantId)=>{
//Showtenanttitleandadditionaldisplayinfo.
},
beforeSignInSuccess:(user)=>{
//Doadditionalprocessingonuserbeforesign-inis
//complete.
returnPromise.resolve(user);
}
},
tenants:{
//TenantconfigurationfortenantIDtenantId1.
tenantId1:{
//Fulllabel,displayname,buttoncolorandiconURLofthe
//tenantselectionbutton.Onlyneededifyouare
//usingtheoptionfirstoption.
fullLabel:'ACME Portal',
displayName:'ACME',
buttonColor:'#2F2F2F',
iconUrl:'<icon-url-of-sign-in-button>',
//Sign-inprovidersenabledfortenantId1.
signInOptions:[
//Microsoftsign-in.
{
provider:'microsoft.com',
providerName:'Microsoft',
buttonColor:'#2F2F2F',
iconUrl:'<icon-url-of-sign-in-button>',
loginHintKey:'login_hint'
},
//Email/passwordsign-in.
{
provider:'password',
//Donotrequiredisplaynameonsignup.
requireDisplayName:false,
disableSignUp:{
//Disableuserfromsigningupwithemailproviders.
status:true,
adminEmail:'admin@example.com',
helpLink:'https://www.example.com/trouble_signing_in'
}
},
//SAMLprovider.(multipleSAMLproviderscanbepassed)
{
provider:'saml.my-provider1',
providerName:'SAML provider',
fullLabel:'Employee Login',
buttonColor:'#4666FF',
iconUrl:'https://www.example.com/photos/my_idp/saml.png'
},
],
//Ifthereisonlyonesign-inprovidereligiblefortheuser,
//whethertoshowtheproviderselectionpage.
immediateFederatedRedirect:true,
signInFlow:'redirect',//Orpopup
//ThetermsofserviceURLandprivacypolicyURLforthesign-inpage
//specifictoeachtenant.
tosUrl:'http://localhost/tenant1/tos',
privacyPolicyUrl:'http://localhost/tenant1/privacypolicy'
},
//TenantconfigurationfortenantIDtenantId2.
tenantId2:{
fullLabel:'OCP Portal',
displayName:'OCP',
buttonColor:'#2F2F2F',
iconUrl:'<icon-url-of-sign-in-button>',
//Tenant2supportsaSAML,OIDCandEmail/passwordsign-in.
signInOptions:[
//Email/passwordsign-in.
{
provider:firebase.auth.EmailAuthProvider.PROVIDER_ID,
//Donotrequiredisplaynameonsignup.
requireDisplayName:false
},
//SAMLprovider.(multipleSAMLproviderscanbepassed)
{
provider:'saml.my-provider2',
providerName:'SAML provider',
fullLabel:'Contractor Portal',
buttonColor:'#4666FF',
iconUrl:'https://www.example.com/photos/my_idp/saml.png'
},
//OIDCprovider.(multipleOIDCproviderscanbepassed)
{
provider:'oidc.my-provider1',
providerName:'OIDC provider',
buttonColor:'#4666FF',
iconUrl:'https://www.example.com/photos/my_idp/oidc.png'
},
],
},
//TenantconfigurationfortenantIDtenantId3.
tenantId3:{
fullLabel:'Tenant3 Portal',
displayName:'Tenant3',
buttonColor:'#007bff',
iconUrl:'<icon-url-of-sign-in-button>',
//Tenant3supportsaGoogleandEmail/passwordsign-in.
signInOptions:[
//Email/passwordsign-in.
{
provider:firebase.auth.EmailAuthProvider.PROVIDER_ID,
//Donotrequiredisplaynameonsignup.
requireDisplayName:false
},
//Googleprovider.
{
provider:'google.com',
scopes:['scope1','scope2','https://example.com/scope3'],
loginHintKey:'login_hint',
customParameters:{
prompt:'consent',
},
},
],
//SetstheadminRestrictedOperationconfigurationforproviders
//includingfederated,email/password,emaillinkandphonenumber.
adminRestrictedOperation:{
status:true,
adminEmail:'admin@example.com',
helpLink:'https://www.example.com/trouble_signing_in'
}
},
},
},
};
The following sections provide guidance on how to configure some of the fields specific to IAP. For examples on setting other fields, see the code snippet above, or the FirebaseUI documentation on GitHub.
Setting the API key
A typical configuration begins with an API key for your project:
//Theprojectconfiguration.
constconfigs={
//ConfigurationforAPI_KEY.
API_KEY:{
//Configgoeshere
}
}
In most cases, you only need to specify a single API key. However, if you want to use a single authentication URL across multiple projects, you can include multiple API keys:
constconfigs={
API_KEY1:{
//Configgoeshere
},
API_KEY2:{
//Configgoeshere
},
}
Getting the authentication domain
Set the authdomain field to the domain provisioned to facilitate federated
sign-in. You can retrieve this field from the
Identity Platform page in the Google Cloud console.
Specifying tenants IDs
A configuration requires a list of tenants and providers that users can authenticate with.
Each tenant is identified by its ID. If you're using project-level
authentication (no tenants), use the special _ identifier as an API key
instead. For example:
constconfigs={
//ConfigurationforprojectidentifiedbyAPIkeyAPI_KEY1.
API_KEY1:{
tenants:{
//Project-levelIdPsflow.
_:{
//Tenantconfiggoeshere
},
//Singletenantflow.
1036546636501:{
//Tenantconfiggoeshere
}
}
}
}
You can also specify a wildcard tenant configuration using the * operator.
This tenant is used as a fallback if no matching ID is found.
Configuring tenant providers
Each tenant has its own providers; these are specified in the signInOptions
field:
tenantId1:{
signInOptions:[
// Options go here
]
}
See Configuring sign-in providers in the FirebaseUI documentation to learn how to configure providers.
In addition to the steps outlined in the FirebaseUI documentation, there are several fields specific to IAP that depend on the tenant selection mode you choose. See the next section for more information on these fields.
Choosing a tenant selection mode
Users can select a tenant in two ways: options-first mode, or identifier-first mode.
In options mode, the user begins by selecting a tenant from a list, then enters their username and password. In identifier mode, the user enters their email first. The system then automatically selects the first tenant with an identity provider matching the email's domain.
To use options mode, set displayMode to optionFirst. You'll then
need to provide configuration information for each tenant's button, including
displayName, buttonColor, and iconUrl. An optional fullLabel can also
be provided to override the entire button label instead of just the display
name.
The following is an example of a tenant configured to use options mode:
tenantId1: {
fullLabel: 'ACME Portal',
displayName: 'ACME',
buttonColor: '#2F2F2F',
iconUrl: '<icon-url-of-sign-in-button>',
// ...
To use identifier mode, each sign-in option must specify an hd field
indicating what domain it supports. This can be either a regex (such as
/@example\.com$/) or the domain string (e.g., example.com).
The code below shows a tenant configured to use identifier mode:
tenantId1:{
signInOptions:[
//Email/passwordsign-in.
{
hd:'acme.com',//usingregex:/@acme\.com$/
//...
},
Enabling immediate redirect
If your app only supports a single identity provider, setting
immediateFederatedRedirect to true will skip the sign-in UI and
redirect the user directly to the provider.
Setting up callbacks
The configuration object contains a set of callbacks that are invoked at various points during the authentication flow. This lets you additionally customize the UI. The following hooks are available:
selectTenantUiShown()
Triggered when the UI to select a tenant is shown. Use this if you want
to modify the UI with a customized title or theme.
signInUiShown(tenantId)
Triggered when a tenant is selected and the UI for the user to enter their
credentials is shown. Use this if you want to modify the UI with a
customized title or theme.
beforeSignInSuccess(user)
Triggered before sign-in completes. Use this to modify a signed in user
before redirecting back to the IAP resource.
The following example code shows how you might implement these callbacks:
callbacks:{
selectTenantUiShown:()=>{
//ShowinfooftheIAPresource.
showUiTitle(
'Select your employer to access your Health Benefits');
},
signInUiShown:(tenantId)=>{
//Showtenanttitleandadditionaldisplayinfo.
consttenantName=getTenantNameFromId(tenantId);
showUiTitle(`Sign in to access your ${tenantName} Health Benefits`);
},
beforeSignInSuccess:(user)=>{
//Doadditionalprocessingonuserbeforesign-inis
//complete.
//Forexampleupdatetheuserprofile.
returnuser.updateProfile({
photoURL:'https://example.com/profile/1234/photo.png',
}).then(function(){
//ToreflectupdatedphotoURLintheIDtoken,forcetoken
//refresh.
returnuser.getIdToken(true);
}).then(function(){
returnuser;
});
}
}
Initializing the library
Once you've created a configuration object, follow these steps to initialize the library on your authentication page:
Create an HTML container to render the UI in.
<!DOCTYPE html> <html> <head>...</head> <body> <!--ThesurroundingHTMLisleftuntouchedbyFirebaseUI. Yourappmayusethatspaceforbranding,controlsandother customizations.--> <h1>WelcometoMyAwesomeApp</h1> <divid="firebaseui-auth-container"></div> </body> </html>Create a
FirebaseUiHandlerinstance to render in the HTML container, and pass theconfigelement you created to it.constconfigs={ //... } consthandler=newfirebaseui.auth.FirebaseUiHandler( '#firebaseui-auth-container',configs);Create a new
Authenticationinstance, pass the handler to it, and callstart().constciapInstance=newciap.Authentication(handler); ciapInstance.start();
Deploy your application and navigate to the authentication page. A sign-in UI containing your tenants and providers should appear.
What's next
- Learn how to access non-Google resources programmatically.
- Learn about managing sessions.
- Gain a deeper understanding of how external identities work with IAP.