refactor: remove PKCE from OIDC flow (confidential client)
All checks were successful
CI / cleanup-branch (push) Has been skipped
CI / build (push) Successful in 1m16s
CI / docker (push) Successful in 1m2s
CI / deploy-feature (push) Has been skipped
CI / deploy (push) Successful in 37s

Backend holds client_secret and does the token exchange server-side,
making PKCE redundant. Removes code_verifier/code_challenge from all
frontend auth paths and backend exchange method. Eliminates the source
of "grant request is invalid" errors from verifier mismatches.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-07 10:22:13 +02:00
parent 03ff9a3813
commit d4b530ff8a
7 changed files with 23 additions and 66 deletions

View File

@@ -129,7 +129,7 @@ public class OidcAuthController {
try {
OidcTokenExchanger.OidcUserInfo oidcUser =
tokenExchanger.exchange(request.code(), request.redirectUri(), request.codeVerifier());
tokenExchanger.exchange(request.code(), request.redirectUri());
String userId = "user:oidc:" + oidcUser.subject();
String issuerHost = URI.create(config.get().issuerUri()).getHost();
@@ -219,5 +219,5 @@ public class OidcAuthController {
}
}
public record CallbackRequest(String code, String redirectUri, String codeVerifier) {}
public record CallbackRequest(String code, String redirectUri) {}
}

View File

@@ -12,7 +12,6 @@ import com.nimbusds.oauth2.sdk.AuthorizationCode;
import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant;
import com.nimbusds.oauth2.sdk.TokenRequest;
import com.nimbusds.oauth2.sdk.TokenResponse;
import com.nimbusds.oauth2.sdk.pkce.CodeVerifier;
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
import com.nimbusds.oauth2.sdk.auth.Secret;
@@ -59,7 +58,7 @@ public class OidcTokenExchanger {
/**
* Exchanges an authorization code for validated user info.
*/
public OidcUserInfo exchange(String code, String redirectUri, String codeVerifier) throws Exception {
public OidcUserInfo exchange(String code, String redirectUri) throws Exception {
OidcConfig config = getConfig();
OIDCProviderMetadata metadata = getProviderMetadata(config.issuerUri());
@@ -69,9 +68,8 @@ public class OidcTokenExchanger {
new Secret(config.clientSecret())
);
AuthorizationCodeGrant grant = codeVerifier != null && !codeVerifier.isBlank()
? new AuthorizationCodeGrant(new AuthorizationCode(code), new URI(redirectUri), new CodeVerifier(codeVerifier))
: new AuthorizationCodeGrant(new AuthorizationCode(code), new URI(redirectUri));
AuthorizationCodeGrant grant = new AuthorizationCodeGrant(
new AuthorizationCode(code), new URI(redirectUri));
TokenRequest tokenRequest = new TokenRequest(
metadata.getTokenEndpointURI(),
@@ -79,8 +77,7 @@ public class OidcTokenExchanger {
grant
);
log.info("OIDC token exchange: tokenEndpoint={}, redirectUri={}, hasPkce={}, grantType={}",
metadata.getTokenEndpointURI(), redirectUri, codeVerifier != null && !codeVerifier.isBlank(), grant.getType());
log.info("OIDC token exchange: tokenEndpoint={}, redirectUri={}", metadata.getTokenEndpointURI(), redirectUri);
var httpRequest = tokenRequest.toHTTPRequest();
if (securityProperties.isOidcTlsSkipVerify()) {