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

ClientRegistrations class's OpenID Provider Configuration Validation does not conform to specification #16460

Open
abchau opened this issue Jan 21, 2025 · 3 comments
Assignees
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-feedback We need additional information before we can continue type: bug A general bug

Comments

@abchau
Copy link

abchau commented Jan 21, 2025

Describe the bug

The section 4.3 in the OpenID Connect Discovery specification says "the Issuer URL that was used as the prefix to /.well-known/openid-configuration". However, the validation in ClientRegistrations.class does an equal() comparison of the entire issuer URL which is comparing too much because a provider's Issuer URL might contain additional parameters.

For example, in Azure AD B2C multiple OIDC configurations could be using the same Issuer and configuration URL in Azure AD B2C is not an straightforward URL. An additional parameter p is added at the end to identify which configurations you want to retrieve.

Usual Provider:

https://someprovider.com/someprefix/v2.0/

Azure AD B2C:

https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/?p=b2c_1_policy_name_a
{
  "issuer": "https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/",
  "authorization_endpoint": "https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/oauth2/v2.0/authorize?p=b2c_1_policy_name_a",
...
}

https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/?p=b2c_1_policy_name_b
{
  "issuer": "https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/",
  "authorization_endpoint": "https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/oauth2/v2.0/authorize?p=b2c_1_policy_name_b",
...
}

To Reproduce

Follow the procedure at https://learn.microsoft.com/en-us/azure/developer/java/spring-framework/configure-spring-boot-starter-java-app-with-azure-active-directory-b2c-oidc

Because the well known uri is https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/.well-known/openid-configuration?p=b2c_1_policy_name_a, this Issuer URL must be configurated with additional ?p=b2c_1_policy_name_a at the end.

# application.properties
spring.security.oauth2.client.provider.b2c.issuer-uri=https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/?p=b2c_1_policy_name_a

The following exception will be thrown during start up.

Caused by: java.lang.IllegalStateException: The Issuer "https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/" provided in the configuration metadata did not match the requested issuer "https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/?p=b2c_1_policy_name_a"
	at org.springframework.util.Assert.state(Assert.java:101) ~[spring-core-6.2.1.jar:6.2.1]
	at org.springframework.security.oauth2.client.registration.ClientRegistrations.withProviderConfiguration(ClientRegistrations.java:286) ~[main/:na]
	at org.springframework.security.oauth2.client.registration.ClientRegistrations.lambda$oidc$0(ClientRegistrations.java:205) ~[main/:na]
	at org.springframework.security.oauth2.client.registration.ClientRegistrations.getBuilder(ClientRegistrations.java:256) ~[main/:na]
	at org.springframework.security.oauth2.client.registration.ClientRegistrations.fromIssuerLocation(ClientRegistrations.java:192) ~[main/:na]

The exception was due to this method is comparing https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/ (metadata.getIssuer().getValue()) and https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/?p=b2c_1_policy_name_a (issuer).

	private static ClientRegistration.Builder withProviderConfiguration(AuthorizationServerMetadata metadata, String issuer) {
		String metadataIssuer = metadata.getIssuer().getValue();
		Assert.state(issuer.equals(metadataIssuer),
				() -> "The Issuer \"" + metadataIssuer + "\" provided in the configuration metadata did "
						+ "not match the requested issuer \"" + issuer + "\"");

Expected behavior
The validation should be validating whether the issuer value from well known configuration is the prefix of Issuer URL.
defined in spring.security.oauth2.client.provider.b2c.issuer-uri= without taking into account of additional query string parameters .

Possible Solution

I've tested in my local that using issuer.startsWith(metadataIssuer) instead of issuer.equals(metadataIssuer) could avoid the issue and it seems more conform to the specification as in "the Issuer URL that was used as the prefix to /.well-known/openid-configuration".

e.g.

		Assert.state(issuer.startsWith(metadataIssuer),
				() -> "The Issuer \"" + metadataIssuer + "\" provided in the configuration metadata did "
						+ "not match the requested issuer \"" + issuer + "\"");
@abchau abchau added status: waiting-for-triage An issue we've not yet triaged type: bug A general bug labels Jan 21, 2025
@abchau abchau changed the title ClientRegistrations's OpenID Provider Configuration Validation does not conform to specification ClientRegistrations class's OpenID Provider Configuration Validation does not conform to specification Jan 21, 2025
@abchau
Copy link
Author

abchau commented Jan 22, 2025

sample.zip

@sjohnr sjohnr self-assigned this Jan 23, 2025
@sjohnr
Copy link
Member

sjohnr commented Jan 23, 2025

@abchau, thanks for getting in touch!

The section 4.3 in the OpenID Connect Discovery specification says "the Issuer URL that was used as the prefix to /.well-known/openid-configuration". However, the validation in ClientRegistrations.class does an equal() comparison of the entire issuer URL which is comparing too much because a provider's Issuer URL might contain additional parameters.

The spec states (emphasis added by me):

The issuer value returned MUST be identical to the Issuer URL that was used as the prefix to /.well-known/openid-configuration to retrieve the configuration information.

This makes it quite clear that the requirement is to use strict equality to validate the issuer returned.

Because the well known uri is https://eaxmple.b2clogin.com/00000000-0000-0000-00000000-000000000000/v2.0/.well-known/openid-configuration?p=b2c_1_policy_name_a, this Issuer URL must be configurated with additional ?p=b2c_1_policy_name_a at the end.

Adding additional data to the request, such as ?p=b2c_1_policy_name_a would be off-spec, and require customization on your end. I believe you would want to influence the outbound request separately from specifying the issuer URI.

However, I believe doing so is not in the spirit of the specification and it appears the provider is deviating from that. The well-known URL is very well defined, and should not require additional parameters. If you disagree, please provide a reference in the spec where provision is made for this requirement. Otherwise, I think the next step would be exploring other options for working around this issue.

@sjohnr sjohnr added status: waiting-for-feedback We need additional information before we can continue in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 23, 2025
@spring-projects-issues
Copy link

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Jan 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-feedback We need additional information before we can continue type: bug A general bug
Projects
None yet
Development

No branches or pull requests

3 participants