Java SpringBoot Keycloak Rest Api Jwt Auth Postman Didn't find publicKey for kid - spring-boot

I'm creating a microservices project. The idea is that a reactjs application get a token from Keycloack and send this jwt token to a springboot rest api in the backend. I'm using docker compose to manage the containers in my local machine.
With Postman I get the token form keycloack, but when I use this token as bearer token to call the rest api with Postman,I'm getting 401.
I configured keycloak, but in the backend, in the logs I found the error:
2021-02-28 10:37:14.134 ERROR 1 --- [nio-8081-exec-4] o.k.a.rotation.AdapterTokenVerifier : Didn't find publicKey for kid: fbb8f5e8-2341-4d1d-82d8-6efe736c90c5
In the logs of keycloak I see:
10:22:19,590 INFO [org.keycloak.keys.DefaultKeyManager] (default task-4) No keys found for realm=master and algorithm=HS256 for use=SIG. Generating keys.
10:22:25,423 INFO [org.keycloak.keys.DefaultKeyManager] (default task-5) No keys found for realm=master and algorithm=RS256 for use=SIG. Generating keys.
10:23:18,927 WARN [org.keycloak.events] (default task-4) type=LOGIN_ERROR, realmId=todo-realm, clientId=todo-app, userId=null, ipAddress=172.29.0.1, error=invalid_client_credentials, grant_type=password
In the Springboot application.properties i put these properties:
keycloak.realm = todo-realm
keycloak.auth-server-url = http://keycloak:8080/auth
keycloak.ssl-required = external
keycloak.resource = todo-app
keycloak.credentials.secret = the secret of the client in keycloack
keycloak.use-resource-role-mappings = true
keycloak.bearer-only = true
In the keycloak I created a realm called: todo-realm. I created a client called todo-app and two roles:
app-user
app-admin
I creted a user, called user1, with the role: app-user.
In my springboot app, the pom is:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.cammisa.filippo.todolist</groupId>
<artifactId>todo-list</artifactId>
<version>0.0.3-SNAPSHOT</version>
<name>todo-list</name>
<description>Demo project with Spring Boot for A To do List</description>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<docker.image.prefix>fcammisa</docker.image.prefix>
<docker-image-name>todo-list-backend</docker-image-name>
<keycloak.version>12.0.3</keycloak.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</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.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- link: http://localhost:8080/api/swagger-ui/index.html?configUrl=/api/v3/api-docs/swagger-config -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.5.2</version>
</dependency>
<!-- restdocs -->
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-mockmvc</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.restdocs</groupId>
<artifactId>spring-restdocs-restassured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.cloudyrock.mongock</groupId>
<artifactId>mongock-spring-v5</artifactId>
</dependency>
<dependency>
<groupId>com.github.cloudyrock.mongock</groupId>
<artifactId>mongodb-springdata-v3-driver</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.github.cloudyrock.mongock</groupId>
<artifactId>mongock-bom</artifactId>
<version>4.1.17</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>12.0.3</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>
</project>
I created a class to configure keycloack:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/api/todo/todos").hasAnyRole("user")
/*.antMatchers("/api/todo/insert").hasAnyRole("user")
.antMatchers("/api/todo/update").hasAnyRole("user")
.antMatchers("/api/todo/get/{id}").hasAnyRole("user","admin")
.antMatchers("/api/todo/todos").hasAnyRole("user")
.antMatchers("/api/todos/{pageNo}/{pageSize}").hasAnyRole("user")
.antMatchers("/api/todo/delete").hasAnyRole("user")
.antMatchers("/api/todo/delete/{id}").hasAnyRole("user")*/
.anyRequest()
.permitAll();
http.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
}
This is my docker compose file:
version: "3.7"
services:
tododb-service:
image: mongo:latest
container_name: tododb
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: todo
MONGO_INITDB_ROLE: userAdminAnyDatabase
ports:
- 27017:27017
todo-app:
build:
context: .
container_name: todo-app
ports:
- 8081:8081
keycloak-db:
image: postgres
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
keycloak:
image: jboss/keycloak:12.0.3
volumes:
- ./imports:/opt/jboss/keycloak/imports
#command:
# - "-b 0.0.0.0 -Dkeycloak.import=/opt/jboss/keycloak/imports/realm-export.json"
environment:
DB_VENDOR: POSTGRES
DB_ADDR: keycloak-db
DB_DATABASE: keycloak
DB_USER: keycloak
DB_SCHEMA: public
DB_PASSWORD: password
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: password
# Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
#JDBC_PARAMS: "ssl=true"
ports:
- 8080:8080
- 9990:9990
depends_on:
- keycloak-db
Can someone help me to get the result of the rest api using Postaman of my rest api ?
Thank you so much.

Related

Unable to Access Spring Boot Actuator Endpoints

I try to use actuator endpoints in spring boot. The application runs smoothly. My pom file is given below:
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.luv2code.springboot</groupId>
<artifactId>thymeleafdemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>thymeleafdemo</name>
<description>Ab Jove principium</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<!-- umumi bağımlılıklar -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>net.lingala.zip4j</groupId>
<artifactId>zip4j</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</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.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</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-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Here is the content of the application.properties file:
spring.datasource.url=DATABASE_URL
spring.datasource.username=USERNAME
spring.datasource.password=PASSWORD
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.jpa.database-platform=org.hibernate.dialect.Oracle12cDialect
# Spring Data JPA properties
spring.data.jpa.repository.packages=com.yok.springboot.thymeleafdemo.dao
spring.data.jpa.entity.packages-to-scan=com.yok.springboot.thymeleafdemo.entity
spring.jpa.hibernate.use-new-id-generator-mappings=false
spring.jpa.hibernate.ddl-auto=create
#
# JDBC properties
#
app.datasource.jdbc-url=DATABASE_URL
app.datasource.username=USERNAME
app.datasource.password=PASSWORD
#
# Hikari properties
spring.datasource.hikari.maximumPoolSize=10
spring.datasource.hikari.idleTimeout=2000
spring.datasource.hikari.poolName=SpringBootJPAHikariCP
spring.datasource.hikari.maxLifetime=20000
spring.datasource.hikari.connectionTimeout=30000
# Actuator properties
# expose all endpoints:
management.endpoints.web.exposure.include=*
management.endpoints.beans.enabled=true
management.endpoints.web.exposure.include=info,env
management.endpoint.env.enabled=true
management.endpoint.info.enabled=true
management.endpoints.enabled-by-default=true
This is the start of my Spring Boot Application:
package com.yok.springboot.thymeleafdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class ThymeleafdemoApplication {
public static void main(String[] args) {
SpringApplication.run(ThymeleafdemoApplication.class, args);
}
}
Whenever I try to connect /health,/Info or /metrics endpoint by typing http://localhost:8080/health, the HTTP request transfers to http://localhost:8080/showMyLoginPage. I cannot reach endpoint. How can I solve this? Thanks in advance.
Edit -1
Mr. Fatih demands me to observe the result "http://localhost:8080/actuator" and this picture reveals: the picture
Here is the console output of the application:
https://drive.google.com/file/d/1zYP1qe-Ohbcan93ZO6rqjxX9LqlGiIIg/view?usp=sharing
Edit-2
The problem is partly solved. The actuators are available after the login of the application. But the problem is, after the login page, the homepage appears. All actuators are working, however, whenever I hit http://localhost:8080/actuator/health URL, {"status":"DOWN"} appears at the screen. Here is the console output taken during this operation:
reached urls:
http://localhost:8080/showMyLoginPage
http://localhost:8080/students/list/page/1
http://localhost:8080/actuator/health
http://localhost:8080/actuator/heapdump
http://localhost:8080/actuator/env
console output: (exception has thrown)
java.lang.IllegalArgumentException: dataSource or dataSourceClassName
or jdbcUrl is required. at
com.zaxxer.hikari.HikariConfig.validate(HikariConfig.java:1029)
~[HikariCP-4.0.3.jar:na] at
com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:109)
~[HikariCP-4.0.3.jar:na] at
org.springframework.jdbc.datasource.DataSourceUtils.fetchConnection(DataSourceUtils.java:159)
~[spring-jdbc-5.3.22.jar:5.3.22] at
org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:117)
~[spring-jdbc-5.3.22.jar:5.3.22] at
org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
~[spring-jdbc-5.3.22.jar:5.3.22] at
org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:330)
~[spring-jdbc-5.3.22.jar:5.3.22] at
org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator.getProduct(DataSourceHealthIndicator.java:122)
~[spring-boot-actuator-2.7.3.jar:2.7.3] at
org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator.doDataSourceHealthCheck(DataSourceHealthIndicator.java:105)
~[spring-boot-actuator-2.7.3.jar:2.7.3] at
org.springframework.boot.actuate.jdbc.DataSourceHealthIndicator.doHealthCheck(DataSourceHealthIndicator.java:100)
~[spring-boot-actuator-2.7.3.jar:2.7.3]
Edit-3
Mr Fatih pointed out some of the changes at the WebSecurityConfiguration. I have changed the code and I am getting this error:
java.lang.IllegalStateException: permitAll only works with either
HttpSecurity.authorizeRequests() or
HttpSecurity.authorizeHttpRequests(). Please define one or the other
but not both.
Here is the change I've made:
/*
* import section have omitted for brevity
*/
#Configuration
#EnableWebSecurity
public class DemoSecurityConfig {
/*
* other codes have omitted for brevity
*/
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authz) -> authz.antMatchers("/actuator/**").permitAll().anyRequest().authenticated());
http.authorizeRequests(
configurer -> configurer.antMatchers("/**").hasRole("ADMIN").antMatchers("/**").hasRole("USER"))
.formLogin(configurer -> configurer.loginPage("/showMyLoginPage")
.loginProcessingUrl("/authenticateTheUser").permitAll())
.logout(configurer -> configurer.permitAll())
.exceptionHandling(configurer -> configurer.accessDeniedPage("/access-denied"));
return http.build();
}
}
Here is the console output: https://drive.google.com/file/d/1CtjRBHXVRqirZ0Vt_3FEhx_N9oEwyfFZ/view
You are using the spring-security package for application security. So when you want to access your /actuator endpoints, you need to log in first. If you want to access your /actuator endpoints without logging in, you must configure a security configuration. With the following configuration, you can exclude all endpoints starting with /actuator from security.
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/actuator/**").permitAll().anyRequest().authenticated();
}
}
Since WebSecurityConfigurerAdapter has been deprecated, you can do this as well.
#Configuration
public class SecurityConfiguration {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(autz -> autz
.mvcMatchers("/actuator/**").permitAll()
.anyRequest().authenticated()
);
return http.build();
}
}
** is a wildcard definition and allows you to access this endpoint without logging in, regardless of what comes after the actuator part.
Please Consider using a version for your dependency as far as i remember 1.9.5 RELEASE or 1.9.5 might help in this context , i had the same issue a year ago.

/graphql endpoint returns 404 error during integration test of spring cloud app but not by running the app with mvn spring-boot:run

spring-cloud.version:Greenwich.SR2, spring boot 2.1.7
mvn spring-boot:run makes the endpoint /graphql accessible but not mvn clean verify
I included graphql-java-servlet, javax.servlet-api, graphql-spring-boot-starter-test and graphql-spring-boot-starter, but it stills does not work
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<!-- graphql -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java</artifactId>
<version>13.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-extended-scalars</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>java-dataloader</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.10.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>5.0.2</version>
</dependency>
<!-- Apache CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>spring-mock-mvc</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
Here is my simple test which returns 404:
#Test
public void persons() throws Exception {
Map<String, Object> variables = new HashMap<String, Object>();
GraphQLRequest request = new GraphQLRequest(
"query persons{persons"
+ "{"
+ " id"
+ "}}",
variables,
null);
// SUT
given()
.contentType(ContentType.JSON)
.body(request)
.get(GRAPHQL_PATH)
.then()
.log().body()
.statusCode(200);
}
The test class is annotated with :
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#TestPropertySource(locations = "classpath:bootstrap-test.yml")
Here is my bootstrap.yml:
spring:
application:
name: crm-service
cloud:
config:
uri: http://localhost:8081
fail-fast: false
password: configPassword
username: user
main:
allow-bean-definition-overriding: true #i dont remember why but i think there is a bug with spring cloud and OAuth2ClientContext
acls-management:
permissions-config-path: permissions-config.json
acl-rules-path: acl-rules.json
eureka:
client:
register-with-eureka: false
fetch-registry: false
graphql:
servlet:
mapping: /graphql
enabled: true

Spring Security + AAD: invalid_token_response follow-up with latest available spring-boot version (2.1.2)

I am facing the same issue as posted in the question Spring Security + AAD: invalid_token_response
I did try 2.1.0, it didn't help.
I am currently using Spring-boot 2.1.2, spring-security-oauth2-client 5.1.3 and i am still getting the same error
I am sharing my pom.xml
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>perdict</groupId>
<artifactId>ouath2-client</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<name>ouath2-client</name>
<build>
<finalName>predictouath2client</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<java.version>1.8</java.version>
<azure.version>2.1.2</azure.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot-bom</artifactId>
<version>${azure.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
and the WebSecurityConfig looks like:-
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(oidcUserService);
}
the application.yaml looks like:-
spring:
security:
oauth2:
client:
registration:
azure:
client-id: xxxxxxxxxxxxxxxx
client-secret: xxxxxxxxxxxxxxxx
client-authentication-method: basic
authorization-grant-type: authorization_code
redirect-uri-template: '{baseUrl}/login/oauth2/code/{registrationId}'
scope: openid, https://graph.microsoft.com/user.read
client-name: Microsoft Azure
client-alias: azure
provider:
azure:
authorization-uri: https://login.microsoftonline.com/xxxxxxxxxxxxxx/oauth2/authorize
token-uri: https://login.microsoftonline.com/xxxxxxxxxxxxxx/oauth2/token
user-info-uri: https://login.microsoftonline.com/xxxxxxxxxxxxxx/openid/userinfo
jwk-set-uri: https://login.microsoftonline.com/xxxxxxxxxxxxxx/discovery/keys
user-name-attribute: name
azure:
activedirectory:
tenant-id: xxxxxxxxxxxxxx
active-directory-groups: Users
The detail error from the log files is
2019-02-08 05:48:28.612 DEBUG 99981 --- [nio-8010-exec-4] o.s.web.client.RestTemplate : Response 401 UNAUTHORIZED
2019-02-08 05:48:28.619 DEBUG 99981 --- [nio-8010-exec-4] .s.a.DefaultAuthenticationEventPublisher : No event was found for the exception org.springframework.security.oauth2.core.OAuth2AuthenticationException
2019-02-08 05:48:28.620 DEBUG 99981 --- [nio-8010-exec-4] .s.o.c.w.OAuth2LoginAuthenticationFilter : Authentication request failed: org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized
at org.springframework.security.oauth2.client.oidc.authentication.OidcAuthorizationCodeAuthenticationProvider.authenticate(OidcAuthorizationCodeAuthenticationProvider.java:143) ~[spring-security-oauth2-client-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:175) ~[spring-security-core-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter.attemptAuthentication(OAuth2LoginAuthenticationFilter.java:186) ~[spring-security-oauth2-client-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) ~[spring-security-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.3.RELEASE.jar:5.1.3.RELEASE]

Spring Cloud Config client not loading the value from config server

I am facing below issue while I try to run my Spring Cloud Config Client:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'DATABASE_NAME' in string value "${DATABASE_NAME}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204
My dependencies in POM.xml are as below:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config</artifactId>
<version>1.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
The bootstrap.yml
spring:
application:
name: my-config-client
cloud:
services:
registrationMethod: route
config:
enabled: true
uri: http://localhost:${config.port:8888}
The application.yml is as below:
# HTTP Server
server:
port: 2222
# Spring properties
spring:
profiles:
active: dev
#Disable HTTP Basic Authentication
security:
basic:
enabled: false
The class where I am trying to access the property is as below:
#RefreshScope
#Component
public class MyProperty {
#Value("${DATABASE_NAME}")
private String databaseName;
public String getDatabaseName() {
return databaseName;
}
}
My config server is running fine. When I use this url on browser http://localhost:8888/configserver/dev, It gives the below result:
{
"name":"configserver",
"profiles":[
"dev"
],
"label":"master",
"version":"c991526a93fb776e37e18e138c7485d894d6ea4f",
"propertySources":[
{
"name":"https://onestash.abc.com/scm/kapmol/microservice-config-repo.git/configserver.properties",
"source":{
"DATABASE_NAME":"ABC",
"CONVERT_USERS":"Y",
"LRDS_JNDI_NAME":"jdbc/tds_new"
}
}
]
}
I tried with all the posts who were facing this issue. But, it is not working for me. May be, I am missing some points. If anybody can provide help, it would be great.
Thanks
There are some breaking changes with the new spring cloud module read more: here.
Bootstrap, provided by spring-cloud-commons, is no longer enabled by
default. If your project requires it, it can be re-enabled by
properties or by a new starter.
To re-enable by properties set spring.cloud.bootstrap.enabled=true or spring.config.use-legacy-processing=true. These need to be set as
an environment variable, java system property or a command line
argument.
The other option is to include the new spring-cloud-starter-bootstrap
It worked for me by adding these dependencies:
<parent>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId>
<version>2020.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
I referred this post answered by 'spencergibb' and able to resolve the issue. I added "spring.config.name" in my bootstrap.yml file of client application and resolved the issue. Now, my bootstrap.yml look like as below:
spring:
application:
name: my-config-client
cloud:
services:
registrationMethod: route
config:
name: configserver
enabled: true
uri: http://localhost:${config.port:8888}

Spring MongoDB authorization failed

I have an issue with Spring MongoDB authorization process - attempts to retrieve data via REST API led to response:
"error": "Internal Server Error",
"exception": "org.springframework.data.mongodb.CannotGetMongoDbConnectionException",
"message": "Failed to authenticate to database [testdb], username = [test_user], password = [t**t]"
I have installed and configured MongoDB. This is my MongoDB config file:
systemLog:
destination: file
logAppend: true
path: C:\Program Files\MongoDB\data\log\mongod.log
timeStampFormat: iso8601-utc
storage:
dbPath: C:\Program Files\MongoDB\data\db
journal:
enabled: true
processManagement:
# fork: true
pidFilePath: C:\Program Files\MongoDB\mongod.pid
net:
port: 27017
bindIp: 127.0.0.1
security:
authorization: enabled
Next step I have created admin user and user for testdb database:
> use admin
switched to db admin
> db.createUser({user: "admin", pwd: "qwerty", roles: ["root"]})
Successfully added user: { "user" : "admin", "roles" : [ "root" ] }
> use testdb
switched to db testdb
> db.createUser({user: "test_user", pwd: "test", roles: [{role: "readWrite", db: "testdb"}]})
Successfully added user: {
"user" : "test_user",
"roles" : [
{
"role" : "readWrite",
"db" : "testdb"
}
]
}
POM file:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.rest</groupId>
<artifactId>spring-rest-api</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<properties>
<!-- Enable Java 8 -->
<java.version>1.8</java.version>
<guava.version>18.0</guava.version>
<hamcrest.version>1.3</hamcrest.version>
<mockito.version>1.9.5</mockito.version>
<assertj.version>1.7.0</assertj.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Configure the main class of our Spring Boot application -->
<start-class>org.wixanz.App</start-class>
</properties>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
</parent>
<dependencies>
<!-- Get the dependencies of a web application -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data MongoDB-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven Support -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Java MongoDB configuration file:
#Configuration
#PropertySource("classpath:mongodb.properties")
public class MongoDBConfig {
#Autowired
Environment env;
#Bean
public MongoDbFactory mongoDbFactory() throws Exception {
UserCredentials userCredentials = new UserCredentials(env.getProperty("mongodb.username"), env.getProperty("mongodb.password"));
MongoClient mongo = new MongoClient(env.getProperty("mongodb.host"), Integer.parseInt(env.getProperty("mongodb.port")));
return new SimpleMongoDbFactory(mongo, env.getProperty("mongodb.db"), userCredentials);
}
#Bean
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(mongoDbFactory());
}
}
MongoDB.properties file in project:
mongodb.host=localhost
mongodb.port=27017
mongodb.db=testdb
mongodb.username=test_user
mongodb.password=test
If I try to connect to testdb database without implementation of UserCredential than the connection established successfully and data received.
What I need to correct that database authorize connection passed successfully?
Connect to mongoDb
mongo 127.0.0.1:27017
Create User
Go to mongoDB console and delete your current user & set authSchema version to 3 instead of 5 ,
follow these commands in mongo console -
mongo use admin
db.system.users.remove({}) <== removing all users
db.system.version.remove({}) <== removing current version
db.system.version.insert({ "_id" : "authSchema", "currentVersion" : 3 })
Create User:
use test-dev-db
db.createUser(
{
user: "root",
pwd: "bnuy93JoLJjiop",
roles: [ "readWrite", "dbAdmin" ]
}
)

Resources