Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to support multiple idp? #560

Open
coldcodefire opened this issue Mar 26, 2024 · 2 comments
Open

How to support multiple idp? #560

coldcodefire opened this issue Mar 26, 2024 · 2 comments

Comments

@coldcodefire
Copy link

hi guys, is it possible to support multiple idp? my goal is to make it work with Azure Ad and google auth ay the same time, and provide unique ACS path to idp side, which means at the idp side, it looks like one SAML SP. it can parse SAML assertion from Azure/Google in the same ACS path.
in current implementation, it seems SP is bond with an idp metadata. how can we expand this to multiple idp.

@gravgaard
Copy link

Interested due to #524

@OscarVanL
Copy link

OscarVanL commented Nov 10, 2024

If you initialise a new saml.ServiceProvider for every request then you can support multiple IdPs.

There are some shortcomings with this approach, for example:

  • You'll either need to call FetchMetadata every request to populate the IDPMetadata value, this is inefficient and could lead your server to be rate limited by the IdP (Speculation - I am unsure what kind of rate limits IdPs put on their metadata APIs).
  • Or you'll need to keep some kind of cache of each IdP's saml.EntityDescriptor (with a maximum size/TTL to mitigate memory leak/OOM risks) and call FetchMetadata only if you get a cache miss.

In my case, I couldn't use the metadata URL approach as my existing SAML implementation stored each IdP's certificate and entity ID on the server side, but not the metadata URL. It is possible to use this package without using FetchMetadata in this scenario by populating IDPMetadata manually.

The package doesn't seem to encourage this approach so it is a rather convoluted workaround (I see feature requests like #552 which would make this easier).

Here's how I (ab)use the package to work in this scenario:

idpCertificate := "-----BEGIN CERTIFICATE-----\nABCDEF\n-----END CERTIFICATE-----"
block, _ := pem.Decode([]byte(idpCertificate))
entityID := "https://sts.windows.net/388aeae7-c30d-4117-9f1c-f0d87071cf2c/"

sp := saml.ServiceProvider{
	MetadataURL: mustParseURL("https://sp.example.com/saml2/metadata"),
	AcsURL:      mustParseURL("https://sp.example.com/saml2/acs"),
	IDPMetadata: &saml.EntityDescriptor{
		EntityID: entityID,
		IDPSSODescriptors: []saml.IDPSSODescriptor{
			{
				SSODescriptor: saml.SSODescriptor{
					RoleDescriptor: saml.RoleDescriptor{
						KeyDescriptors: []saml.KeyDescriptor{
							{
								KeyInfo: saml.KeyInfo{
									X509Data: saml.X509Data{
										X509Certificates: []saml.X509Certificate{
											{
												Data: base64.StdEncoding.EncodeToString(block.Bytes),
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	},
}

assertion, err := sp.ParseXMLResponse(xmlres, []string{requestID})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants