Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Spring Authorization Server grants: PKCE for public clients, credentials for services

Last updated: 1 Oct 20264 min read
tutorial
IntermediateBy AITrove Editorial

A browser client cannot keep a secret; PKCE protects its authorization-code exchange, while client credentials represent a service rather than a signed-in user.

Start with client capability

The parcel dashboard runs in a browser, so a bundled client secret would be visible to its users. Register it as a public client with an exact redirect location, authorization-code grant and required PKCE proof. A backend relay with a protected secret can be a confidential client and request client-credentials tokens for service-to-service work. Those tokens do not carry an operator session. Browser login and service-token caching solve different problems.

Check the grant against the API

A resource server should authorize a client-credentials token as a service identity, not manufacture a user from its subject. Keep scopes narrow, validate audience, and decide whether a human action needs a delegated user token instead. An exact redirect allowlist is part of the authorization-code boundary; a loose wildcard can hand a code to an unintended page. PKCE binds the code exchange to the client that started it, but does not replace redirect validation or API authorization.

Try the attack-shaped cases

Reject a code exchange with the wrong verifier, a redirect location absent from registration, and a browser request using a service token for an operator-only endpoint. The registration sketch below illustrates a public client; supply the redirect location from reviewed configuration, and run protocol tests against the selected Spring Security version before publishing the client.

Implementation sketch

Java
RegisteredClient browserClient(String reviewedRedirect) {
    return RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("parcel-dashboard")
        .clientAuthenticationMethod(ClientAuthenticationMethod.NONE)
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .redirectUri(reviewedRedirect)
        .scope("parcel.read")
        .clientSettings(ClientSettings.builder().requireProofKey(true).build())
        .build();
}

Cost and verification

PKCE adds a verifier and challenge per authorization attempt, with negligible compute cost. Server-side clients must store and rotate credentials; public clients cannot solve secret storage by hiding a value in JavaScript.

Common Mistakes

  • Do not ship a confidential-client secret in browser code.
  • Do not treat a client-credentials token as proof of a human user's identity.
  • Do not use redirect wildcards or skip the verifier failure test.

Read next

Spring Authorization Server JDBC state: clients, grants and consent across restarts, Spring Security OAuth2 login: callback, identity and browser session, Spring OAuth2 client credentials: acquire and reuse a service token, Spring resource server JWT: validate both issuer and intended audience.

spring
spring-security
oauth2
authorization-server-grant-boundaries
Storage details