Hosting a sign-in page with Cloud Run

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 deploy and customize a pre-built sign-in page using Cloud Run. This is the fastest way to get started with external identities, and doesn't require you to write any code.

You can also build a sign-in page yourself. Building your own page is more difficult, but increases your control over the authentication flow and user experience. See Creating a sign-in page with FirebaseUI and Creating a custom sign-in page to learn more.

Before you begin

Testing the sign-in page

The initial sign-in page created by IAP is fully functional. To test it:

  1. Navigate to a resource protected by IAP. You should be automatically redirected to the sign-in page.

  2. Select a tenant and provider to sign-in with. If you don't see any tenants or providers listed, make sure you've configured one using Identity Platform.

  3. Sign in with your credentials.

You should be redirected to the protected resource.

Customizing the sign-in page

You can customize the sign-in page using a JSON configuration file. Some options include:

  • Adding a header and logo to the sign-in page.
  • Specifying the available tenants and providers.
  • Customizing the icons and styling of each tenant and provider button.
  • Adding links to your app's privacy policy and terms of service.

The following sections explain how to access and update the JSON configuration file.

Obtaining an access token

In order to administer the sign-in page, you need a Google access token. The easiest way to obtain one is by enabling Google as an provider for Identity Platform. If your app already uses Google as an identity provider, you can skip this section.

  1. Go to the Identity Platform Providers page in the Cloud Console.

    Go to the Identity Platform Providers page

  2. Click Add a Provider.

  3. Select Google from the list of providers.

  4. Configure the Web Client ID and Web Client Secret:

    1. In a separate tab, open the IAP page.

      Go to the IAP page

    2. Expand the View more menu for your resource, then click Edit OAuth Client.

    3. Copy the Client ID and Client secret fields into the Google provider configuration for Identity Platform.

    4. Add the Identity Platform redirect URL to the list of Authorized Redirect URIs for the OAuth client. The URL is formatted like https://<var>PROJECT_ID</var>.firebaseapp.com/__/auth/handler.

  5. Click Save on both pages.

Signing in to the admin panel

The JSON configuration for the sign-in page hosted by Cloud Run. The following steps show how to access the panel. Note that you'll need the Storage Admin (roles/storage.admin) role.

  1. Go to the IAP page in the Cloud Console.

    Go to the IAP page

  2. Select your resource from the list.

  3. Launch the URL listed under Customize page in the info panel. It should look something like https://servicename-xyz-uc.a.run.app/admin.

  4. Sign in with the same Google account you used to configure IAP. A text editor containing the JSON configuration file appears.

Modifying the configuration

The configuration schema for the sign-in page is based on FirebaseUI, and inherits many of its properties. The following code shows an example configuration with two tenants:

{
  "AIzaSyC5DtmRUR...": {
    "authDomain": "awesomeco.firebaseapp.com",
    "displayMode": "optionFirst",
    "selectTenantUiTitle": "Awesome Company Portal",
    "selectTenantUiLogo": "https://awesome.com/abcd/logo.png",
    "styleUrl": "https://awesome.com/abcd/overrides/stylesheet.css",
    "tosUrl": "https://awesome.com/abcd/tos.html",
    "privacyPolicyUrl": "https://awesome.com/abcd/privacypolicy.html",
    "tenants": {
      "tenant-a-id": {
        "fullLabel": "Company A Portal",
        "displayName": "Company A",
        "iconUrl": "https://companya.com/img/icon.png",
        "logoUrl": "https://companya.com/img/logo.png",
        "buttonColor": "#007bff",
        "signInOptions": [
          "password",
          "facebook.com",
          "google.com",
          "microsoft.com",
          {
            "provider": "saml.okta-cicp-app",
            "providerName": "Corp Account",
            "fullLabel": "Employee Corporate Login",
            "buttonColor": "#ff0000",
            "iconUrl": "https://companya.com/abcd/icon-1.png"
          },
          {
            "provider": "oidc.okta-oidc",
            "providerName": "Contractor Account",
            "fullLabel": "Contractor Account Portal",
            "buttonColor": "#00ff00",
            "iconUrl": "https://companya.com/abcd/icon-2.png"
          }
        ],
        "tosUrl": "https://companya.com/abcd/tos.html",
        "privacyPolicyUrl": "https://companya.com/abcd/privacypolicy.html"
      },
      "tenant-b-id": {
        "fullLabel": "Company B Portal",
        "displayName": "Company B",
        "iconUrl": "https://companyb.com/img/icon.png",
        "logoUrl": "https://companyb.com/img/logo.png",
        "buttonColor": "#007bff",
        "immediateFederatedRedirect": true,
        "signInOptions": [
          {
            "provider": "saml.okta-bla-app",
            "providerName": "Corp Account",
            "buttonColor": "#0000ff",
            "iconUrl": "https://companyb.com/abcd/icon.png"
          }
        ],
        "tosUrl": "https://companyb.com/abcd/tos.html",
        "privacyPolicyUrl": "https://companyb.com/abcd/privacypolicy.html"
      }
    }
  }
}

For a complete list of available properties, see the reference documentation.

Overriding CSS

You can use the styleUrl property to specify a custom CSS file. Styles in this file will override the default CSS. The file must be publicly accessible using HTTPS (for example, hosted in a Cloud Storage bucket).

The following example demonstrates overriding the default CSS:

/** Change header title style. */
.heading-center {
  color: #7181a5;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 20px;
  font-weight: bold;
}

/** Use round edged borders for container. */
.main-container {
  border-radius: 5px;
}

/** Change page background color. */
body {
  background-color: #f8f9fa;
}

Redeploying the Cloud Run instance

In some cases, you might want to redeploy the Cloud Run instance that hosts the sign-in page. Example scenarios include:

  • Adding, modifying, or removing identity providers
  • Modifying tenant configurations
  • Setting environment variables
  • Updating the container image to the latest version

Regularly updating and redeploying the container image ensures you have the latest bug fixes and security patches. You can view the list of changes between versions on GitHub.

You can get the current version of the deployed container using the /versionz endpoint. For example:

curl 'https://servicename-xyz-uc.a.run.app/versionz'

To redeploy the Cloud Run instance:

  1. Go to the Cloud Run page in the Cloud Console.

    Go to the Cloud Run page

  2. Select the instance hosting the sign-in page.

  3. Click Edit & Deploy New Revision.

  4. Optionally, specify advanced settings for the revision, or add an environment variable by clicking the Variables & Secrets tab.

  5. Click Deploy.

Advanced options

Customizing the sign-in page programmatically

In addition to using the /admin console, you can update the JSON configuration programmatically.

To get the current configuration, use the /get_admin_config endpoint. For example:

curl -H 'Authorization: Bearer [TOKEN]'
  'https://servicename-xyz-uc.a.run.app/get_admin_config'

To update the configuration, use /set_admin_config. For example:

curl -XPOST -H 'Authorization: Bearer [TOKEN]' -H "Content-type: application/json"
  -d '[UPDATED-CONFIG]' 'https://servicename-xyz-uc.a.run.app/set_admin_config'

Both REST calls require the https://www.googleapis.com/auth/devstorage.read_write scope, and a valid OAuth token must be attached to the Authorization header.

Setting environment variables

You can set environment variables on the Cloud Run instance to customize advance settings. The following table lists the available variables:

Variable Description
DEBUG_CONSOLE A boolean value (0 or 1) indicating whether to log all network request errors and details. Sensitive data will not be logged. Disabled (0) by default.
UI_CONFIG A string containing the JSON configuration for the sign-in page. Using this variable instead of the /admin panel avoids reading and writing to a Cloud Storage when accessing the configuration. Invalid configurations are ignored. Using the /admin panel to validate your JSON before setting this variable can help minimize syntax errors.
GCS_BUCKET_NAME A string overriding the default Cloud Storage bucket used to store the JSON configuration. The file is named config.json, and the default location is gcip-iap-bucket-[CLOUD-RUN-SERVICE-NAME]-[PROJECT-NUMBER].
ALLOW_ADMIN A boolean value (0 or 1) indicating whether to allow access to the /admin configuration panel. Enabled (1) by default.

You'll need to deploy a new revision of the Cloud Run instance after updating variables before the changes take effect. To learn more about environment variables, see the Cloud Run documentation.

Customizing the domain

By default, users will see the URL of the Cloud Run instance when signing in. To specify a custom domain instead:

  1. Follow the steps in Mapping custom domains to set a custom domain for the Cloud Run instance.

  2. Configure IAP to use the new authentication URL:

    1. Go to the IAP page in the Cloud Console.

      Go to the IAP page

    2. Select the resource protected by IAP.

    3. In the side panel, select the Edit icon next to the Login URL field.

    4. Select Use an existing hosted sign-in page, and choose your domain from the drop-down menu.

    5. Click Save.

Using one sign-in page for multiple IAP resources

You can protect multiple IAP resources using the same sign-in page. This reduces the work associated with managing multiple configurations.

To re-use a sign-in page:

  1. Follow the steps in this article to deploy the authentication page for the first resource protected by IAP.

  2. Enable IAP for the second resource. When prompted to specify a sign-in page, select I'll provide my own, and enter the URL of the Cloud Run service as the URL.

  3. Redeploy the Cloud Run service.

What's next