Cloud Run を使用したログインページのホスティング

Identity-Aware Proxy(IAP)で外部 ID を使用するには、ログインページをアプリ側で用意する必要があります。IAP は、ユーザーがセキュリティで保護されたリソースにアクセスする前に、このページにリダイレクトして認証します。

このドキュメントでは、Cloud Run を使用して作成済みのログインページをデプロイし、カスタマイズする方法を説明します。これは外部 ID を使用する最も早い方法です。また、コードを記述する必要はありません。

ご自身でログインページを作成することもできます。独自のログインページを作成することはより難しいですが、認証フローとユーザー エクスペリエンスに対する制御性が向上します。詳しくは、FirebaseUI を使用したログインページの作成カスタム ログインページの作成をご覧ください。

ログインページの制限事項

プロジェクトでメールの列挙保護が有効になっている場合、事前構築済みのログインページは使用できません。

プロジェクトでメール列挙保護が有効になっている場合は、email-enumeration-protection を無効にしてから、このドキュメントの手順に進んでください。

準備

  • Compute Engine API を有効にします。

    Compute Engine API を有効にする

  • 外部 ID を有効にして、設定時に [ログインページを作成] オプションを選択します。これにより、Cloud Run と FirebaseUI によってログインページが作成されます。

  • Cloud Run で使用されるサービス アカウント(PROJECT_NUMBER-compute@developer.gserviceaccount.com)に、次の事前定義されたロールがあることを確認します。

    • roles/identitytoolkit.viewer
    • roles/iap.settingsAdmin
    • roles/compute.networkViewer

ホストされているページのリダイレクト URL の設定

ホストされているログインページは、独自のドメインを Firebase 認証ドメインとして使用し、リダイレクトを介したログインがすべての環境で正しく機能するようにします。ホストされているページの URL を、承認済みのリダイレクト URL としてプロバイダの構成に追加する必要があります。

ホストされているログインページの URL を承認済みのリダイレクト URL として追加する手順は次のとおりです。

  1. アプリケーションを選択したら、[ログイン URL] をコピーします。

  2. Google Cloud コンソールで、[認証情報] ページに移動します。

    認証情報に進む

  3. アプリの OAuth 2.0 クライアント用の承認済みのリダイレクト URI の 1 つとして LOGIN_URL/__/auth/handler を追加します。プロバイダの構成に使用したのと同じ OAuth クライアント ID とシークレット キーを選択します。

  4. アプリで他の SAML プロバイダと OIDC プロバイダを使用している場合は、承認済みのリダイレクト URI または ACS URL として LOGIN_URL/__/auth/handler を追加します。

または、ポップアップ ログインフローを使用してログインページをカスタマイズすることで、LOGIN_URL/__/auth/handler ではなく PROJECT_ID.firebaseapp.com を認証ドメインとして使用することもできます。

ページにポップアップ ログイン フローを実装する手順は次のとおりです。

  1. [ページのカスタマイズ] をクリックします。

  2. JSON 形式の構成ファイルでは、authDomainPROJECT_ID.firebaseapp.com に、signInFlowpopup に設定します。

  3. 構成を保存するには、[保存] をクリックします。

以下を置き換えます。

  • LOGIN_URL: ホストされているログインページのドメイン
  • PROJECT_ID: Firebase プロジェクト ID

ポップアップ ログイン フローの構成例を次に示します。

{
  "AIzaSyC5DtmRUR...": {
    "authDomain": "example.firebaseapp.com",
    "displayMode": "optionFirst",
    ...
    ...
    "tenants": {
      "tenant-a-id": {
        "fullLabel": "Company A Portal",
        "displayName": "Company A",
        ...
        ...
        "signInFlow": "popup",
        ...
        ...
      }
    }
  }
}

リダイレクトのベスト プラクティスとストレージ パーティショニングの詳細については、サードパーティのストレージ アクセスをブロックするブラウザで signInWithRedirect を使用する場合のベスト プラクティスをご覧ください。

ログインページをテストする

IAP によって作成された最初のログインページは完全に動作します。ログインページをテストするには:

  1. IAP で保護されたリソースに移動します。ログインページに自動的にリダイレクトされます。

  2. ログインに使用するテナントとプロバイダを選択します。テナントまたはプロバイダがリストに表示されない場合は、Identity Platform を使用して構成されていることを確認します。

  3. 自分の認証情報でログインします。

保護されたリソースにリダイレクトされます。

ログインページのカスタマイズ

JSON 構成ファイルを使用してログインページをカスタマイズできます。次のようなオプションがあります。

  • ログインページにヘッダーとロゴを追加する。
  • 使用可能なテナントとプロバイダを指定する。
  • 各テナントとプロバイダのボタンのアイコンとスタイルをカスタマイズする。
  • アプリのプライバシー ポリシーと利用規約へのリンクを追加する。

以下のセクションでは、JSON 構成ファイルにアクセスして更新する方法について説明します。

アクセス トークンの取得

ログインページを管理するには Google のアクセス トークンが必要です。これを取得する最も簡単な方法は、Identity Platform のプロバイダとして Google を有効にすることです。アプリですでに Google が ID プロバイダとして使用されている場合は、このセクションをスキップできます。

  1. Google Cloud コンソールで [Identity Platform Providers] ページに移動します。

    Identity Platform プロバイダ ページに移動

  2. [プロバイダを追加] をクリックします。

  3. プロバイダのリストから Google を選択します。

  4. ウェブ クライアント IDウェブ クライアント シークレットを構成します。

    1. 別のタブで IAP ページを開きます。

      IAP ページに移動

    2. リソースの [詳細] メニューを展開して、[OAuth クライアントを編集] をクリックします。

    3. [Client ID] フィールドと [Client secret] フィールドを Identity Platform の Google プロバイダの構成にコピーします。

    4. Identity Platform のリダイレクト URL を、OAuth クライアントの [承認済みリダイレクト URI] のリストに追加します。URL は、https://PROJECT_ID.firebaseapp.com/__/auth/handler のような形式です。

  5. 両方のページで [保存] をクリックします。

管理パネルへのログイン

ログインのページの JSON 構成は、Cloud Run でホストされました。管理者パネルにアクセスする方法は次のとおりです。ストレージ管理者(roles/storage.admin)ロールが必要になりますので、注意してください。

  1. Google Cloud コンソールで [IAP] ページに移動します。

    IAP ページに移動

  2. リストからリソースを選択します。

  3. 情報パネルの [ページのカスタマイズ] に表示されている URL をクリックします。URL は、https://servicename-xyz-uc.a.run.app/admin のような形式になります。

  4. IAP の構成に使用したのと同じ Google アカウントでログインします。JSON 構成ファイルを含むテキスト エディタが表示されます。

構成の変更

ログインページの構成スキーマは FirebaseUI に基づいており、多くのプロパティを継承しています。次のコードは、3 つのテナントを含む構成の例を示しています。

{
  "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": [
          {
            "provider": "password",
            "requireDisplayName": false,
            "disableSignUp": {
              "status": true,
              "adminEmail": "admin@example.com",
              "helpLink": "https://www.example.com/trouble_signing_in"
            }
          },
          "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"
      },
      "tenant-c-id": {
        "fullLabel": "Company C Portal",
        "displayName": "Company C",
        "iconUrl": "https://companyc.com/img/icon.png",
        "logoUrl": "https://companyc.com/img/logo.png",
        "buttonColor": "#007bff",
        "immediateFederatedRedirect": true,
        "signInOptions": [
          {
            "provider": "password",
            "requireDisplayName": false
          },
          {
            "provider": "google.com",
            "scopes": ["scope1", "scope2", "https://example.com/scope3"],
            "loginHintKey": "login_hint",
            "customParameters": {
              "prompt": "consent",
            },
          }
        ],
        "tosUrl": "https://companyc.com/abcd/tos.html",
        "privacyPolicyUrl": "https://companyc.com/abcd/privacypolicy.html",
        "adminRestrictedOperation": {
          "status": true,
          "adminEmail": "admin@example.com",
          "helpLink": "https://www.example.com/trouble_signing_in"
        }
      },
    }
  }
}

使用可能なプロパティの完全な一覧については、リファレンス ドキュメントをご覧ください。

CSS のオーバーライド

styleUrl プロパティを使用して、カスタム CSS ファイルを指定できます。このファイルのスタイルはデフォルトの CSS よりも優先されます。このファイルは、HTTPS で一般公開する必要があります(たとえば、Cloud Storage バケットでホストする)。

デフォルトの 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;
}

Cloud Run インスタンスの再デプロイ

場合によっては、ログインページをホストする Cloud Run インスタンスを再デプロイすることもあります。次のようなシナリオの場合です。

  • ID プロバイダの追加、変更、削除
  • テナント構成の変更
  • 環境変数の設定
  • コンテナ イメージの最新バージョンへの更新

コンテナ イメージを定期的に更新、再デプロイすることで、最新のバグ修正とセキュリティ パッチを適用できます。バージョン間の変更の一覧は、GitHub で確認できます。

/versionz エンドポイントを使用して、デプロイされたコンテナの現在のバージョンを取得できます。次に例を示します。

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

Cloud Run インスタンスを再デプロイするには:

  1. Google Cloud コンソールで [Cloud Run] ページに移動します。

    [Cloud Run] ページに移動

  2. ログインページをホストしているインスタンスを選択します。

  3. [新しいリビジョンを編集してデプロイ] をクリックします。

  4. 必要に応じて、リビジョンの詳細設定を指定するか、[変数とSecret] タブをクリックして環境変数を追加します。

  5. [デプロイ] をクリックします。

詳細オプション

プログラムによるログインページのカスタマイズ

/admin コンソールの使用に加えて、JSON 構成をプログラムで更新できます。

現在の構成を取得するには、/get_admin_config エンドポイントを使用します。例:

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

構成を更新するには、/set_admin_config を使用します。次に例を示します。

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

どちらの REST 呼び出しにも https://www.googleapis.com/auth/devstorage.read_write スコープが必要で、有効な OAuth トークンを Authorization ヘッダーに付加する必要があります。

環境変数の設定

Cloud Run インスタンスで環境変数を設定して、高度な設定をカスタマイズできます。次の表に使用可能な変数を示します。

変数 説明
DEBUG_CONSOLE すべてのネットワーク リクエスト エラーと詳細をログに記録するかどうかを示すブール値(0 または 1)。センシティブ データはログに記録されません。デフォルトで無効(0)です。
UI_CONFIG ログインページの JSON 構成を含む文字列。/admin パネルの代わりにこの変数を使用すると、構成にアクセスするときに Cloud Storage に対する読み取りと書き込みが行われません。無効な構成は無視されます。この変数を設定する前に /admin パネルを使用して JSON を検証すると、構文エラーを最小限に抑えることができます。
GCS_BUCKET_NAME JSON 構成の保存に使用されるデフォルトの Cloud Storage バケットをオーバーライドする文字列。ファイル名は config.json で、デフォルトの場所は gcip-iap-bucket-[CLOUD-RUN-SERVICE-NAME]-[PROJECT-NUMBER] です。
ALLOW_ADMIN /admin 構成パネルへのアクセスを許可するかどうかを示すブール値(0 または 1)。デフォルトでは有効(1)です。

変更を有効にする前に、変数を更新した後、Cloud Run インスタンスの新しいリビジョンをデプロイする必要があります。環境変数について詳しくは、Cloud Run のドキュメントをご覧ください。

ドメインのカスタマイズ

デフォルトでは、ログイン時に Cloud Run インスタンスの URL が表示されます。代わりにカスタム ドメインを指定するには:

  1. カスタム ドメインのマッピングの手順に沿って、Cloud Run インスタンスにカスタム ドメインを設定します。

  2. 新しい認証 URL を使用するように IAP を構成します。

    1. Google Cloud コンソールで [IAP] ページに移動します。

      IAP ページに移動

    2. IAP で保護されたリソースを選択します。

    3. サイドパネルで、[Login URL] フィールドの横にある [Edit] アイコンを選択します。

    4. [ホストされている既存のログインページを使用] を選択し、プルダウン メニューからドメインを選択します。

    5. [保存] をクリックします。

複数の IAP リソースに 1 つのログインページを使用する

同じログインページを使用して、複数の IAP リソースを保護できます。これにより、複数の構成の管理に伴う作業を減らすことができます。

ログインページを再利用するには:

  1. この記事の手順に沿って、IAP で保護された最初のリソースの認証ページをデプロイします。

  2. 2 番目のリソースに対して IAP を有効にします。ログインページを指定するよう求められたら、[自分で提供する] を選択し、Cloud Run サービスの URL を [URL] に入力します。

  3. Cloud Run サービスを再デプロイします。

トラブルシューティング

ログインページは、サードパーティ Cookie を無効にしているブラウザや、ストレージ パーティショニングを実装しているブラウザでは動作しません。

この問題を解決するには、次の手順を行います。

  1. ログインページを再デプロイします。最新バージョンのログインページでは、ログインページのドメインを authDomain として使用しています。

  2. ログインページの構成をカスタマイズし、IAP で保護されたアプリケーションのログインページの URL として authDomain が設定されていることを確認します。

    {
      "AIzaSyC5DtmRUR...": {
        "authDomain": "LOGIN_URL",
        ...
      }
    }
    

次のステップ