首页 > 解决方案 > TokenEndpoint : Handling error: InvalidGrantException, Bad credentials with right credentials

问题描述

I am currently working on my own project which should have its own oauth authentication server using spring-boot and spring-oauth.

I get

TokenEndpoint : Handling error: InvalidGrantException, Bad credentials even the name and password are right.

I save my users in mysql and encode the passwords with bCrypt. Below are my configurations

I tried:

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

        @Autowired
        private AuthenticationManager authenticationManager;

        @Autowired
        private PasswordEncoder passwordEncoder;

        /**
         * Setting up the endpointsconfigurer authentication manager.
         * The AuthorizationServerEndpointsConfigurer defines the authorization and token endpoints and the token services.
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager);
            endpoints.tokenStore(getTokenStore());
        }

        @Bean
        public TokenStore getTokenStore(){
            return new InMemoryTokenStore();
        }

        /**
         * Setting up the clients with a clientId, a clientSecret, a scope, the grant types and the authorities.
         * @param clients
         * @throws Exception
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients
                    .inMemory()
                    .withClient("my-trusted-client")
                    .authorizedGrantTypes("password")
                    .authorities("ROLE_USER").scopes("read","write","trust")
                    .resourceIds("oauth2-resource").accessTokenValiditySeconds(5000).secret(passwordEncoder.encode("secret"));
        }

        /**
         * We here defines the security constraints on the token endpoint.
         * We set it up to isAuthenticated, which returns true if the user is not anonymous
         * @param security the AuthorizationServerSecurityConfigurer.
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.checkTokenAccess("isAuthenticated()");
        }

    }

    public class CustomUserDetails implements UserDetails {

        private String password;
        private String username;
        private Collection<? extends GrantedAuthority> authorities;

        public CustomUserDetails(User user) {
            this.username = user.getUsername();
            this.password = user.getPassword();
            this.authorities = translate(user.getRole());
        }


        private Collection<? extends GrantedAuthority> translate(Role role) {
            List<GrantedAuthority> authorities = new ArrayList<>();
            String roleName = role.getRole().toUpperCase();
            authorities.add(new SimpleGrantedAuthority(roleName));
            return authorities;
        }

        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return authorities;
        }

        @Override
        public String getPassword() {
            return password;
        }

        @Override
        public String getUsername() {
            return username;
        }

        @Override
        public boolean isAccountNonExpired() {
            return true;
        }

        @Override
        public boolean isAccountNonLocked() {
            return true;
        }

        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }

        @Override
        public boolean isEnabled() {
            return true;
        }

    }

        @Configuration
        @EnableResourceServer
        public class ResourceServerConfig extends WebSecurityConfigurerAdapter {

            @Override
            public void configure(HttpSecurity http) throws Exception {
                http
                        .authorizeRequests()
                        .antMatchers("/","/home","/register","/login").permitAll()
                        .antMatchers("/private/**").authenticated()
                        .antMatchers("/post").authenticated()
                        .antMatchers("/post/postComment").authenticated()
                        .antMatchers(HttpMethod.DELETE , "/post/**").hasAuthority("ROLE_ADMIN");
            }

            @Override
            @Bean
            public AuthenticationManager authenticationManagerBean() throws Exception {
                return super.authenticationManagerBean();
            }
        }

    @SpringBootApplication
    @EnableAuthorizationServer
    public class BackendApplication {

        @Autowired
        private PasswordEncoder passwordEncoder;

        public static void main(String[] args) {
            SpringApplication.run(BackendApplication.class, args);
        }
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }

        /**
         * Password grants are switched on by injecting an AuthenticationManager.
         * Here, we setup the builder so that the userDetailsService is the one we coded.
         * @param builder
         * @param repository
         * @throws Exception
         */
        @Autowired
        public void authenticationManager(AuthenticationManagerBuilder builder, UserRepository repository, UserService userService) throws Exception {
            if (repository.count()==0) {
                userService.save(new User("admin", "{noop}adminPassword", new Role("ROLE_USER")));
            }
            builder.userDetailsService(userDetailsService(repository)).passwordEncoder(passwordEncoder);
        }

        /**
         * We return an istance of our CustomUserDetails.
         * @param repository
         * @return
         */
        private UserDetailsService userDetailsService(final UserRepository repository) {
            return username -> new CustomUserDetails(repository.findByUsername(username));
        }
    }

Warning Message: 2019-07-24 15:46:42.341 WARN 73936 --- [nio-8088-exec-4] o.s.s.o.provider.endpoint.TokenEndpoint : Handling error: InvalidGrantException, Bad credentials

URL: http://localhost:8088/oauth/token The Request is url-www-form-encoded with the Parameters:

and "Basic Auth" with Username "my-trusted-client" and Password "secret".

标签: springspring-securityoauth-2.0

解决方案


用于 .secret("{bcrypt}" + passwordEncoder.encode("secret"))my-trusted-client 和.secret("{bcrypt}" + passwordEncoder.encode("adminPassword"))admin。并且:检查 BcryptPasswordEncoder 是否在调试会话中使用。


推荐阅读