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

本文說明如何使用 Identity Platform Admin 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----字串。這些金鑰用於在識別資訊提供者上簽署權杖。

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

中繼方實體 ID
SAML 依賴方 (RP/SP) 實體 ID。這通常是應用程式的網址。在 SAML 識別資訊提供者中,這稱為「對象」。
回呼網址

驗證完成時要返回的網址。SAML 供應商通常將此稱為「宣告客戶服務 (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 權杖對象的 ID。
用戶端密鑰
啟用 OIDC 程式碼流程時必須提供的用戶端密鑰。
核發單位
供應商的Issuer。這應該看起來像 https://example.com。Identity Platform 會使用這個網址找出 OIDC 導覽文件 (通常位於 /.well-known/openid-configuration),其中會指定 provider 的 OAuth 端點和公開金鑰。Identity Platform 會根據 OpenID Connect 規格驗證 ID 權杖。如果供應商不遵守探索服務的 OIDC 規格,就無法與 Identity Platform 搭配使用。
回應類型
OAuth 授權流程的供應商回應類型。您可以將 {idToken, code} 其中一個設為 true,但不能同時設為 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 個供應商。這也是每個批次的供應商數量上限。

後續步驟