spring-projects/spring-security · warning
AuthorizationGrantType
Error message
AuthorizationGrantType: %s does not match the pre-defined constant %s and won't match a valid OAuth2AuthorizedClientProvider
What it means
ClientRegistration.Builder.build() warns when the supplied AuthorizationGrantType has the same value as one of the pre-defined constants (AUTHORIZATION_CODE, CLIENT_CREDENTIALS, etc.) but is a different instance. Such a non-canonical instance will not match by reference/equality in OAuth2AuthorizedClientProvider selection, so authorized client resolution silently fails.
Solutions
- Use the predefined constants: AuthorizationGrantType.AUTHORIZATION_CODE, CLIENT_CREDENTIALS, PASSWORD, JWT_BEARER, DEVICE_CODE instead of new AuthorizationGrantType(...)
- Normalize loaded grant type values to the constant via a mapping/lookup in your ClientRegistration repository
- If a truly custom grant type, choose a value that does not collide with the built-in ones
Example fix
// before
.authorizationGrantType(new AuthorizationGrantType("authorization_code"))
// after
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) Defensive patterns
Strategy: validation
Validate before calling
String value = grantTypeValue.trim();
AuthorizationGrantType actual = Stream.of(
AuthorizationGrantType.AUTHORIZATION_CODE, AuthorizationGrantType.CLIENT_CREDENTIALS,
AuthorizationGrantType.PASSWORD, AuthorizationGrantType.JWT_BEARER,
AuthorizationGrantType.DEVICE_CODE)
.filter(g -> g.getValue().equalsIgnoreCase(value))
.findFirst().orElse(new AuthorizationGrantType(value));
Type guard
AuthorizationGrantType canonicalGrantType(String value) {
if ("authorization_code".equalsIgnoreCase(value)) return AuthorizationGrantType.AUTHORIZATION_CODE;
if ("client_credentials".equalsIgnoreCase(value)) return AuthorizationGrantType.CLIENT_CREDENTIALS;
return new AuthorizationGrantType(value);
} Prevention
- Always use AuthorizationGrantType predefined constants in code and mappers
- Normalize grant-type strings from config/DB through a lookup table
- Add an integration test asserting OAuth2AuthorizedClientProvider resolution works for each registered client
When it happens
Trigger: Calling ClientRegistration.withRegistrationId(...).authorizationGrantType(new AuthorizationGrantType("authorization_code")) or reading a grant type string and constructing a new instance instead of using AuthorizationGrantType.AUTHORIZATION_CODE.
Common situations: Deserializing client registrations from config/DB where the grant type string is mapped to a fresh AuthorizationGrantType object; custom grant types that collide with built-in values case-insensitively.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Invalid Authorization Grant Type
- Invalid Authorization Grant Type
- Invalid Client Registration with Id
- Unable to create an bean. Expected one bean of type , but…
- A Bean named mvcHandlerMappingIntrospector of type…
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/05af274ccf0fc66a.
Report an issue: GitHub.
Appendix: source
Thrown at oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/registration/ClientRegistration.java:715
Assert.hasText(this.authorizationUri, "authorizationUri cannot be empty");
Assert.hasText(this.tokenUri, "tokenUri cannot be empty");
}
private void validateClientCredentialsGrantType() {
Assert.notNull(this.authorizationGrantType, "authorizationGrantType cannot be null");
Assert.isTrue(AuthorizationGrantType.CLIENT_CREDENTIALS.equals(this.authorizationGrantType),
() -> "authorizationGrantType must be " + AuthorizationGrantType.CLIENT_CREDENTIALS.getValue());
Assert.hasText(this.registrationId, "registrationId cannot be empty");
Assert.hasText(this.clientId, "clientId cannot be empty");
Assert.hasText(this.tokenUri, "tokenUri cannot be empty");
}
private void validateAuthorizationGrantTypes() {
Assert.notNull(this.authorizationGrantType, "authorizationGrantType cannot be null");
for (AuthorizationGrantType authorizationGrantType : AUTHORIZATION_GRANT_TYPES) {
if (authorizationGrantType.getValue().equalsIgnoreCase(this.authorizationGrantType.getValue())
&& !authorizationGrantType.equals(this.authorizationGrantType)) {
logger.warn(LogMessage.format(
"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)
&& this.clientSettings.isRequireProofKey()) {
this.clientSettings = ClientSettings.builder().requireProofKey(false).build();
}
}
private void validateScopes() {
if (this.scopes == null) {
return;
}
for (String scope : this.scopes) {
Assert.isTrue(validateScope(scope), "scope \"" + scope + "\" contains invalid characters");
}
}View on GitHub (pinned to 96852e8860)