Oauth2 bad Anmeldeinformationen Spring Boot

Bin ich immer die Fehlermeldung:

"error": "invalid_grant",
"error_description": "Bad credentials"

Hier ist die Anforderung, die ich machen:

POST /oauth/token HTTP/1.1
Host: localhost:8443
Authorization: Basic bW9iaWxlOg==
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

username=admin&password=pass&client_id=mobile&grant_type=password&client_secret=

Mein code ist von hier: https://github.com/juleswhite/mobilecloud-14/tree/master/examples/9-VideoServiceWithOauth2

Hier ist der code:
Application.java:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import com.capstone.auth.OAuth2SecurityConfiguration;
import com.google.common.io.BaseEncoding;

@Configuration
@EnableAutoConfiguration
@ComponentScan
@EnableWebMvc
@Import(OAuth2SecurityConfiguration.class)
public class Application extends RepositoryRestMvcConfiguration{

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);

    }

}

ClientAndUserDetailsService.java

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService;

/**
 * A class that combines a UserDetailsService and ClientDetailsService
 * into a single object.
 * 
 * @author jules
 *
 */
public class ClientAndUserDetailsService implements UserDetailsService,
        ClientDetailsService {

    private final ClientDetailsService clients_;

    private final UserDetailsService users_;

    private final ClientDetailsUserDetailsService clientDetailsWrapper_;

    public ClientAndUserDetailsService(ClientDetailsService clients,
            UserDetailsService users) {
        super();
        clients_ = clients;
        users_ = users;
        clientDetailsWrapper_ = new ClientDetailsUserDetailsService(clients_);
    }

    @Override
    public ClientDetails loadClientByClientId(String clientId)
            throws ClientRegistrationException {
        return clients_.loadClientByClientId(clientId);
    }

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        UserDetails user = null;
        try{
            user = users_.loadUserByUsername(username);
        }catch(UsernameNotFoundException e){
            user = clientDetailsWrapper_.loadUserByUsername(username);
        }
        return user;
    }

}

OAuth2SecurityConfiguration.java

@Configuration
public class OAuth2SecurityConfiguration {
    //This first section of the configuration just makes sure that Spring
    //Security picks
    //up the UserDetailsService that we create below.
    @Configuration
    @EnableWebSecurity
    protected static class WebSecurityConfiguration extends
            WebSecurityConfigurerAdapter {

        @Autowired
        private UserDetailsService userDetailsService;

        @Autowired
        protected void registerAuthentication(
                final AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService);
        }
    }

    /**
     * This method is used to configure who is allowed to access which parts of
     * our resource server (i.e. the "/video" endpoint)
     */
    @Configuration
    @EnableResourceServer
    protected static class ResourceServer extends
            ResourceServerConfigurerAdapter {

        //This method configures the OAuth scopes required by clients to access
        //all of the paths in the video service.
        @Override
        public void configure(HttpSecurity http) throws Exception {

            http.csrf().disable();

            http.authorizeRequests().antMatchers("/oauth/token").anonymous();

            //If you were going to reuse this class in another
            //application, this is one of the key sections that you
            //would want to change

            //Require all GET requests to have client "read" scope
            http.authorizeRequests().antMatchers(HttpMethod.GET, "/**")
                    .access("#oauth2.hasScope('read')");

            //Require all other requests to have "write" scope
            http.authorizeRequests().antMatchers("/**")
                    .access("#oauth2.hasScope('write')");
        }

    }

    /**
     * This class is used to configure how our authorization server (the
     * "/oauth/token" endpoint) validates client credentials.
     */
    @Configuration
    @EnableAuthorizationServer
    @Order(Ordered.LOWEST_PRECEDENCE - 100)
    protected static class OAuth2Config extends
            AuthorizationServerConfigurerAdapter {

        //Delegate the processing of Authentication requests to the framework
        @Autowired
        private AuthenticationManager authenticationManager;

        //A data structure used to store both a ClientDetailsService and a
        //UserDetailsService
        private ClientAndUserDetailsService combinedService_;

        /**
         * 
         * This constructor is used to setup the clients and users that will be
         * able to login to the system. This is a VERY insecure setup that is
         * using hard-coded lists of clients /users /passwords and should
         * never be used for anything other than local testing on a machine that
         * is not accessible via the Internet. Even if you use this code for
         * testing, at the bare minimum, you should consider changing the
         * passwords listed below and updating the VideoSvcClientApiTest.
         * 
         * @param auth
         * @throws Exception
         */
        public OAuth2Config() throws Exception {

            //If you were going to reuse this class in another
            //application, this is one of the key sections that you
            //would want to change

            //Create a service that has the credentials for all our clients
            ClientDetailsService csvc = new InMemoryClientDetailsServiceBuilder()
                    //Create a client that has "read" and "write" access to the
                    //video service
                    .withClient("mobile")
                    .authorizedGrantTypes("password")
                    .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                    .scopes("read", "write")
                    .resourceIds("test")
                    .and()
                    //Create a second client that only has "read" access to the
                    //video service
                    .withClient("mobileReader")
                    .authorizedGrantTypes("password")
                    .authorities("ROLE_CLIENT").scopes("read")
                    .resourceIds("test").accessTokenValiditySeconds(3600)
                    .and().build();

            //Create a series of hard-coded users.
            UserDetailsService svc = new InMemoryUserDetailsManager(
                    Arrays.asList(
                            User.create("admin", "pass", "ADMIN", "USER"),
                            User.create("user0", "pass", "USER"),
                            User.create("username", "password", "USER")));

            //Since clients have to use BASIC authentication with the client's
            //id/secret,
            //when sending a request for a password grant, we make each client
            //a user
            //as well. When the BASIC authentication information is pulled from
            //the
            //request, this combined UserDetailsService will authenticate that
            //the
            //client is a valid "user".
            combinedService_ = new ClientAndUserDetailsService(csvc, svc);
        }

        /**
         * Return the list of trusted client information to anyone who asks for
         * it.
         */
        @Bean
        public ClientDetailsService clientDetailsService() throws Exception {
            return combinedService_;
        }

        /**
         * Return all of our user information to anyone in the framework who
         * requests it.
         */
        @Bean
        public UserDetailsService userDetailsService() {
            return combinedService_;
        }

        /**
         * This method tells our AuthorizationServerConfigurerAdapter to use the
         * delegated AuthenticationManager to process authentication requests.
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {
            endpoints.authenticationManager(authenticationManager);
        }

        /**
         * This method tells the AuthorizationServerConfigurerAdapter to use our
         * self-defined client details service to authenticate clients with.
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer clients)
                throws Exception {
            clients.withClientDetails(clientDetailsService());
        }

    }

    //This version uses the Tomcat web container and configures it to
    //support HTTPS. The code below performs the configuration of Tomcat
    //for HTTPS. Each web container has a different API for configuring
    //HTTPS.
    //
    //The app now requires that you pass the location of the keystore and
    //the password for your private key that you would like to setup HTTPS
    //with. In Eclipse, you can set these options by going to:
    //1. Run->Run Configurations
    //2. Under Java Applications, select your run configuration for this app
    //3. Open the Arguments tab
    //4. In VM Arguments, provide the following information to use the
    //default keystore provided with the sample code:
    //
    //-Dkeystore.file=src/main/resources/private/keystore
    //-Dkeystore.pass=changeit
    //
    //5. Note, this keystore is highly insecure! If you want more securtiy, you
    //should obtain a real SSL certificate:
    //
    //http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html
    //
    @Bean
    EmbeddedServletContainerCustomizer containerCustomizer(
            @Value("${keystore.file:src/main/resources/private/keystore}") String keystoreFile,
            @Value("${keystore.pass:changeit}") final String keystorePass)
            throws Exception {

        //If you were going to reuse this class in another
        //application, this is one of the key sections that you
        //would want to change

        final String absoluteKeystoreFile = new File(keystoreFile)
                .getAbsolutePath();

        return new EmbeddedServletContainerCustomizer() {

            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
                tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() {
                    @Override
                    public void customize(Connector connector) {
                        connector.setPort(8443);
                        connector.setSecure(true);
                        connector.setScheme("https");

                        Http11NioProtocol proto = (Http11NioProtocol) connector
                                .getProtocolHandler();
                        proto.setSSLEnabled(true);
                        proto.setKeystoreFile(absoluteKeystoreFile);
                        proto.setKeystorePass(keystorePass);
                        proto.setKeystoreType("JKS");
                        proto.setKeyAlias("tomcat");
                    }
                });

            }
        };
    }

}

Vielen Dank für Ihre Aufmerksamkeit und Zeit!

Diese ClientAndUserDetailsService sieht aus wie ein anti-pattern, und ich habe gesehen, dass es ziemlich viel in letzter Zeit. Haben Sie Fragen zu dieser vor, sind Sie nur kopieren von code aus dem gleichen Ort (wo)?
Nein, ich habe nicht gefragt! Aber Ι schweigen von der Quelle des Codes. Es ist falsch?
OK, vielen Dank. Ich wusste nicht, ob das war Ihr code oder die Quelle von allen anderen komisch authentication manager.
Das sieht hinky zu: http.authorizeRequests().antMatchers("/oauth/token").anonymous(). Ich würde vielleicht empfehlen abschreiben aus der Feder OAuth-tests (Beispiel) anstatt von jules, wenn Sie wollen etwas, das Sie kopieren und einfügen können.
Ok danke, werde ich mit der Feder OAuth-tests (Beispiel)!

InformationsquelleAutor KostasC | 2014-10-29

Schreibe einen Kommentar