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

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

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

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

ログインページの制限

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

プロジェクトでメール列挙保護が有効になっている場合は、このドキュメントの手順を続行する前に、メール列挙保護を無効にします

準備

  • 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

Identity Platform プロバイダの承認済みリダイレクト URI の設定

ログインリダイレクト(外部 IdP ログインページへのリダイレクト)を必要とする Identity Platform プロバイダを使用する場合。ホストされているログインページの URL を、承認済みリダイレクト URL としてプロバイダ構成に追加する必要があります。

たとえば、Google プロバイダの場合は、次の操作を行う必要があります。

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

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

    認証情報に進む

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

他の SAML プロバイダや OIDC プロバイダの場合は、承認済みリダイレクト URI または ACS URL として LOGIN_URL/__/auth/handler を追加して同じ操作を行います。

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

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. Google Cloud コンソールで、[認証情報] ページに移動します。

      認証情報に進む

    2. 既存の OAuth 2.0 クライアントを使用するか、新しいクライアントを作成します。Client IDClient secretウェブ クライアント IDウェブ クライアント シークレットに構成します。OAuth 2.0 クライアント用の承認済みリダイレクト URI の 1 つとして LOGIN_URL/__/auth/handler を追加します。LOGIN_URL は、[ログインページを作成する] オプションを選択した後に IAP によって作成されたログイン URL です。これは、Google Cloud コンソールの IAP ページで、IAP で保護されたリソースを選択すると見つかります。

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

管理パネルへのログイン

LOGIN_URL/admin パネルで Cloud Run でホストされているログインページの JSON 構成。管理者パネルにアクセスする方法は次のとおりです。ストレージ管理者(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 に基づいており、多くのプロパティを継承しています。IAP によって作成された LOGIN_URL をデフォルトの authDomain として使用する代わりに、PROJECT_ID.firebaseapp.com を使用できます。

PROJECT_ID.firebaseapp.comauthDomain として使用する場合は、signInFlowpopup に変更して、主要なブラウザでのサードパーティ ストレージ アクセスの問題を回避します(サードパーティのストレージ アクセスをブロックするブラウザで、signInWithRedirect を使用するためのベスト プラクティスをご覧ください)。また、Identity Platform プロバイダの承認済みリダイレクト URI の設定 の手順に沿って、ユーザーがログインする Identity Platform プロバイダの承認済みリダイレクト URI または ACS URL の 1 つとして PROJECT_ID.firebaseapp.com/__/auth/handler を追加します。

次のコードは、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",
        "signInFlow": "popup",
        "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,
        "signInFlow": "popup",
        "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,
        "signInFlow": "popup",
        "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 とストレージ パーティショニング

サードパーティ Cookie を無効にしているブラウザや、ストレージ パーティショニングを実装しているブラウザでは、ログインページまたは管理ページが正しく機能しない場合があります。

ログインページが機能しない

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

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

  2. ログインページの構成をカスタマイズして、authDomain が IAP が作成した LOGIN_URL として設定されるか、signInFlowPROJECT_ID.firebaseapp.compopup として設定されるようにします。

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

    または

    {
      "AIzaSyC5DtmRUR...": {
        "authDomain": "PROJECT_ID.firebaseapp.com",
        "tenants": {
          "tenant-a-id": {
            ...
            "signInFlow": "popup"
            ...
          }
        }
        ...
      }
    }
    

管理ページが機能しない

2024 年 6 月 24 日以降、/admin ページはサードパーティ Cookie のトラッキングを無効にしているブラウザや、ストレージ パーティショニングを実装しているブラウザでは機能しません。一時的な回避策として、サードパーティの Cookie によるトラッキングを有効にする(Firefox)かストレージ パーティショニングを無効にする(chrome)ことでページにアクセスして構成ファイルを変更します。

次のステップ