透過程式管理 SAML 和 OIDC 供應商

本文說明如何使用 Identity Platform 管理員 SDK,以程式輔助方式管理安全宣告標記語言 (SAML) 2.0 和 OpenID Connect (OIDC) 供應商設定。

您可以使用 Admin SDK 自動設定供應商、執行基本 CRUD 作業、輪替憑證等。如果您有大量供應商,且使用 Google Cloud 控制台手動管理這些供應商會很麻煩,這項功能就很實用。

事前準備

使用 SAML 提供者

建立 SAML 提供者設定

建立 SAML 供應器設定時,您必須提供下列參數。如要進一步瞭解如何取得部分值,您可能需要參閱身分識別提供者的說明文件。

顯示名稱
設定的使用者友善顯示名稱。這個名稱也是 Google Cloud 主控台中的供應商標籤。
已啟用
目前供應器設定是否已啟用或停用。使用者無法透過已停用的登入資訊提供者登入。
供應商 ID
供應者的專屬 ID,開頭為 saml.
識別資訊提供者實體 ID
提供者的實體 ID。
單一登入 (SSO) 網址
提供者的 SAML 單一登入 (SSO) 網址。網址必須有效。
X.509 憑證

SAML 供應器 X.509 憑證清單,包括 -----BEGIN CERTIFICATE----------END CERTIFICATE---- 字串。這些金鑰會用於在 ID 提供者上簽署權杖。

Identity Platform 收到 SAML 回應後,會使用記錄中的憑證驗證簽名。如果驗證失敗,系統會拒絕回應。您必須在輪替金鑰時更新這些憑證。建議您上傳多個憑證,以免在輪替期間發生服務中斷。

轉送方實體 ID
SAML 信賴方 (RP/SP) 實體 ID。這通常是應用程式的網址。在 SAML 身分識別資訊提供者中,這會稱為對象。
回呼網址

驗證完成後要返回的網址。SAML 供應商通常稱這為「Assertion Consumer Service (ACS)」網址。您必須向 SAML 供應器註冊這個網址。 其格式應類似 https://PROJECT-ID.firebaseapp.com/__/auth/handler,類似於在 Google Cloud 控制台中顯示的網址。如需更多資訊,請參閱「使用 SAML 讓使用者登入」。

使用預設回呼網址可簡化 SAML 回應的驗證程序。不過,您也可以選擇顯示自訂網域。在這種情況下,請確認專案的 Identity Platform 回呼網址已正確設定 SAML 識別資訊提供者。通常會像 https://AUTH-DOMAIN/__/auth/handler 這樣。

以下範例說明如何建立 SAML 提供者設定:

Node.js

const newConfig = {
  displayName: 'SAML provider name',
  enabled: true,
  providerId: 'saml.myProvider',
  idpEntityId: 'IDP_ENTITY_ID',
  ssoURL: 'https://example.com/saml/sso/1234/'
  x509Certificates: [
    '-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----',
    '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
  ],
  rpEntityId: 'RP_ENTITY_ID',
  // Using the default callback URL.
  callbackURL: 'https://project-id.firebaseapp.com/__/auth/handler',
};
admin.auth().createProviderConfig(newConfig).then(() => {
  // Successful creation.
}).catch((error) => {
  // Handle error.
});

Go

newConfig := (&auth.SAMLProviderConfigToCreate{}).
	DisplayName("SAML provider name").
	Enabled(true).
	ID("saml.myProvider").
	IDPEntityID("IDP_ENTITY_ID").
	SSOURL("https://example.com/saml/sso/1234/").
	X509Certificates([]string{
		"-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----",
		"-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----",
	}).
	RPEntityID("RP_ENTITY_ID").
	CallbackURL("https://project-id.firebaseapp.com/__/auth/handler")
saml, err := client.CreateSAMLProviderConfig(ctx, newConfig)
if err != nil {
	log.Fatalf("error creating SAML provider: %v\n", err)
}

log.Printf("Created new SAML provider: %s", saml.ID)

Python

saml = auth.create_saml_provider_config(
    display_name='SAML provider name',
    enabled=True,
    provider_id='saml.myProvider',
    idp_entity_id='IDP_ENTITY_ID',
    sso_url='https://example.com/saml/sso/1234/',
    x509_certificates=[
        '-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----',
        '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
    ],
    rp_entity_id='P_ENTITY_ID',
    callback_url='https://project-id.firebaseapp.com/__/auth/handler')

print('Created new SAML provider:', saml.provider_id)

Java

SamlProviderConfig.CreateRequest request = new SamlProviderConfig.CreateRequest()
    .setDisplayName("SAML provider name")
    .setEnabled(true)
    .setProviderId("saml.myProvider")
    .setIdpEntityId("IDP_ENTITY_ID")
    .setSsoUrl("https://example.com/saml/sso/1234/")
    .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----")
    .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----")
    .setRpEntityId("RP_ENTITY_ID")
    .setCallbackUrl("https://project-id.firebaseapp.com/__/auth/handler");
SamlProviderConfig saml = FirebaseAuth.getInstance().createSamlProviderConfig(request);
System.out.println("Created new SAML provider: " + saml.getProviderId());

完成後,方法會傳回新建立設定的 SAMLAuthProviderConfig 物件。

更新 SAML 供應器設定

以下範例說明如何修改 SAML 提供者設定。您可以更新任何欄位,但提供者 ID 除外。

Node.js

const updatedConfig = {
  x509Certificates: [
    '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
    '-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----',
  ],
};
admin.auth().updateProviderConfig('saml.myProvider', updatedConfig).then(() => {
  // Successful update.
}).catch((error) => {
  // Handle error.
});

Go

updatedConfig := (&auth.SAMLProviderConfigToUpdate{}).
	X509Certificates([]string{
		"-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----",
		"-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----",
	})
saml, err := client.UpdateSAMLProviderConfig(ctx, "saml.myProvider", updatedConfig)
if err != nil {
	log.Fatalf("error updating SAML provider: %v\n", err)
}

log.Printf("Updated SAML provider: %s", saml.ID)

Python

saml = auth.update_saml_provider_config(
    'saml.myProvider',
    x509_certificates=[
        '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
        '-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----',
    ])

print('Updated SAML provider:', saml.provider_id)

Java

SamlProviderConfig.UpdateRequest request =
    new SamlProviderConfig.UpdateRequest("saml.myProvider")
      .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----")
      .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----");
SamlProviderConfig saml = FirebaseAuth.getInstance().updateSamlProviderConfig(request);
System.out.println("Updated SAML provider: " + saml.getProviderId());

完成後,方法會針對更新的設定傳回 SAMLAuthProviderConfig 物件。

取得 SAML 供應器設定

識別 SAML 設定的主要方法是使用供應商 ID。以下範例說明如何取得 SAML 供應器設定:

Node.js

admin.auth().getProviderConfig('saml.myProvider').then((config) => {
  // Get display name and whether it is enabled.
  console.log(config.displayName, config.enabled);
}).catch((error) => {
  // Handle error. Common error is that config is not found.
});

Go

saml, err := client.SAMLProviderConfig(ctx, "saml.myProvider")
if err != nil {
	log.Fatalf("error retrieving SAML provider: %v\n", err)
}

log.Printf("%s %t", saml.DisplayName, saml.Enabled)

Python

saml = auth.get_saml_provider_config('saml.myProvider')
print(saml.display_name, saml.enabled)

Java

SamlProviderConfig saml = FirebaseAuth.getInstance().getSamlProviderConfig("saml.myProvider");
System.out.println(saml.getDisplayName() + ": " + saml.isEnabled());

如果有提供者使用指定 ID,這個方法會傳回 SAMLAuthProviderConfig 物件。

刪除 SAML 供應器設定

以下範例說明如何刪除 SAML 供應器設定:

Node.js

admin.auth().deleteProviderConfig('saml.myProvider').then(() => {
  // Successful deletion.
}).catch((error) => {
  // Handle error.
});

Go

if err := client.DeleteSAMLProviderConfig(ctx, "saml.myProvider"); err != nil {
	log.Fatalf("error deleting SAML provider: %v\n", err)
}

Python

auth.delete_saml_provider_config('saml.myProvider')

Java

FirebaseAuth.getInstance().deleteSamlProviderConfig("saml.myProvider");

列出 SAML 供應器設定

以下範例說明如何列出現有的 SAML 提供者設定:

Node.js

// Returns 10 SAML provider configs starting from the specified nextPageToken offset.
admin.auth().listProviderConfigs({type: 'saml', maxResults: 10, pageToken: 'nextPageToken'}).then((results) => {
  results.providerConfigs.forEach((config) => {
    console.log(config.providerId);
  });
  // To list the next 10:
  // return admin.auth().listProviderConfigs(
  //     {type: 'saml', maxResults: 10, pageToken: results.pageToken});
}).catch((error) => {
  // Handle error.
});

Go

iter := client.SAMLProviderConfigs(ctx, "nextPageToken")
for {
	saml, err := iter.Next()
	if err == iterator.Done {
		break
	}
	if err != nil {
		log.Fatalf("error retrieving SAML providers: %v\n", err)
	}

	log.Printf("%s\n", saml.ID)
}

Python

for saml in auth.list_saml_provider_configs('nextPageToken').iterate_all():
    print(saml.provider_id)

Java

ListProviderConfigsPage<SamlProviderConfig> page = FirebaseAuth.getInstance()
    .listSamlProviderConfigs("nextPageToken");
for (SamlProviderConfig config : page.iterateAll()) {
  System.out.println(config.getProviderId());
}

每個結果批次都包含提供者設定清單,以及用於擷取下一個批次的下一頁權杖。列出所有提供者後,系統不會傳回權杖。

根據預設,每個批次會傳回 100 個供應者。這也是每批提供者的數量上限。

使用 OIDC 供應器

建立 OIDC 提供者設定

建立 OIDC 供應商設定時,您必須提供下列參數。如要進一步瞭解如何取得部分值,您可能需要參閱身分提供者的說明文件。

顯示名稱
設定的使用者友善顯示名稱。這個名稱也是 Google Cloud 主控台中的供應商標籤。
已啟用
目前供應器設定是否已啟用或停用。使用者無法透過已停用的登入資訊提供者登入。
供應商 ID
供應者的專屬 ID,開頭為 oidc.
用戶端 ID
用於確認 OIDC 提供者 ID 權杖的目標對象。
用戶端密鑰
啟用 OIDC 碼流程所需的用戶端密鑰。
核發單位
供應商的 Issuer。應該會像 https://example.com 這樣。Identity Platform 會使用這個網址找出 OIDC 探索文件 (通常位於 /.well-known/openid-configuration),其中會指定提供者的 OAuth 端點和公開金鑰。Identity Platform 會根據 OpenID Connect 規格驗證 ID 權杖。如果您的供應商不遵循 OIDC 探索服務規格,就無法與 Identity Platform 搭配運作。
回應類型
提供者針對 OAuth 授權流程的回應類型。您可以將 {idToken, code} 其中一個設為 true,但不能同時設為兩個。如果已啟用程式碼流程,您必須提供用戶端密鑰。

以下範例說明如何建立使用隱含授權流程的 OIDC 提供者設定:

Node.js

const newConfig = {
  displayName: 'OIDC provider name',
  enabled: true,
  clientId: 'CLIENT_ID2',
  issuer: 'https://oidc.com/CLIENT_ID2',
  providerId: 'oidc.provider2',
  responseType: {
    idToken: true,
    code: false,
  },
};
admin.auth().createProviderConfig(newConfig).then(() => {
  // Successful creation.
}).catch((error) => {
  // Handle error.
});

Go

newConfig := (&auth.OIDCProviderConfigToCreate{}).
	DisplayName("OIDC provider name").
	Enabled(true).
	ID("oidc.myProvider").
	ClientID("CLIENT_ID2").
	Issuer("https://oidc.com/CLIENT_ID2")
oidc, err := client.CreateOIDCProviderConfig(ctx, newConfig)
if err != nil {
	log.Fatalf("error creating OIDC provider: %v\n", err)
}

log.Printf("Created new OIDC provider: %s", oidc.ID)

Python

oidc = auth.create_oidc_provider_config(
    display_name='OIDC provider name',
    enabled=True,
    provider_id='oidc.myProvider',
    client_id='CLIENT_ID2',
    issuer='https://oidc.com/CLIENT_ID2')

print('Created new OIDC provider:', oidc.provider_id)

Java

OidcProviderConfig.CreateRequest request = new OidcProviderConfig.CreateRequest()
    .setDisplayName("OIDC provider name")
    .setEnabled(true)
    .setProviderId("oidc.myProvider")
    .setClientId("CLIENT_ID2")
    .setIssuer("https://oidc.com/CLIENT_ID2");
OidcProviderConfig oidc = FirebaseAuth.getInstance().createOidcProviderConfig(request);
System.out.println("Created new OIDC provider: " + oidc.getProviderId());

完成後,方法會傳回新建設定的 OIDCAuthProviderConfig 物件。

更新 OIDC 供應器設定

以下範例說明如何修改 OIDC 提供者設定。您可以更新任何欄位,但提供者 ID 除外。

Node.js

const updatedConfig = {
  displayName: 'OIDC provider name',
  enabled: true,
  clientId: 'CLIENT_ID',
  clientSecret: 'CLIENT_SECRET'
  issuer: 'https://oidc.com/',
  responseType: {
    code: true,
    idToken: false,
  },
};
admin.auth().updateProviderConfig('oidc.myProvider', updatedConfig).then(() => {
  // Successful update.
}).catch((error) => {
  // Handle error.
});

Go

updatedConfig := (&auth.OIDCProviderConfigToUpdate{}).
	DisplayName("OIDC provider name").
	Enabled(true).
	ClientID("CLIENT_ID").
	Issuer("https://oidc.com")
oidc, err := client.UpdateOIDCProviderConfig(ctx, "oidc.myProvider", updatedConfig)
if err != nil {
	log.Fatalf("error updating OIDC provider: %v\n", err)
}

log.Printf("Updated OIDC provider: %s", oidc.ID)

Python

oidc = auth.update_oidc_provider_config(
    'oidc.myProvider',
    client_id='CLIENT_ID',
    issuer='https://oidc.com')

print('Updated OIDC provider:', oidc.provider_id)

Java

OidcProviderConfig.UpdateRequest request =
    new OidcProviderConfig.UpdateRequest("oidc.myProvider")
        .setDisplayName("OIDC provider name")
        .setEnabled(true)
        .setClientId("CLIENT_ID")
        .setIssuer("https://oidc.com");
OidcProviderConfig oidc = FirebaseAuth.getInstance().updateOidcProviderConfig(request);
System.out.println("Updated OIDC provider: " + oidc.getProviderId());

完成後,方法會針對更新的設定傳回 OIDCAuthProviderConfig 物件。

取得 OIDC 提供者設定

識別 OIDC 設定的主要方法是使用其提供者 ID。以下範例說明如何取得 OIDC 供應器設定:

Node.js

admin.auth().getProviderConfig('oidc.myProvider').then((config) => {
  // Get display name and whether it is enabled.
  console.log(config.displayName, config.enabled);
}).catch((error) => {
  // Handle error. Common error is that config is not found.
});

Go

oidc, err := client.OIDCProviderConfig(ctx, "oidc.myProvider")
if err != nil {
	log.Fatalf("error retrieving OIDC provider: %v\n", err)
}

log.Printf("%s %t", oidc.DisplayName, oidc.Enabled)

Python

oidc = auth.get_oidc_provider_config('oidc.myProvider')

print(oidc.display_name, oidc.enabled)

Java

OidcProviderConfig oidc = FirebaseAuth.getInstance().getOidcProviderConfig("oidc.myProvider");
System.out.println(oidc.getDisplayName() + ": " + oidc.isEnabled());

如果有提供者使用指定 ID,這個方法會傳回 OIDCAuthProviderConfig 物件。

刪除 OIDC 供應商設定

以下範例說明如何刪除 OIDC 提供者設定:

Node.js

admin.auth().deleteProviderConfig('oidc.myProvider').then(() => {
  // Successful deletion.
}).catch((error) => {
  // Handle error.
});

Go

if err := client.DeleteOIDCProviderConfig(ctx, "oidc.myProvider"); err != nil {
	log.Fatalf("error deleting OIDC provider: %v\n", err)
}

Python

auth.delete_oidc_provider_config('oidc.myProvider')

Java

FirebaseAuth.getInstance().deleteOidcProviderConfig("oidc.myProvider");

列出 OIDC 供應器設定

以下範例說明如何列出現有的 OIDC 提供者設定:

Node.js

// Returns 10 OIDC provider configs starting from the specified nextPageToken offset.
admin.auth().listProviderConfigs({type: 'oidc', maxResults: 10, pageToken: 'nextPageToken'}).then((results) => {
  results.providerConfigs.forEach((config) => {
    console.log(config.providerId);
  });
  // To list the next 10:
  // return admin.auth().listProviderConfigs(
  //     {type: 'oidc', maxResults: 10, pageToken: results.pageToken});
}).catch((error) => {
  // Handle error.
});

Go

iter := client.OIDCProviderConfigs(ctx, "nextPageToken")
for {
	oidc, err := iter.Next()
	if err == iterator.Done {
		break
	}
	if err != nil {
		log.Fatalf("error retrieving OIDC providers: %v\n", err)
	}

	log.Printf("%s\n", oidc.ID)
}

Python

for oidc in auth.list_oidc_provider_configs('nextPageToken').iterate_all():
    print(oidc.provider_id)

Java

ListProviderConfigsPage<OidcProviderConfig> page = FirebaseAuth.getInstance()
    .listOidcProviderConfigs("nextPageToken");
for (OidcProviderConfig oidc : page.iterateAll()) {
  System.out.println(oidc.getProviderId());
}

每個結果批次都包含提供者設定清單,以及用於擷取下一個批次的下一頁權杖。列出所有提供者後,系統不會傳回權杖。

根據預設,每個批次會傳回 100 個供應者。這也是每批提供者的數量上限。

後續步驟