Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

rohan-naik07
Copy link

@rohan-naik07 rohan-naik07 commented Jul 10, 2025

Fixes gh-16391

PKCE enabled by default for confidential as well as public clients.
Client Authentication method won't affect the PKCE customizer.
PKCE can be disabled using isRequireProofKey() client setting.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 10, 2025
@rohan-naik07 rohan-naik07 changed the base branch from main to 6.5.x July 10, 2025 16:55
@rohan-naik07 rohan-naik07 marked this pull request as ready for review July 14, 2025 14:29
@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) type: breaks-passivity A change that breaks passivity with the previous release and removed status: waiting-for-triage An issue we've not yet triaged labels Jul 15, 2025
@jgrandja jgrandja self-assigned this Jul 15, 2025
@rohan-naik07
Copy link
Author

Hi @jgrandja ,

Thank you for reviewing my pull request. I noticed that you marked it as "breaks passivity" and self-assigned the related issue.

I want to understand this better so I can improve future contributions. Could you please clarify what aspect of the PR breaks passivity, and how you envision the correct approach? I'm eager to align with the design principles of the project and contribute effectively.

Thanks again for your time and guidance!

Best regards,
Rohan

@jgrandja
Copy link
Contributor

Hi @rohan-naik07. I haven't had time to review your PR but I plan on it next week.

Our process is to self-assign PR's when we review it and the user who submitted the PR is assigned the original issue.

The reason I marked this "breaks-passivity" is because it is a breaking change that needs to be applied. For example, since the required change is for the OAuth2 Client to send PKCE parameters by default, it's possible that the authorization server does not support PKCE and therefore the flow will fail. So what was working previously might stop working with the upgrade to 7.0 because of this change. Does that make sense?

FYI, the reason for this change is OAuth 2.1 recommends/requires PKCE.

@rohan-naik07
Copy link
Author

Ok, that makes sense. Thanks for clarifying my doubts.

Copy link
Contributor

@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 @rohan-naik07. Please see review comments.

Also, please rebase off of main and ensure there is only 1 commit with the changes. Thanks.

clientRegistration.clientName = StringUtils.hasText(this.clientName) ? this.clientName
: this.registrationId;
clientRegistration.clientSettings = this.clientSettings;
if (this.clientSettings.requireProofKey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this since clientRegistration.clientSettings is set in previous line with this.clientSettings and only the clientSettings should be used.

private ClientSettings() {

}
private ClientSettings() {}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please revert this formatting change as only required changes should be applied

private boolean requireProofKey;

private Builder() {
this.requireProofKey = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please move this to variable initialization private boolean requireProofKey = true;

}
if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())
|| clientRegistration.getClientSettings().isRequireProofKey()) {
if (clientRegistration.getClientSettings().isRequireProofKey()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Public Clients (indicated with ClientAuthenticationMethod.NONE) always require PKCE but with this change it's possible to disable PKCE for Public Clients. Please revert this as the original logic is still correct.

}
if (ClientAuthenticationMethod.NONE.equals(clientRegistration.getClientAuthenticationMethod())
|| clientRegistration.getClientSettings().isRequireProofKey()) {
if (clientRegistration.getClientSettings().isRequireProofKey()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Public Clients (indicated with ClientAuthenticationMethod.NONE) always require PKCE but with this change it's possible to disable PKCE for Public Clients. Please revert this as the original logic is still correct.

====
Public Clients are supported using https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE).
PKCE will automatically be used when `client-authentication-method` is set to "none" (`ClientAuthenticationMethod.NONE`).
https://tools.ietf.org/html/rfc7636[Proof Key for Code Exchange] (PKCE) will be enabled by default for public as well as confidential clients. Refer https://docs.spring.io/spring-security/reference/servlet/oauth2/client/client-authentication.html#oauth2-client-authentication-public[this
Copy link
Contributor

Choose a reason for hiding this comment

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

Please revert this as the original content is still valid

The supported values are *header*, *form*, and *query*.
<16> `userNameAttributeName`: The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `authorizationGrantType` is `none`, then PKCE will be enabled by default.
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: This will by default be `true`, as PKCE will be enabled by default.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please update the text to:

If true or if clientAuthenticationMethod is none, then PKCE will be enabled.

Copy link
Author

Choose a reason for hiding this comment

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

Aren't we stressing enough on the point that PKCE will be also enabled for confidential clients?... Or we don't want to for now

// @formatter:on
}

public static ClientRegistration.Builder publicClientRegistrationWithNoPkce() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please remove this as TestClientRegistrations.clientRegistration() can be used and the caller can simply change builder.clientSettings(updatedClientSettings)

@rohan-naik07 rohan-naik07 force-pushed the pkce-default-config-gh-16391 branch 3 times, most recently from abe7742 to cb7cff4 Compare August 21, 2025 18:07
@rohan-naik07 rohan-naik07 requested a review from jgrandja August 23, 2025 08:35
@rohan-naik07 rohan-naik07 force-pushed the pkce-default-config-gh-16391 branch 2 times, most recently from 80416c4 to 4f7a21c Compare September 2, 2025 16:20
@rohan-naik07 rohan-naik07 changed the base branch from 6.5.x to main September 2, 2025 16:21
@rohan-naik07
Copy link
Author

Hi @jgrandja , just wanted to kindly follow up on this PR. Please let me know if there are any changes or clarifications I can make to help move it forward.

@jgrandja
Copy link
Contributor

jgrandja commented Sep 2, 2025

Hi @rohan-naik07. Really apologize for the delay. I was at SpringOne last week and I was very busy leading up to that. I have a little more breathing room now and need to catch up on quite a bit. I'm planning on reviewing your PR later this week or early next week. Thanks for your patience.

@rohan-naik07 rohan-naik07 marked this pull request as draft September 16, 2025 15:49
Copy link
Contributor

@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 your patience @rohan-naik07. Please see review comments.

I noticed there were a lot of changes made that were not relevant to the enhancement this PR addresses, especially in DefaultOAuth2AuthorizationRequestResolverTests.

In general, PR's should only add/update the minimal amount of code necessary to fulfill the enhancement requirements. No other code should change, especially if it's not relevant to the enhancement.

I would recommend going through all the code again and reverting everything that is not needed as part of this enhancement. There is quite a bit of updates in DefaultOAuth2AuthorizationRequestResolverTests that should be reverted.

Thanks.

The supported values are *header*, *form*, and *query*.
<16> `userNameAttributeName`: The name of the attribute returned in the UserInfo Response that references the Name or Identifier of the end-user.
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `authorizationGrantType` is `none`, then PKCE will be enabled by default.
<17> [[oauth2Client-client-registration-requireProofKey]]`requireProofKey`: If `true` or if `authorizationGrantType` is `none`, then PKCE will be enabled.
Copy link
Contributor

Choose a reason for hiding this comment

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

As mentioned in this comment, please update to:

If true or if clientAuthenticationMethod is none, then PKCE will be enabled.

clientRegistration.clientName = StringUtils.hasText(this.clientName) ? this.clientName
: this.registrationId;
clientRegistration.clientSettings = this.clientSettings;
if (clientRegistration.clientSettings.requireProofKey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not understanding the reason for this but I believe it should be removed.

"AuthorizationGrantType: %s does not match the pre-defined constant %s and won't match a valid OAuth2AuthorizedClientProvider",
this.authorizationGrantType, authorizationGrantType));
}
if (!AuthorizationGrantType.AUTHORIZATION_CODE.equals(this.authorizationGrantType)
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add a new validation check as follows:

If authorization_code and client_authentication_method equals none then pkce must be true else invalid

private static final long serialVersionUID = 7495627155437124692L;

private boolean requireProofKey;
private boolean requireProofKey = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be reverted since it will be set by the Builder

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.*;
Copy link
Contributor

Choose a reason for hiding this comment

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

Please revert this as wildcard imports are not allowed

@@ -1,5 +1,5 @@
/*
* Copyright 2004-present the original author or authors.
* Copyright 2002-2025 the original author or authors.
Copy link
Contributor

Choose a reason for hiding this comment

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

This should not change. Please revert.

}

@Test
void authorizationRequestBaseUriEqualToRedirectFilter() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this removed? Please revert.

public void resolveWhenNotAuthorizationRequestThenDoesNotResolve() {
String requestUri = "/path";
MockHttpServletRequest request = get(requestUri).build();
MockHttpServletRequest request = new MockHttpServletRequest("GET", requestUri);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did this change? Please only make required changes that are needed. Please revert.

public void resolveWhenNotAuthorizationRequestThenRequestBodyNotConsumed() throws IOException {
String requestUri = "/path";
MockHttpServletRequest request = post(requestUri).build();
MockHttpServletRequest request = new MockHttpServletRequest("POST", requestUri);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did this change? Please only make required changes that are needed. Please revert.

assertPkceApplied(authorizationRequest, clientRegistration);
}

// gh-6548
Copy link
Contributor

Choose a reason for hiding this comment

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

Why was this removed? The comment gh-6548 typically (by convention) refers to a bug that was fixed previously so I don't think it should be removed.

@jgrandja jgrandja added this to the 7.0.0-RC1 milestone Sep 16, 2025
@rohan-naik07 rohan-naik07 force-pushed the pkce-default-config-gh-16391 branch from 4f7a21c to d3b143d Compare September 20, 2025 14:34
@rohan-naik07 rohan-naik07 reopened this Sep 20, 2025
@rohan-naik07 rohan-naik07 force-pushed the pkce-default-config-gh-16391 branch from 5dd2b47 to a3020f9 Compare September 22, 2025 16:52
@rohan-naik07 rohan-naik07 force-pushed the pkce-default-config-gh-16391 branch from a3020f9 to 5efddb4 Compare September 22, 2025 16:56
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) type: breaks-passivity A change that breaks passivity with the previous release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Consider Enabling PKCE for Authorization Code by Default
3 participants