spring-attic / spring-security-oauth

Support for adding OAuth1(a) and OAuth2 features (consumer and provider) for Spring web applications.
http://github.com/spring-projects/spring-security-oauth
Apache License 2.0
4.7k stars 4.04k forks source link

Getting o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null ..issue while accessing the rest resource #1088

Open Rabindra1980 opened 7 years ago

Rabindra1980 commented 7 years ago

objective of my application-Securing REST API with Oauth2 Technolgies used- spring boot 1.5.3 spring security spring oauth spring jdbc Mysql database List of important classes that i have implemented. Authorization serverconfig class


package com.rabindra.microservice.simpleDrCloudauthserverpartI.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 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.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

@Configuration @EnableAuthorizationServer public class OAuth2Configuration extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager auth;

@Autowired
private DataSource dataSource;

//private BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

@Bean
public JdbcTokenStore tokenStore() {
    return new JdbcTokenStore(dataSource);
}

@Bean
protected AuthorizationCodeServices authorizationCodeServices() {
    return new JdbcAuthorizationCodeServices(dataSource);
}

/*@Override
public void configure(AuthorizationServerSecurityConfigurer security)
        throws Exception {
    security.passwordEncoder(passwordEncoder);
}*/

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
        throws Exception {
    endpoints.authorizationCodeServices(authorizationCodeServices())
            .authenticationManager(auth).tokenStore(tokenStore()).approvalStoreDisabled();

}

/*
 * Setup the client application which attempts to get access to user's
 * account after user permission.
 */
@Override
public void configure(ClientDetailsServiceConfigurer clients)
        throws Exception {

    clients.jdbc(dataSource);
            //.passwordEncoder(passwordEncoder);
            //below section is hardcoded

            /*.withClient("client")
            .authorizedGrantTypes("authorization_code", "client_credentials", 
                    "refresh_token","password", "implicit")
            .authorities("ROLE_CLIENT")
            .resourceIds("apis")
            .scopes("read")
            .secret("secret")
            .accessTokenValiditySeconds(300);*/

}

/**
 * Configure the {@link AuthenticationManagerBuilder} with initial
 * configuration to setup users.
 * 
 * @author Rabindra
 *
 */
@Configuration
@Order(Ordered.LOWEST_PRECEDENCE - 20)
protected static class AuthenticationManagerConfiguration extends
        GlobalAuthenticationConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Override
    public void init(AuthenticationManagerBuilder auth) throws Exception {
        // @formatter:off
                    auth.jdbcAuthentication().dataSource(dataSource)

                    .usersByUsernameQuery("select * from users where username=?")
                    .authoritiesByUsernameQuery("select username,authority from authorities where username=?");

    }
}

}


Resource server configuration class package com.rabindra.microservice.simpleDrCloudauthserverpartI.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import org.springframework.security.oauth2.provider.token.TokenStore; @Configuration @EnableResourceServer

public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter{

@Autowired
private DataSource dataSource;
@Autowired
private TokenStore tokenStore;

@Override
public void configure(ResourceServerSecurityConfigurer resources)
        throws Exception {
    resources.tokenStore(tokenStore);
}

@Override 
public void configure(HttpSecurity http) throws Exception {
     // @formatter:off

    http.authorizeRequests().anyRequest().authenticated();  
}

/*Add resource-server specific properties (like a resource id). The defaults should work for many applications, but you might want to change at least the resource id.*/

/ @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.resourceId("apis"); }/ } Note these two class are in one spring boot application Api controller package com.rabindra.microservice.simpleDrCloudauthserverpartI.api;

import java.security.Principal;

import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;

@RestController @RequestMapping("/") public class AuthUserController {

/**
 * Return the principal identifying the logged in user
 * @param user
 * @return
 */
@RequestMapping("/user")
public Principal getCurrentLoggedInUser(Principal user) {
    System.out.println("inside AuthUserController user "+user.getName());
    return user;
}

} application .yml for authorization server server: port: 9090 contextPath: /authserv #The auth server will run on this port and with auth contextpath like http://localhost:9090/auth .you can give ny name for the contextpath

spring: datasource: url: jdbc:mysql://localhost:3306/auth username: root password: root driver-class-name: com.mysql.jdbc.Driver

jpa:

database-platform: org.hibernate.dialect.MySQLDialect
show-sql: false
hibernate:
  ddl-auto: update

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0
<groupId>com.rabindra.simple-DrCloud-auth-serverpartI</groupId>
<artifactId>simple-DrCloud-auth-serverpartI</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>simple-DrCloud-auth-serverpartI</name>
<description>Demo project for Spring Boot simple-DrCloud-auth-serverpartI</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
    <spring-cloud.version>Dalston.SR1</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>


another spring boot application where i have one resource which has to be accessd. Please find the class as below for this application

controller- package com.rabindra.microservice.simpleDrCloudpartI.api.controller;

import java.time.LocalTime; import java.time.format.DateTimeFormatter;

import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;

@RestController public class TimeRestController { // Only users with the role ROLE_ADMIN or ROLE_EXTERNAL_USER are allowed to retrieve the time @RequestMapping(value = "/time")

public String currentTime() {
    return LocalTime.now().format(DateTimeFormatter.ISO_LOCAL_TIME);
}

}


security config class


package com.rabindra.microservice.simpleDrCloudpartI.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; @Configuration @EnableWebSecurity @EnableOAuth2Sso public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private DataSource dataSource;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) 
  throws Exception {
    auth.jdbcAuthentication().dataSource(dataSource).usersByUsernameQuery("select * from users where username=?")
    .authoritiesByUsernameQuery("select username,authority from authorities where username=?") ;

}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.authorizeRequests().anyRequest().fullyAuthenticated().and().httpBasic();
    http.csrf().disable();

}

}


application.yml

we commented it as we set the credential in adapter class using inmmemory

security:

user:

password: test123

spring: datasource: url: jdbc:mysql://localhost:3306/auth username: root password: root driver-class-name: com.mysql.jdbc.Driver

jpa:

database-platform: org.hibernate.dialect.MySQLDialect
show-sql: false
hibernate:
  ddl-auto: update

Configure the Authorization Server and User Info Resource Server details

security: oauth2: client: accessTokenUri: http://localhost:9090/authserv/oauth/token userAuthorizationUri: http://localhost:9090/authserv/oauth/authorize clientId: myauthserver clientSecret: secret scope: read,write auto-approve-scopes: '.*'

resource:
  userInfoUri: http://localhost:9090/authserv/user

----------------  

pom.xml for this application

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0
<groupId>com.rabindra.simple-DrCloud-partI</groupId>
<artifactId>simple-DrCloud-partI</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>

<name>simple-DrCloud-partI</name>
<description>Demo project for Spring Boot simple-DrCloud-partI</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
     <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-oauth2</artifactId>
    </dependency> 
    <!-- <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
    </dependency> -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
</dependencies>

<build>

    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>

</build>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Camden.SR7</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>


while running the url , http://localhost:8080/time, in chrome it is giving as below error 2017-06-17 11:16:21.336 INFO 7668 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet' 2017-06-17 11:16:21.336 INFO 7668 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2017-06-17 11:16:21.378 INFO 7668 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 42 ms 2017-06-17 11:17:02.834 WARN 7668 --- [nio-8080-exec-5] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null 2017-06-17 11:17:03.142 WARN 7668 --- [nio-8080-exec-6] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null 2017-06-17 11:21:22.462 WARN 7668 --- [nio-8080-exec-3] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null 2017-06-17 11:21:22.518 WARN 7668 --- [nio-8080-exec-4] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null 2017-06-17 11:21:29.564 WARN 7668 --- [nio-8080-exec-8] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null 2017-06-17 11:21:29.670 WARN 7668 --- [io-8080-exec-10] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null 2017-06-17 11:21:36.450 WARN 7668 --- [nio-8080-exec-3] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.HttpClientErrorException, 401 null

--- I have created table in mysql table ,schema as auth create table users ( username varchar(256), password varchar(256), enabled boolean );

create table authorities ( username varchar(256), authority varchar(256) );

create table oauth_client_details ( client_id VARCHAR(256) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256) );

create table oauth_client_token ( token_id VARCHAR(256), token LONGVARBINARY, authentication_id VARCHAR(256), user_name VARCHAR(256), client_id VARCHAR(256) );

create table oauth_access_token ( token_id VARCHAR(256), token LONGVARBINARY, authentication_id VARCHAR(256), user_name VARCHAR(256), client_id VARCHAR(256), authentication LONGVARBINARY, refresh_token VARCHAR(256) );

create table oauth_refresh_token ( token_id VARCHAR(256), token LONGVARBINARY, authentication LONGVARBINARY );

create table oauth_code ( code VARCHAR(256), authentication LONGVARBINARY );


There is no data in oauth_refresh_token table.

Could you please help me to resolve this issue. Is ther anything missed to implement.

Regards, Rabindra

Rabindra1980 commented 7 years ago

Hi All, Can anybody guide me to resolve this issue.

Rabindra1980 commented 7 years ago

Hi @dsyer , Could you please help me out to sort this issue.

Thanks, Rabindra

dsyer commented 7 years ago

It's not really an issue specifically about this project. It's more of a usage question about Spring Boot. Your best option is to create a sample app and put the code in github, then ask your question on stack overflow. I recommend you learn how to format code snippets in markdown as well. Good luck.

Rabindra1980 commented 7 years ago

Thanks for your early response. I will put the code in github.

junneyang commented 7 years ago

any solution? already many guys have this problem, but still no response

dsyer commented 7 years ago

I responded on Jun 19 (nearly 3 months ago). It's pretty hard to tell, but it seems like a usage issue to me (hence not really for discussion here), but we can leave this open until we get some more data.

sanskritiagarwal commented 5 years ago

userInfoUri must be wrong .

I corrected userInfoUri and it worked for me