Configure GCP Workforce Pool Identity Providers

The gcp:iam/workforcePoolProvider:WorkforcePoolProvider resource, part of the Pulumi GCP provider, defines external identity provider configurations within workforce pools, enabling SAML or OIDC authentication for human users accessing Google Cloud. This guide focuses on three capabilities: SAML and OIDC protocol configuration, attribute mapping from external credentials, and Azure AD group enrichment.

Workforce pool providers belong to WorkforcePool resources and require OAuth client credentials from external identity systems. Workforce identity federation must be enabled for your organization by the Google Cloud account team. The examples are intentionally small. Combine them with your own workforce pools and IAM policies.

Configure SAML authentication with minimal settings

Organizations federating workforce identities often start with SAML providers, connecting their existing identity systems to Google Cloud without managing separate credentials.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const pool = new gcp.iam.WorkforcePool("pool", {
    workforcePoolId: "example-pool",
    parent: "organizations/123456789",
    location: "global",
});
const example = new gcp.iam.WorkforcePoolProvider("example", {
    workforcePoolId: pool.workforcePoolId,
    location: pool.location,
    providerId: "example-prvdr",
    attributeMapping: {
        "google.subject": "assertion.sub",
    },
    saml: {
        idpMetadataXml: "<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://test.com\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>",
    },
});
import pulumi
import pulumi_gcp as gcp

pool = gcp.iam.WorkforcePool("pool",
    workforce_pool_id="example-pool",
    parent="organizations/123456789",
    location="global")
example = gcp.iam.WorkforcePoolProvider("example",
    workforce_pool_id=pool.workforce_pool_id,
    location=pool.location,
    provider_id="example-prvdr",
    attribute_mapping={
        "google.subject": "assertion.sub",
    },
    saml={
        "idp_metadata_xml": "<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://test.com\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		pool, err := iam.NewWorkforcePool(ctx, "pool", &iam.WorkforcePoolArgs{
			WorkforcePoolId: pulumi.String("example-pool"),
			Parent:          pulumi.String("organizations/123456789"),
			Location:        pulumi.String("global"),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewWorkforcePoolProvider(ctx, "example", &iam.WorkforcePoolProviderArgs{
			WorkforcePoolId: pool.WorkforcePoolId,
			Location:        pool.Location,
			ProviderId:      pulumi.String("example-prvdr"),
			AttributeMapping: pulumi.StringMap{
				"google.subject": pulumi.String("assertion.sub"),
			},
			Saml: &iam.WorkforcePoolProviderSamlArgs{
				IdpMetadataXml: pulumi.String("<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://test.com\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var pool = new Gcp.Iam.WorkforcePool("pool", new()
    {
        WorkforcePoolId = "example-pool",
        Parent = "organizations/123456789",
        Location = "global",
    });

    var example = new Gcp.Iam.WorkforcePoolProvider("example", new()
    {
        WorkforcePoolId = pool.WorkforcePoolId,
        Location = pool.Location,
        ProviderId = "example-prvdr",
        AttributeMapping = 
        {
            { "google.subject", "assertion.sub" },
        },
        Saml = new Gcp.Iam.Inputs.WorkforcePoolProviderSamlArgs
        {
            IdpMetadataXml = "<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://test.com\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkforcePool;
import com.pulumi.gcp.iam.WorkforcePoolArgs;
import com.pulumi.gcp.iam.WorkforcePoolProvider;
import com.pulumi.gcp.iam.WorkforcePoolProviderArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderSamlArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var pool = new WorkforcePool("pool", WorkforcePoolArgs.builder()
            .workforcePoolId("example-pool")
            .parent("organizations/123456789")
            .location("global")
            .build());

        var example = new WorkforcePoolProvider("example", WorkforcePoolProviderArgs.builder()
            .workforcePoolId(pool.workforcePoolId())
            .location(pool.location())
            .providerId("example-prvdr")
            .attributeMapping(Map.of("google.subject", "assertion.sub"))
            .saml(WorkforcePoolProviderSamlArgs.builder()
                .idpMetadataXml("<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://test.com\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>")
                .build())
            .build());

    }
}
resources:
  pool:
    type: gcp:iam:WorkforcePool
    properties:
      workforcePoolId: example-pool
      parent: organizations/123456789
      location: global
  example:
    type: gcp:iam:WorkforcePoolProvider
    properties:
      workforcePoolId: ${pool.workforcePoolId}
      location: ${pool.location}
      providerId: example-prvdr
      attributeMapping:
        google.subject: assertion.sub
      saml:
        idpMetadataXml: <?xml version="1.0"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://test.com"><md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://test.com/sso"/></md:IDPSSODescriptor></md:EntityDescriptor>

The saml block contains the identity provider’s metadata XML, which includes signing certificates and SSO endpoints. The attributeMapping property defines how claims from the SAML assertion map to Google Cloud attributes. The google.subject mapping is required and identifies the authenticated principal in IAM bindings and Cloud Logging.

Configure OIDC authentication with web SSO

OIDC providers offer an alternative to SAML for organizations using modern identity platforms that support OpenID Connect.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const pool = new gcp.iam.WorkforcePool("pool", {
    workforcePoolId: "example-pool",
    parent: "organizations/123456789",
    location: "global",
});
const example = new gcp.iam.WorkforcePoolProvider("example", {
    workforcePoolId: pool.workforcePoolId,
    location: pool.location,
    providerId: "example-prvdr",
    attributeMapping: {
        "google.subject": "assertion.sub",
    },
    oidc: {
        issuerUri: "https://accounts.thirdparty.com",
        clientId: "client-id",
        clientSecret: {
            value: {
                plainText: "client-secret",
            },
        },
        webSsoConfig: {
            responseType: "CODE",
            assertionClaimsBehavior: "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS",
        },
    },
});
import pulumi
import pulumi_gcp as gcp

pool = gcp.iam.WorkforcePool("pool",
    workforce_pool_id="example-pool",
    parent="organizations/123456789",
    location="global")
example = gcp.iam.WorkforcePoolProvider("example",
    workforce_pool_id=pool.workforce_pool_id,
    location=pool.location,
    provider_id="example-prvdr",
    attribute_mapping={
        "google.subject": "assertion.sub",
    },
    oidc={
        "issuer_uri": "https://accounts.thirdparty.com",
        "client_id": "client-id",
        "client_secret": {
            "value": {
                "plain_text": "client-secret",
            },
        },
        "web_sso_config": {
            "response_type": "CODE",
            "assertion_claims_behavior": "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS",
        },
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		pool, err := iam.NewWorkforcePool(ctx, "pool", &iam.WorkforcePoolArgs{
			WorkforcePoolId: pulumi.String("example-pool"),
			Parent:          pulumi.String("organizations/123456789"),
			Location:        pulumi.String("global"),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewWorkforcePoolProvider(ctx, "example", &iam.WorkforcePoolProviderArgs{
			WorkforcePoolId: pool.WorkforcePoolId,
			Location:        pool.Location,
			ProviderId:      pulumi.String("example-prvdr"),
			AttributeMapping: pulumi.StringMap{
				"google.subject": pulumi.String("assertion.sub"),
			},
			Oidc: &iam.WorkforcePoolProviderOidcArgs{
				IssuerUri: pulumi.String("https://accounts.thirdparty.com"),
				ClientId:  pulumi.String("client-id"),
				ClientSecret: &iam.WorkforcePoolProviderOidcClientSecretArgs{
					Value: &iam.WorkforcePoolProviderOidcClientSecretValueArgs{
						PlainText: pulumi.String("client-secret"),
					},
				},
				WebSsoConfig: &iam.WorkforcePoolProviderOidcWebSsoConfigArgs{
					ResponseType:            pulumi.String("CODE"),
					AssertionClaimsBehavior: pulumi.String("MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var pool = new Gcp.Iam.WorkforcePool("pool", new()
    {
        WorkforcePoolId = "example-pool",
        Parent = "organizations/123456789",
        Location = "global",
    });

    var example = new Gcp.Iam.WorkforcePoolProvider("example", new()
    {
        WorkforcePoolId = pool.WorkforcePoolId,
        Location = pool.Location,
        ProviderId = "example-prvdr",
        AttributeMapping = 
        {
            { "google.subject", "assertion.sub" },
        },
        Oidc = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcArgs
        {
            IssuerUri = "https://accounts.thirdparty.com",
            ClientId = "client-id",
            ClientSecret = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcClientSecretArgs
            {
                Value = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcClientSecretValueArgs
                {
                    PlainText = "client-secret",
                },
            },
            WebSsoConfig = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcWebSsoConfigArgs
            {
                ResponseType = "CODE",
                AssertionClaimsBehavior = "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkforcePool;
import com.pulumi.gcp.iam.WorkforcePoolArgs;
import com.pulumi.gcp.iam.WorkforcePoolProvider;
import com.pulumi.gcp.iam.WorkforcePoolProviderArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcClientSecretArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcClientSecretValueArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcWebSsoConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var pool = new WorkforcePool("pool", WorkforcePoolArgs.builder()
            .workforcePoolId("example-pool")
            .parent("organizations/123456789")
            .location("global")
            .build());

        var example = new WorkforcePoolProvider("example", WorkforcePoolProviderArgs.builder()
            .workforcePoolId(pool.workforcePoolId())
            .location(pool.location())
            .providerId("example-prvdr")
            .attributeMapping(Map.of("google.subject", "assertion.sub"))
            .oidc(WorkforcePoolProviderOidcArgs.builder()
                .issuerUri("https://accounts.thirdparty.com")
                .clientId("client-id")
                .clientSecret(WorkforcePoolProviderOidcClientSecretArgs.builder()
                    .value(WorkforcePoolProviderOidcClientSecretValueArgs.builder()
                        .plainText("client-secret")
                        .build())
                    .build())
                .webSsoConfig(WorkforcePoolProviderOidcWebSsoConfigArgs.builder()
                    .responseType("CODE")
                    .assertionClaimsBehavior("MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS")
                    .build())
                .build())
            .build());

    }
}
resources:
  pool:
    type: gcp:iam:WorkforcePool
    properties:
      workforcePoolId: example-pool
      parent: organizations/123456789
      location: global
  example:
    type: gcp:iam:WorkforcePoolProvider
    properties:
      workforcePoolId: ${pool.workforcePoolId}
      location: ${pool.location}
      providerId: example-prvdr
      attributeMapping:
        google.subject: assertion.sub
      oidc:
        issuerUri: https://accounts.thirdparty.com
        clientId: client-id
        clientSecret:
          value:
            plainText: client-secret
        webSsoConfig:
          responseType: CODE
          assertionClaimsBehavior: MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS

The oidc block specifies the issuer URI, OAuth client credentials, and web SSO configuration. The webSsoConfig property controls the OAuth flow: responseType sets the authorization code flow, and assertionClaimsBehavior determines how claims from the ID token and UserInfo endpoint are merged. The clientSecret must be provided securely.

Enrich SAML identities with Azure AD group data

When authorization decisions depend on group membership, you can configure an OAuth client to fetch additional attributes from the identity provider after SAML authentication completes.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const pool = new gcp.iam.WorkforcePool("pool", {
    workforcePoolId: "example-pool",
    parent: "organizations/123456789",
    location: "global",
});
const example = new gcp.iam.WorkforcePoolProvider("example", {
    workforcePoolId: pool.workforcePoolId,
    location: pool.location,
    providerId: "example-prvdr",
    attributeMapping: {
        "google.subject": "assertion.sub",
    },
    saml: {
        idpMetadataXml: "<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://sts.windows.net/826602fe-2101-470c-9d71-ee1343668989\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>",
    },
    extraAttributesOauth2Client: {
        issuerUri: "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
        clientId: "client-id",
        clientSecret: {
            value: {
                plainText: "client-secret",
            },
        },
        attributesType: "AZURE_AD_GROUPS_ID",
        queryParameters: {
            filter: "mail:gcp",
        },
    },
    displayName: "Display name",
    description: "A sample SAML workforce pool provider.",
    disabled: false,
    attributeCondition: "true",
});
import pulumi
import pulumi_gcp as gcp

pool = gcp.iam.WorkforcePool("pool",
    workforce_pool_id="example-pool",
    parent="organizations/123456789",
    location="global")
example = gcp.iam.WorkforcePoolProvider("example",
    workforce_pool_id=pool.workforce_pool_id,
    location=pool.location,
    provider_id="example-prvdr",
    attribute_mapping={
        "google.subject": "assertion.sub",
    },
    saml={
        "idp_metadata_xml": "<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://sts.windows.net/826602fe-2101-470c-9d71-ee1343668989\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>",
    },
    extra_attributes_oauth2_client={
        "issuer_uri": "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
        "client_id": "client-id",
        "client_secret": {
            "value": {
                "plain_text": "client-secret",
            },
        },
        "attributes_type": "AZURE_AD_GROUPS_ID",
        "query_parameters": {
            "filter": "mail:gcp",
        },
    },
    display_name="Display name",
    description="A sample SAML workforce pool provider.",
    disabled=False,
    attribute_condition="true")
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		pool, err := iam.NewWorkforcePool(ctx, "pool", &iam.WorkforcePoolArgs{
			WorkforcePoolId: pulumi.String("example-pool"),
			Parent:          pulumi.String("organizations/123456789"),
			Location:        pulumi.String("global"),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewWorkforcePoolProvider(ctx, "example", &iam.WorkforcePoolProviderArgs{
			WorkforcePoolId: pool.WorkforcePoolId,
			Location:        pool.Location,
			ProviderId:      pulumi.String("example-prvdr"),
			AttributeMapping: pulumi.StringMap{
				"google.subject": pulumi.String("assertion.sub"),
			},
			Saml: &iam.WorkforcePoolProviderSamlArgs{
				IdpMetadataXml: pulumi.String("<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://sts.windows.net/826602fe-2101-470c-9d71-ee1343668989\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>"),
			},
			ExtraAttributesOauth2Client: &iam.WorkforcePoolProviderExtraAttributesOauth2ClientArgs{
				IssuerUri: pulumi.String("https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0"),
				ClientId:  pulumi.String("client-id"),
				ClientSecret: &iam.WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretArgs{
					Value: &iam.WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretValueArgs{
						PlainText: pulumi.String("client-secret"),
					},
				},
				AttributesType: pulumi.String("AZURE_AD_GROUPS_ID"),
				QueryParameters: &iam.WorkforcePoolProviderExtraAttributesOauth2ClientQueryParametersArgs{
					Filter: pulumi.String("mail:gcp"),
				},
			},
			DisplayName:        pulumi.String("Display name"),
			Description:        pulumi.String("A sample SAML workforce pool provider."),
			Disabled:           pulumi.Bool(false),
			AttributeCondition: pulumi.String("true"),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var pool = new Gcp.Iam.WorkforcePool("pool", new()
    {
        WorkforcePoolId = "example-pool",
        Parent = "organizations/123456789",
        Location = "global",
    });

    var example = new Gcp.Iam.WorkforcePoolProvider("example", new()
    {
        WorkforcePoolId = pool.WorkforcePoolId,
        Location = pool.Location,
        ProviderId = "example-prvdr",
        AttributeMapping = 
        {
            { "google.subject", "assertion.sub" },
        },
        Saml = new Gcp.Iam.Inputs.WorkforcePoolProviderSamlArgs
        {
            IdpMetadataXml = "<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://sts.windows.net/826602fe-2101-470c-9d71-ee1343668989\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>",
        },
        ExtraAttributesOauth2Client = new Gcp.Iam.Inputs.WorkforcePoolProviderExtraAttributesOauth2ClientArgs
        {
            IssuerUri = "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
            ClientId = "client-id",
            ClientSecret = new Gcp.Iam.Inputs.WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretArgs
            {
                Value = new Gcp.Iam.Inputs.WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretValueArgs
                {
                    PlainText = "client-secret",
                },
            },
            AttributesType = "AZURE_AD_GROUPS_ID",
            QueryParameters = new Gcp.Iam.Inputs.WorkforcePoolProviderExtraAttributesOauth2ClientQueryParametersArgs
            {
                Filter = "mail:gcp",
            },
        },
        DisplayName = "Display name",
        Description = "A sample SAML workforce pool provider.",
        Disabled = false,
        AttributeCondition = "true",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkforcePool;
import com.pulumi.gcp.iam.WorkforcePoolArgs;
import com.pulumi.gcp.iam.WorkforcePoolProvider;
import com.pulumi.gcp.iam.WorkforcePoolProviderArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderSamlArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtraAttributesOauth2ClientArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretValueArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtraAttributesOauth2ClientQueryParametersArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var pool = new WorkforcePool("pool", WorkforcePoolArgs.builder()
            .workforcePoolId("example-pool")
            .parent("organizations/123456789")
            .location("global")
            .build());

        var example = new WorkforcePoolProvider("example", WorkforcePoolProviderArgs.builder()
            .workforcePoolId(pool.workforcePoolId())
            .location(pool.location())
            .providerId("example-prvdr")
            .attributeMapping(Map.of("google.subject", "assertion.sub"))
            .saml(WorkforcePoolProviderSamlArgs.builder()
                .idpMetadataXml("<?xml version=\"1.0\"?><md:EntityDescriptor xmlns:md=\"urn:oasis:names:tc:SAML:2.0:metadata\" entityID=\"https://sts.windows.net/826602fe-2101-470c-9d71-ee1343668989\"><md:IDPSSODescriptor protocolSupportEnumeration=\"urn:oasis:names:tc:SAML:2.0:protocol\"> <md:KeyDescriptor use=\"signing\"><ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect\" Location=\"https://test.com/sso\"/></md:IDPSSODescriptor></md:EntityDescriptor>")
                .build())
            .extraAttributesOauth2Client(WorkforcePoolProviderExtraAttributesOauth2ClientArgs.builder()
                .issuerUri("https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0")
                .clientId("client-id")
                .clientSecret(WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretArgs.builder()
                    .value(WorkforcePoolProviderExtraAttributesOauth2ClientClientSecretValueArgs.builder()
                        .plainText("client-secret")
                        .build())
                    .build())
                .attributesType("AZURE_AD_GROUPS_ID")
                .queryParameters(WorkforcePoolProviderExtraAttributesOauth2ClientQueryParametersArgs.builder()
                    .filter("mail:gcp")
                    .build())
                .build())
            .displayName("Display name")
            .description("A sample SAML workforce pool provider.")
            .disabled(false)
            .attributeCondition("true")
            .build());

    }
}
resources:
  pool:
    type: gcp:iam:WorkforcePool
    properties:
      workforcePoolId: example-pool
      parent: organizations/123456789
      location: global
  example:
    type: gcp:iam:WorkforcePoolProvider
    properties:
      workforcePoolId: ${pool.workforcePoolId}
      location: ${pool.location}
      providerId: example-prvdr
      attributeMapping:
        google.subject: assertion.sub
      saml:
        idpMetadataXml: <?xml version="1.0"?><md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="https://sts.windows.net/826602fe-2101-470c-9d71-ee1343668989"><md:IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"> <md:KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>MIIDpDCCAoygAwIBAgIGAX7/5qPhMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxEzARBgNVBAMMCmRldi00NTg0MjExHDAaBgkqhkiG9w0BCQEWDWluZm9Ab2t0YS5jb20wHhcNMjIwMjE2MDAxOTEyWhcNMzIwMjE2MDAyMDEyWjCBkjELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xDTALBgNVBAoMBE9rdGExFDASBgNVBAsMC1NTT1Byb3ZpZGVyMRMwEQYDVQQDDApkZXYtNDU4NDIxMRwwGgYJKoZIhvcNAQkBFg1pbmZvQG9rdGEuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxrBl7GKz52cRpxF9xCsirnRuMxnhFBaUrsHqAQrLqWmdlpNYZTVg+T9iQ+aq/iE68L+BRZcZniKIvW58wqqS0ltXVvIkXuDSvnvnkkI5yMIVErR20K8jSOKQm1FmK+fgAJ4koshFiu9oLiqu0Ejc0DuL3/XRsb4RuxjktKTb1khgBBtb+7idEk0sFR0RPefAweXImJkDHDm7SxjDwGJUubbqpdTxasPr0W+AHI1VUzsUsTiHAoyb0XDkYqHfDzhj/ZdIEl4zHQ3bEZvlD984ztAnmX2SuFLLKfXeAAGHei8MMixJvwxYkkPeYZ/5h8WgBZPP4heS2CPjwYExt29L8QIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQARjJFz++a9Z5IQGFzsZMrX2EDR5ML4xxUiQkbhld1S1PljOLcYFARDmUC2YYHOueU4ee8Jid9nPGEUebV/4Jok+b+oQh+dWMgiWjSLI7h5q4OYZ3VJtdlVwgMFt2iz+/4yBKMUZ50g3Qgg36vE34us+eKitg759JgCNsibxn0qtJgSPm0sgP2L6yTaLnoEUbXBRxCwynTSkp9ZijZqEzbhN0e2dWv7Rx/nfpohpDP6vEiFImKFHpDSv3M/5de1ytQzPFrZBYt9WlzlYwE1aD9FHCxdd+rWgYMVVoRaRmndpV/Rq3QUuDuFJtaoX11bC7ExkOpg9KstZzA63i3VcfYv</ds:X509Certificate></ds:X509Data></ds:KeyInfo></md:KeyDescriptor><md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://test.com/sso"/></md:IDPSSODescriptor></md:EntityDescriptor>
      extraAttributesOauth2Client:
        issuerUri: https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0
        clientId: client-id
        clientSecret:
          value:
            plainText: client-secret
        attributesType: AZURE_AD_GROUPS_ID
        queryParameters:
          filter: mail:gcp
      displayName: Display name
      description: A sample SAML workforce pool provider.
      disabled: false
      attributeCondition: 'true'

The extraAttributesOauth2Client block configures a separate OAuth flow to retrieve group information from Microsoft Graph API. The attributesType specifies which Azure AD attribute to fetch (group IDs or email addresses), and queryParameters filters the results. This enrichment happens after SAML authentication, adding group data to the authenticated identity without modifying the SAML assertion itself.

Override group mappings with extended attributes

Extended attributes provide an alternative to attribute mapping for group membership, retrieving groups directly from the identity provider during sign-in and active sessions.

import * as pulumi from "@pulumi/pulumi";
import * as gcp from "@pulumi/gcp";

const pool = new gcp.iam.WorkforcePool("pool", {
    workforcePoolId: "example-pool",
    parent: "organizations/123456789",
    location: "global",
});
const example = new gcp.iam.WorkforcePoolProvider("example", {
    workforcePoolId: pool.workforcePoolId,
    location: pool.location,
    providerId: "example-prvdr",
    attributeMapping: {
        "google.subject": "assertion.sub",
    },
    oidc: {
        issuerUri: "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
        clientId: "https://analysis.windows.net/powerbi/connector/GoogleBigQuery",
        webSsoConfig: {
            responseType: "CODE",
            assertionClaimsBehavior: "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS",
        },
        clientSecret: {
            value: {
                plainText: "client-secret",
            },
        },
    },
    extendedAttributesOauth2Client: {
        issuerUri: "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
        clientId: "client-id",
        clientSecret: {
            value: {
                plainText: "client-secret",
            },
        },
        attributesType: "AZURE_AD_GROUPS_ID",
    },
});
import pulumi
import pulumi_gcp as gcp

pool = gcp.iam.WorkforcePool("pool",
    workforce_pool_id="example-pool",
    parent="organizations/123456789",
    location="global")
example = gcp.iam.WorkforcePoolProvider("example",
    workforce_pool_id=pool.workforce_pool_id,
    location=pool.location,
    provider_id="example-prvdr",
    attribute_mapping={
        "google.subject": "assertion.sub",
    },
    oidc={
        "issuer_uri": "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
        "client_id": "https://analysis.windows.net/powerbi/connector/GoogleBigQuery",
        "web_sso_config": {
            "response_type": "CODE",
            "assertion_claims_behavior": "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS",
        },
        "client_secret": {
            "value": {
                "plain_text": "client-secret",
            },
        },
    },
    extended_attributes_oauth2_client={
        "issuer_uri": "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
        "client_id": "client-id",
        "client_secret": {
            "value": {
                "plain_text": "client-secret",
            },
        },
        "attributes_type": "AZURE_AD_GROUPS_ID",
    })
package main

import (
	"github.com/pulumi/pulumi-gcp/sdk/v9/go/gcp/iam"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		pool, err := iam.NewWorkforcePool(ctx, "pool", &iam.WorkforcePoolArgs{
			WorkforcePoolId: pulumi.String("example-pool"),
			Parent:          pulumi.String("organizations/123456789"),
			Location:        pulumi.String("global"),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewWorkforcePoolProvider(ctx, "example", &iam.WorkforcePoolProviderArgs{
			WorkforcePoolId: pool.WorkforcePoolId,
			Location:        pool.Location,
			ProviderId:      pulumi.String("example-prvdr"),
			AttributeMapping: pulumi.StringMap{
				"google.subject": pulumi.String("assertion.sub"),
			},
			Oidc: &iam.WorkforcePoolProviderOidcArgs{
				IssuerUri: pulumi.String("https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0"),
				ClientId:  pulumi.String("https://analysis.windows.net/powerbi/connector/GoogleBigQuery"),
				WebSsoConfig: &iam.WorkforcePoolProviderOidcWebSsoConfigArgs{
					ResponseType:            pulumi.String("CODE"),
					AssertionClaimsBehavior: pulumi.String("MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS"),
				},
				ClientSecret: &iam.WorkforcePoolProviderOidcClientSecretArgs{
					Value: &iam.WorkforcePoolProviderOidcClientSecretValueArgs{
						PlainText: pulumi.String("client-secret"),
					},
				},
			},
			ExtendedAttributesOauth2Client: &iam.WorkforcePoolProviderExtendedAttributesOauth2ClientArgs{
				IssuerUri: pulumi.String("https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0"),
				ClientId:  pulumi.String("client-id"),
				ClientSecret: &iam.WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretArgs{
					Value: &iam.WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretValueArgs{
						PlainText: pulumi.String("client-secret"),
					},
				},
				AttributesType: pulumi.String("AZURE_AD_GROUPS_ID"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Gcp = Pulumi.Gcp;

return await Deployment.RunAsync(() => 
{
    var pool = new Gcp.Iam.WorkforcePool("pool", new()
    {
        WorkforcePoolId = "example-pool",
        Parent = "organizations/123456789",
        Location = "global",
    });

    var example = new Gcp.Iam.WorkforcePoolProvider("example", new()
    {
        WorkforcePoolId = pool.WorkforcePoolId,
        Location = pool.Location,
        ProviderId = "example-prvdr",
        AttributeMapping = 
        {
            { "google.subject", "assertion.sub" },
        },
        Oidc = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcArgs
        {
            IssuerUri = "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
            ClientId = "https://analysis.windows.net/powerbi/connector/GoogleBigQuery",
            WebSsoConfig = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcWebSsoConfigArgs
            {
                ResponseType = "CODE",
                AssertionClaimsBehavior = "MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS",
            },
            ClientSecret = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcClientSecretArgs
            {
                Value = new Gcp.Iam.Inputs.WorkforcePoolProviderOidcClientSecretValueArgs
                {
                    PlainText = "client-secret",
                },
            },
        },
        ExtendedAttributesOauth2Client = new Gcp.Iam.Inputs.WorkforcePoolProviderExtendedAttributesOauth2ClientArgs
        {
            IssuerUri = "https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0",
            ClientId = "client-id",
            ClientSecret = new Gcp.Iam.Inputs.WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretArgs
            {
                Value = new Gcp.Iam.Inputs.WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretValueArgs
                {
                    PlainText = "client-secret",
                },
            },
            AttributesType = "AZURE_AD_GROUPS_ID",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.gcp.iam.WorkforcePool;
import com.pulumi.gcp.iam.WorkforcePoolArgs;
import com.pulumi.gcp.iam.WorkforcePoolProvider;
import com.pulumi.gcp.iam.WorkforcePoolProviderArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcWebSsoConfigArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcClientSecretArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderOidcClientSecretValueArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtendedAttributesOauth2ClientArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretArgs;
import com.pulumi.gcp.iam.inputs.WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretValueArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var pool = new WorkforcePool("pool", WorkforcePoolArgs.builder()
            .workforcePoolId("example-pool")
            .parent("organizations/123456789")
            .location("global")
            .build());

        var example = new WorkforcePoolProvider("example", WorkforcePoolProviderArgs.builder()
            .workforcePoolId(pool.workforcePoolId())
            .location(pool.location())
            .providerId("example-prvdr")
            .attributeMapping(Map.of("google.subject", "assertion.sub"))
            .oidc(WorkforcePoolProviderOidcArgs.builder()
                .issuerUri("https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0")
                .clientId("https://analysis.windows.net/powerbi/connector/GoogleBigQuery")
                .webSsoConfig(WorkforcePoolProviderOidcWebSsoConfigArgs.builder()
                    .responseType("CODE")
                    .assertionClaimsBehavior("MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS")
                    .build())
                .clientSecret(WorkforcePoolProviderOidcClientSecretArgs.builder()
                    .value(WorkforcePoolProviderOidcClientSecretValueArgs.builder()
                        .plainText("client-secret")
                        .build())
                    .build())
                .build())
            .extendedAttributesOauth2Client(WorkforcePoolProviderExtendedAttributesOauth2ClientArgs.builder()
                .issuerUri("https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0")
                .clientId("client-id")
                .clientSecret(WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretArgs.builder()
                    .value(WorkforcePoolProviderExtendedAttributesOauth2ClientClientSecretValueArgs.builder()
                        .plainText("client-secret")
                        .build())
                    .build())
                .attributesType("AZURE_AD_GROUPS_ID")
                .build())
            .build());

    }
}
resources:
  pool:
    type: gcp:iam:WorkforcePool
    properties:
      workforcePoolId: example-pool
      parent: organizations/123456789
      location: global
  example:
    type: gcp:iam:WorkforcePoolProvider
    properties:
      workforcePoolId: ${pool.workforcePoolId}
      location: ${pool.location}
      providerId: example-prvdr
      attributeMapping:
        google.subject: assertion.sub
      oidc:
        issuerUri: https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0
        clientId: https://analysis.windows.net/powerbi/connector/GoogleBigQuery
        webSsoConfig:
          responseType: CODE
          assertionClaimsBehavior: MERGE_USER_INFO_OVER_ID_TOKEN_CLAIMS
        clientSecret:
          value:
            plainText: client-secret
      extendedAttributesOauth2Client:
        issuerUri: https://login.microsoftonline.com/826602fe-2101-470c-9d71-ee1343668989/v2.0
        clientId: client-id
        clientSecret:
          value:
            plainText: client-secret
        attributesType: AZURE_AD_GROUPS_ID

The extendedAttributesOauth2Client block retrieves group memberships that override the google.groups attribute from attributeMapping. Extended groups are fetched when users sign in and refreshed during active sessions, keeping group data current. This configuration is mutually exclusive with extraAttributesOauth2Client; you cannot use both on the same provider.

Beyond these examples

These snippets focus on specific provider-level features: SAML and OIDC authentication protocols, attribute mapping and enrichment, and Azure AD group integration. They’re intentionally minimal rather than full identity federation deployments.

The examples reference pre-existing infrastructure such as WorkforcePool resources, OAuth client credentials from identity providers, and organization-level workforce identity federation access. They focus on configuring the provider rather than provisioning the surrounding identity infrastructure.

To keep things focused, common provider patterns are omitted, including:

  • Attribute conditions for credential filtering (attributeCondition)
  • Provider lifecycle management (disabled, displayName, description)
  • SCIM-managed groups (scimUsage)
  • Custom attribute mappings beyond google.subject

These omissions are intentional: the goal is to illustrate how each provider feature is wired, not provide drop-in identity federation modules. See the WorkforcePoolProvider resource reference for all available configuration options.

Let's configure GCP Workforce Pool Identity Providers

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Access & Prerequisites
Do I need special access to use workforce identity federation?
Yes, you must request access from your Google Cloud account team for your billing/quota project before creating workforce pool providers. The account team will notify you when access is granted.
Configuration Errors & Constraints
Why am I getting an error when enabling both scimUsage and extendedAttributesOauth2Client?
These fields are mutually exclusive. You must choose either SCIM-managed groups or extended attributes OAuth2 client, not both.
What are the naming requirements for providerId and workforcePoolId?
providerId must be 4-32 characters using [a-z0-9-]. workforcePoolId must be 6-63 lowercase letters, digits, or hyphens, starting with a letter and without a trailing hyphen. Both cannot use the gcp- prefix.
What are the field length limits for workforce pool providers?
Key limits include: description (256 chars), displayName (32 chars), google.subject in attributeMapping (127 bytes), google.display_name (100 bytes), attribute mapping expressions (2048 chars), and total mapped attributes (8KB).
Identity Provider Setup
What's required in attributeMapping for OIDC providers?
OIDC providers must include google.subject in the attribute mapping. For example: {"google.subject": "assertion.sub"}.
How do I choose between OIDC and SAML?
Configure either the oidc block (for OpenID Connect 1.0 providers) or the saml block (for SAML identity providers). These are mutually exclusive; you cannot configure both on the same provider.
What's the difference between extraAttributesOauth2Client and extendedAttributesOauth2Client?
extraAttributesOauth2Client retrieves additional user attributes when claims aren’t available in authentication credentials (supported with SAML and OIDC). extendedAttributesOauth2Client retrieves extended group memberships that override google.groups (only supports AZURE_AD_GROUPS_ID attribute type).
Advanced Features
How do I temporarily disable a provider without deleting it?
Set disabled to true. Disabled providers cannot exchange tokens, but existing tokens still grant access.
Can I use custom attributes in IAM policies?
Yes, you can define up to 50 custom attributes using attribute.{custom_attribute} in attributeMapping. Reference them in IAM policies as principalSet://iam.googleapis.com/locations/{location}/workforcePools/{pool}/attribute.{custom_attribute}/{value}.
Lifecycle Management
What properties can't I change after creating a provider?
The location, providerId, and workforcePoolId properties are immutable after creation.
What happens when I delete a workforce pool provider?
Providers are soft-deleted and permanently deleted after approximately 30 days. You can restore a soft-deleted provider using the undelete API.

Using a different cloud?

Explore security guides for other cloud providers: