English 中文(简体)
未证实的批量-类型错误
原标题:unsupported_grant_type error for authorization_code grant type: Spring Security OAuth2

I am trying to implement the OAuth2 Authorization Server with OpenID Connect, using Spring Security. For this, I am using the authorization code flow with refresh token and JWT. Here is my configuration code-

@Configuration
public class SecurityConfig {

  @Bean
  @Order(1)
  public SecurityFilterChain asSecurityFilterChain(HttpSecurity http) throws Exception {
    OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

    http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
        .authorizationEndpoint(
            a -> a.authenticationProviders(getAuthorizationEndpointProviders()))
        .oidc(Customizer.withDefaults());

    http.exceptionHandling(
        e -> e.authenticationEntryPoint(
            new LoginUrlAuthenticationEntryPoint("/login")));

    return http.build();
  }

  private Consumer<List<AuthenticationProvider>> getAuthorizationEndpointProviders() {
    return providers -> {
      for (AuthenticationProvider p : providers) {
        if (p instanceof OAuth2AuthorizationCodeRequestAuthenticationProvider x) {
          x.setAuthenticationValidator(new CustomRedirectUriValidator());
        }
      }
    };
  }

  @Bean
  @Order(2)
  public SecurityFilterChain appSecurityFilterChain(HttpSecurity http) throws Exception {
    http.formLogin()
        .and()
        .authorizeHttpRequests().anyRequest().authenticated();

    return http.build();
  }

  @Bean
  public UserDetailsService userDetailsService() {
    var u1 = User.withUsername("user")
        .password("password")
        .authorities("read")
        .build();

    return new InMemoryUserDetailsManager(u1);
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
  }

  @Bean
  public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient r1 = RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("client")
        .clientSecret("secret")
        .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
        .scope(OidcScopes.OPENID)
        .scope(OidcScopes.PROFILE)
        .redirectUri("https://springone.io/authorized")
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
        .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
        .tokenSettings(
            TokenSettings.builder()
                .accessTokenFormat(OAuth2TokenFormat.REFERENCE) 
                .accessTokenTimeToLive(Duration.ofSeconds(900))
                .build())
        .build();

    return new InMemoryRegisteredClientRepository(r1);
  }

  @Bean
  public AuthorizationServerSettings authorizationServerSettings() {
    return AuthorizationServerSettings.builder()
        .build();
  }

  @Bean
  public JWKSource<SecurityContext> jwkSource() throws Exception {
    KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
    kg.initialize(2048);
    KeyPair kp = kg.generateKeyPair();

    RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
    RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();

    RSAKey key = new RSAKey.Builder(publicKey)
        .privateKey(privateKey)
        .keyID(UUID.randomUUID().toString())
        .build();

    JWKSet set = new JWKSet(key);
    return new ImmutableJWKSet(set);
  }

  @Bean
  public OAuth2TokenCustomizer<JwtEncodingContext> oAuth2TokenCustomizer() {
    return context -> {
      context.getClaims().claim("test", "test");
    };
  }

}

<>CustomRedirectUrlValidator

import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationContext;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationException;
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationCodeRequestAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;

import java.util.function.Consumer;

public class CustomRedirectUriValidator implements Consumer<OAuth2AuthorizationCodeRequestAuthenticationContext> {

    @Override
    public void accept(OAuth2AuthorizationCodeRequestAuthenticationContext context) {
        OAuth2AuthorizationCodeRequestAuthenticationToken a = context.getAuthentication();
        RegisteredClient registeredClient = context.getRegisteredClient();
        String uri = a.getRedirectUri();

        if (!registeredClient.getRedirectUris().contains(uri)) {
            var error = new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST);
            throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);
        }
    }
}

<PKCE 代码 verifier和代码挑战作为生成

SecureRandom sr = new SecureRandom();

        byte[] code = new byte[32];

        sr.nextBytes(code);

        String codeVerifier = Base64.getUrlEncoder()
                .withoutPadding()
                .encodeToString(code);

        MessageDigest md;
        {
            try {
                md = MessageDigest.getInstance("SHA-256");
                byte[] digested = md.digest(codeVerifier.getBytes());
                String code_challenge = Base64.getUrlEncoder().withoutPadding().encodeToString(digested);
                log.info("Code verifier: {}", codeVerifier);
                log.info("Code challenge: {}", code_challenge);
            } catch (NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }
        }

现在,这是我为获得象征性的准入而采取的步骤。

  1. GET request to oauth2/authorize-

http:// localhost:80/oauth2/authorize?response_type=code&client_id=client&cop= openid&redirect_uri=https://merone.io/authorized&code_challenge=z5f7uuzQ2f0c1CNpuY0UoQE5jSN30YpcxS2s6wmoPq0&code_challenge_method=256

  1. After providing the login username and password as user and password, the browser redirects to the specified redirection url-

https://childrenone.io/authorized?code=TfzC56cc7xwa0wS-O0VvMm1k6kOhYchOcj7sW_pXyeEaRIvw9V6N5YuXoeqwQka1Cvf0ZY9EzGg0dM9zlCXLPYU3q7_T9KVsuc1_sGTV7XBxCHPxtq1VRufg3Zx

  1. Now, using the provided code, POST request to obtain the access token- enter image description here enter image description here

现在,如果一切都正确的话,我就必须能够在反应机构获得信号。 但我却发现错误。

{
    "error_description": "OAuth 2.0 Parameter: grant_type",
    "error": "unsupported_grant_type",
    "error_uri": "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"
}

Now, I checked with Spring Security Grant Types and Spring Security Authorization Server that the grant type authorization_code is valid. But, I can t understand, why am I getting this error? Please help me resolve this.

问题回答

我也面临同样的问题,没有找到解决问题的办法。 在我获得象征性准入之前,我不得不将我的春季间版本从3.2.1降为3.1.0。

plugins { id java id org.springframework.boot version 3.1.0 id io.spring.dependency-management version 1.1.4 }

  1. Create a GET request to oauth2/authorize-

http:// localhost:90/oauth2/authorize?response_type=code&client_id=client&cop=openid&redirect_uri=http:// localhost:90/redirect/authorized&code_challenge=OaWJmipPOKmE66leDkUV8V9Iy8l6gg0NBsRFzgAeg&code_challenge_method=256

  1. After providing the login username and password on the default login form displayed on the browser, you are redirected to the specified redirect url-

http:// localhost:90/redirect/authorized?code=OspZOqTvauO59fLZm7Z7PFO10vzznxpH9TcIhaXIcVshOmI5f_O-oDv4zej7WBS8Jq_USUAm8BgkC-P0vk8mRXUhYTbIwrwmYN3C6hnjP4rNnpghf9Mzly8KZGOFgX

  1. Next, use the code obtained from the authorization server to request an access token like so:

http://localhost:9090/oauth2/token?client_id=client&redirect_uri=http://localhost:9090/redirect/authorized&grant_type=authorization_code&code=OspZOqTvauO59fLZm7Z7PFO10vzznxpH9TcIhaXIcVshOmI5f_O-oDv4zej7WBS8Jq_USUAm8BgkC-P0vk8mRXUhYTbIwrwmYN3C6hnjP4rNnpghf9MzlyIs8KZGOFgX&code_verifier=oIoS6DKeU5B3Dccu_QOutW58En8Ycs5tuqk7hv7rY0A

https://i.stack.imgur.com/fELtS.png”rel=“nofollow noreferer”> 请求张贴

https://i.stack.imgur.com/UepSH.png”rel=“nofollow noreferer”

Access token





相关问题
Spring Security Encrypt MD5

I have a java web application using spring framework and spring security for its login. In my database I have my passwords encrypted to MD5 before being saved. I added in my application-config.xml ...

Grails security [closed]

Which is the best security solution for grails among acegi, jsecurity and Stark security?

Rewrite spring-security redirect URLs

I m trying to get Tuckey UrlRewriteFilter to tidy up URLs for my webapp. One problem I ve got is that when spring-security notices that an anonymous user is trying to access a protected resource it ...

Spring Security Custom freemarker form

I m currently working on a project were we use freemarker as a template language. Instead of using the defualt login form I have created a custom controller and a custom freemarker view which goes ...

Spring Security - Different Filter Entry Points based on Role

I m developing a webapp which allows for two types for users - User and Admin. There s are two parts of the site - the User side, and the Admin side. I m using Spring Security to secure both sites ...

热门标签