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

URL-encoded parameters in redirect URI are encoded twice #1011

Closed

Conversation

andreasf
Copy link
Contributor

This fixes an issue with redirect URIs that already have URL-encoded parameters baked in.

I recently built an OIDC provider with Authorization Server for a client and noticed that some of their redirect URIs would cause problems.

PHP's Yii framework creates redirect URIs in the format https://example.com/index.php?r=site%2Fauth&authclient=foo. The authorization endpoint would reencode the %2F in the parameter to %252F and redirect users to a non-existing route.

This PR fixes the behavior while making sure that the encoding of the state parameter is unchanged.

Related to #875

… authorization response

The redirect URI used in the test contains a URL-encoded parameter and is
similar to redirect URIs of the popular Yii PHP framework.

Also document how state is currently decoded and re-encoded, modifying it in
the process.
…response

Redirect URIs can contain query parameters and these can be URI encoded.
UriComponentsBuilder does not decode query parameters in fromUriString(). They
become part of the template which by default is encoded (again).

This commit configures a UriBuilder that does not encode the template but only
provided values.
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 16, 2022
Copy link
Collaborator

@jgrandja jgrandja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @andreasf ! Please see review comments.

@@ -39,6 +39,18 @@ public static RegisteredClient.Builder registeredClient() {
.scope("scope1");
}

public static RegisteredClient.Builder registeredClientEncodedUri() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this and leverage the existing TestRegisteredClients.registeredClient() and add the url-encoded redirect-uri

@@ -8,6 +8,10 @@ group = project.rootProject.group
version = project.rootProject.version
sourceCompatibility = "17"

test {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all changes in custom-consent-authorizationserver since we have test coverage in default-authorizationserver and there is no need to duplicate

@@ -8,6 +8,10 @@ group = project.rootProject.group
version = project.rootProject.version
sourceCompatibility = "17"

test {
useJUnitPlatform()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed since it's automatically applied by the SpringJavaPlugin

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent quite a while figuring out why the tests don't run locally and in CI, in my opinion this config should have been added in the "Upgrade to JUnit 5" commit.

Did you try it out and are tests running (and failing the build) on your machine without explicitly enabling JUnit 5?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that the samples do not use the io.spring.convention.spring-module plugin, so SpringJavaPlugin is not applied as I previously mentioned. Sorry for the confusion there.

However, I'm wondering why the tests are failing on your end? The tests in default-authorizationserver sample are passing locally and in CI for quite some time now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I didn't make myself fully clear. The tests are not failing in their current state.

What I meant was: if Gradle says the build was successful, that does not necessarily mean that it ran tests. To check if it does, I like to make a test fail, e.g. by throwing a RuntimeException. The failing test should also lead to a failing build.

For CI, I checked the logs of several commits for the test output – I think there's a DB-related message. This message did not appear after the upgrade to JUnit 5.

@@ -87,6 +87,7 @@ public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTe
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
.redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc?param=is%2Fencoded")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's change is%2Fencoded to encoded%20parameter%20value


private static final String AUTHORIZATION_REQUEST = UriComponentsBuilder
.fromPath("/oauth2/authorize")
.queryParam("response_type", "code")
.queryParam("client_id", "messaging-client")
.queryParam("scope", "openid")
.queryParam("state", "some-state")
.queryParam("redirect_uri", REDIRECT_URI)
.queryParam("state", STATE)
Copy link
Collaborator

@jgrandja jgrandja Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all changes related to the state parameter since this was fixed in gh-875 and test coverage is included in the associated commit

@@ -67,6 +74,16 @@ public void setUp() {
this.webClient.getCookieManager().clearCookies(); // log out
}

@Test
void authorizationRequestProperlyEncoded() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this test since it directly tests UriComponentsBuilder, which is not owned by this project.

@@ -83,7 +83,7 @@
public class OAuth2AuthorizationEndpointFilterTests {
private static final String DEFAULT_AUTHORIZATION_ENDPOINT_URI = "/oauth2/authorize";
private static final String AUTHORIZATION_URI = "https://provider.com/oauth2/authorize";
private static final String STATE = "state";
private static final String STATE = "previously encoded/state";
Copy link
Collaborator

@jgrandja jgrandja Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all changes related to the state parameter since this was fixed in gh-875 and test coverage is included in the associated commit

@@ -58,15 +62,18 @@ public class DefaultAuthorizationServerConsentTests {
@MockBean
private OAuth2AuthorizationConsentService authorizationConsentService;

private final String redirectUri = "http://127.0.0.1/login/oauth2/code/messaging-client-oidc";
private final String redirectUri = "http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc?param=is%2Fencoded";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert all changes in DefaultAuthorizationServerConsentTests since we have same test coverage in DefaultAuthorizationServerApplicationTests

@jgrandja jgrandja self-assigned this Jan 9, 2023
@jgrandja jgrandja added type: bug A general bug and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 9, 2023
@jgrandja jgrandja added this to the 0.4.1 milestone Jan 9, 2023
@jgrandja jgrandja changed the title Fix: URL-encoded parameters in redirect URI are encoded twice URL-encoded parameters in redirect URI are encoded twice Jan 10, 2023
@jgrandja
Copy link
Collaborator

@andreasf Just checking back to see if you're able to apply the requested changes?

@andreasf
Copy link
Contributor Author

@andreasf Just checking back to see if you're able to apply the requested changes?

I'm a bit busy but I'll try to take a look this week

jgrandja added a commit that referenced this pull request Feb 15, 2023
@jgrandja
Copy link
Collaborator

@andreasf We have a release next week and I wanted to get this fix in so I went ahead and added a polish commit and merged.

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

Successfully merging this pull request may close these issues.

3 participants