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

  1. Use the predefined constants: AuthorizationGrantType.AUTHORIZATION_CODE, CLIENT_CREDENTIALS, PASSWORD, JWT_BEARER, DEVICE_CODE instead of new AuthorizationGrantType(...)
  2. Normalize loaded grant type values to the constant via a mapping/lookup in your ClientRegistration repository
  3. 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

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


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)