java Spring Boot: error="invalid_grant", error_description="Bad credentials"

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43423932/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 07:25:06  来源:igfitidea点击:

Spring Boot: error="invalid_grant", error_description="Bad credentials"

javaspringspring-boot

提问by Arian

I wrote a very Spring boot simple app.

I wrote a very Spring boot simple app.

To get the authentication token, I used the following curlcommand. But instead I see the following error in the server log (eclipse console): error="invalid_grant", error_description="Bad credentials"

To get the authentication token, I used the following curlcommand. But instead I see the following error in the server log (eclipse console): error="invalid_grant", error_description="Bad credentials"

curl -v -u greetings:123456 -X POST http://localhost:8080/oauth/token -H "Accept: application/json" -d "username=username&password=password&grant_type=password&scope=write&client_secret=12345&client_id=greetings"

I wonder:

I wonder:

What have I done wrong that it doesn't let me get the auth code?

What have I done wrong that it doesn't let me get the auth code?

OAuth2ServerConfiguration.java

OAuth2ServerConfiguration.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;


@Configuration
@EnableResourceServer
@EnableAuthorizationServer
class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {

    String applicationName = "greetings";

    // This is required for password grants, which we specify below as one of the
    // {@literal authorizedGrantTypes()}.
    @Autowired
    AuthenticationManagerBuilder authenticationManager;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        // Workaround for https://github.com/spring-projects/spring-boot/issues/1801
        endpoints.authenticationManager(new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication)
                    throws AuthenticationException {
                // TODO Auto-generated method stub
                return authenticationManager.getOrBuild().authenticate(authentication);
            }
        });
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.inMemory()
            .withClient(applicationName)
            .authorizedGrantTypes("password", "authorization_code", "refresh_token")
            .authorities("ROLE_USER")
            .scopes("write")
            .resourceIds(applicationName)
            .secret("123456");
    }
}

WebSecurityConfiguration.java

WebSecurityConfiguration.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.userdetails.User;

import com.boot.myproj.repository.AccountRepository;

class WebSecurityConfiguration extends GlobalAuthenticationConfigurerAdapter {

    @Autowired
    AccountRepository userRepository;

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }

    @Bean
    UserDetailsService userDetailsService() {
        return (username) -> userRepository
                .findByUsername(username)
                .map(a -> new User(a.username, a.password, true, true, true, true,
                        AuthorityUtils.createAuthorityList("USER", "write")))
                .orElseThrow(
                        () -> new UsernameNotFoundException("could not find the user '"
                                + username + "'"));
    }
}

Account.java

Account.java

import javax.persistence.*;


import com.fasterxml.Hymanson.annotation.JsonIgnore;

@Entity
public class Account {

    @Id
    @GeneratedValue
    private Long id;

    public Long getId() {
        return id;
    }

    public String getPassword() {
        return password;
    }

    public String getUsername() {
        return username;
    }

    @JsonIgnore
    public String password;
    public String username;

    public Account(String name, String password) {
        this.username = name;
        this.password = password;
    }

    Account() { // jpa only
    }
}

AccountRepository.java

AccountRepository.java

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;

import com.boot.myproj.config.security.Account;

public interface AccountRepository extends JpaRepository<Account, String>{
    public Optional<Account> findByUsername(String username);
}

App.java

App.java

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

import com.boot.cut_costs.config.security.Account;
import com.boot.cut_costs.repository.AccountRepository;

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }

    @Bean
    CommandLineRunner init(AccountRepository accountRepository) {
        return (arg) -> {
            accountRepository.save(new Account("username", "password"));
        };
    }
}

回答by Pratik Shah

Add @Configurationto WebSecurityConfigurationclass. So that your bean will get injected in spring context.

Add @Configurationto WebSecurityConfigurationclass. So that your bean will get injected in spring context.

p.s. What you are trying to do here with OAuth2 password grantwill not return an auth code, instead it'll directly return you a accessToken.

p.s. What you are trying to do here with OAuth2 password grantwill not return an auth code, instead it'll directly return you a accessToken.