ניהול ספקי SAML ו-OIDC באופן פרוגרמטי

במסמך הזה מוסבר איך להשתמש ב-Admin SDK של Identity Platform כדי לנהל באופן פרוגרמטי את ההגדרות של ספקי Security Assertion Markup Language ‏ (SAML) 2.0 ו-OpenID Connect ‏ (OIDC).

באמצעות SDK לאדמינים, אתם יכולים להגדיר ספקים באופן אוטומטי, לבצע פעולות CRUD בסיסיות, להחליף אישורים ועוד. האפשרות הזו שימושית אם יש לכם מספר גדול של ספקים שיהיה מסורבל לנהל באופן ידני באמצעות מסוף Google Cloud .

לפני שמתחילים

עבודה עם ספקי SAML

יצירת הגדרה של ספק SAML

כשיוצרים הגדרות של ספק SAML, צריך לספק את הפרמטרים הבאים: יכול להיות שתצטרכו לעיין במסמכי התיעוד של ספק הזהויות כדי לקבל פרטים על האופן שבו אפשר להשיג חלק מהערכים.

השם המוצג
שם תצוגה ידידותי למשתמש בשביל ההגדרה. השם הזה הוא גם תווית הספק במסוף Google Cloud .
מופעל
האם הגדרת הספק הנוכחית מופעלת או מושבתת. המשתמשים לא יכולים להיכנס באמצעות ספקים מושבתים.
מזהה הספק
המזהה הייחודי של הספק, שמתחיל ב-saml..
מזהה ישות של ספק הזהויות
מזהה הישות של הספק.
כתובת אתר לכניסה יחידה
כתובת ה-URL של ספק ה-SAML SSO. כתובת ה-URL חייבת להיות תקינה.
אישורי X.509

רשימה של אישורי X.509 של ספק SAML, כולל המחרוזות -----BEGIN CERTIFICATE----- ו------END CERTIFICATE----. הם משמשים לחתימה על טוקנים בספק הזהויות.

כש-Identity Platform מקבל תגובת SAML, הוא מאמת את החתימה שלה באמצעות אישור שרשום במערכת. אם האימות ייכשל, התשובה תידחה. תצטרכו לעדכן את האישורים האלה כשמבצעים רוטציה של המפתחות. כדאי להעלות כמה אישורים כדי למנוע הפסקות זמניות במהלך הרוטציה.

מזהה ישות של צד מעביר
מזהה הישות של הצד המסתמך (RP/SP) ב-SAML. בדרך כלל זו כתובת ה-URL של האפליקציה. בספק הזהויות של SAML, הנתון הזה נקרא 'קהל'.
כתובת אתר להתקשרות חוזרת

כתובת ה-URL שאליה המשתמש יופנה בסיום האימות. ספקי SAML בדרך כלל מתייחסים לזה ככתובת ה-URL של Assertion Consumer Service‏ (ACS). צריך לרשום את כתובת ה-URL הזו אצל ספק ה-SAML. היא אמורה להיראות כך: https://PROJECT-ID.firebaseapp.com/__/auth/handler, בדומה לכתובות ה-URL שמוצגות במסוף Google Cloud . מידע נוסף זמין במאמר בנושא כניסה של משתמשים באמצעות SAML.

שימוש בכתובת ה-URL של הקריאה החוזרת שמוגדרת כברירת מחדל יפחית את המורכבות של אימות תגובות SAML. אבל אפשר גם לבחור להציג דומיין מותאם אישית. במקרה כזה, צריך לוודא שכתובת ה-URL של הקריאה החוזרת של 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.
});

המשך

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. אפשר לעדכן כל שדה, חוץ ממזהה הספק.

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.
});

המשך

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 היא באמצעות מזהה הספק שלה. בדוגמה הבאה מוצג איך מקבלים הגדרה של ספק 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.
});

המשך

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());

אם קיים ספק עם המזהה שצוין, השיטה מחזירה אובייקט SAMLAuthProviderConfig.

מחיקת הגדרה של ספק SAML

בדוגמה הבאה אפשר לראות איך מוחקים הגדרה של ספק SAML:

Node.js

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

המשך

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.
});

המשך

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 .
מופעל
האם הגדרת הספק הנוכחית מופעלת או מושבתת. המשתמשים לא יכולים להיכנס באמצעות ספקים מושבתים.
מזהה הספק
המזהה הייחודי של הספק, שמתחיל ב-oidc..
מזהה לקוח
המזהה שמשמש לאימות הקהל של אסימון מזהה של ספק OIDC.
סוד לקוח
סוד הלקוח שנדרש כדי להפעיל את תהליך קוד ה-OIDC.
מנפיק
הספק Issuer. הוא אמור להיראות כך: https://example.com מערכת Identity Platform משתמשת בכתובת ה-URL הזו כדי לאתר את מסמך Discovery של OIDC (בדרך כלל נמצא בכתובת /.well-known/openid-configuration), שמצוינות בו נקודות הקצה של OAuth והמפתחות הציבוריים של הספק. פלטפורמת Identity Platform מאמתת אסימונים מזהים בהתאם למפרט OpenID Connect. אם הספק לא עומד במפרט 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.
});

המשך

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. אפשר לעדכן כל שדה, חוץ ממזהה הספק.

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.
});

המשך

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 היא באמצעות מזהה הספק שלה. בדוגמה הבאה מוצג איך מקבלים הגדרה של ספק 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.
});

המשך

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());

אם קיים ספק עם המזהה שצוין, השיטה מחזירה אובייקט OIDCAuthProviderConfig.

מחיקת הגדרה של ספק OIDC

בדוגמה הבאה אפשר לראות איך מוחקים הגדרה של ספק OIDC:

Node.js

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

המשך

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.
});

המשך

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 ספקים. זה גם המספר המקסימלי של ספקים לכל קבוצה.

המאמרים הבאים