Spring MongoDB authorization failed - spring

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" ]
}
)

Related

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

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.

Spring tool suite - console error - whitelabel Error page - access denied

Spring boot sample program with Mysql backend. very simple code. I checked application. properties, access to the DB etc. No clue why I am getting this error.
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 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.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.skb.course.apis</groupId>
<artifactId>library-apis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>library-apis</name>
<description>Project for developing Library APIs</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JPA Data (We are going to use Repositories, Entiries, Hibernate, etc...) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- For MySQL Connector-J -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- For implementing API Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- For handling JWT related functionality-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.0</version>
</dependency>
<!-- Test related dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<!-- Used for Integration Tests. Spring's TestRestTemplate throws an error while sending PUT requests with
authorization error: java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode
Therefore we need to use Apaches's HTTP client. Please refer:
https://stackoverflow.com/questions/16748969/java-net-httpretryexception-cannot-retry-due-to-server-authentication-in-stream
-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Console has no errors and tomcat is configured to run on 3000 port
application.properties file
Mysql db showing list of databaseds
Theere is data available in the PUBLISHER TABLE. but access denied error is thrown
Rest controller code
package com.skb.course.apis.libraryapis.publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.UUID;
#RestController
#RequestMapping(path = "/v1/publishers")
public class PublisherController {
private static Logger logger =
LoggerFactory.getLogger(PublisherController.class);
private PublisherService publisherService;
public PublisherController(PublisherService publisherService) {
this.publisherService = publisherService;
}
#GetMapping(path = "/{publisherId}")
public ResponseEntity<?> getPublisher(#PathVariable Integer publisherId,
#RequestHeader(value = "Trace-Id", defaultValue = "") String traceId)
throws LibraryResourceNotFoundException {
if (!LibraryApiUtils.doesStringValueExist(traceId)) {
traceId = UUID.randomUUID().toString();
}
return new ResponseEntity<>(publisherService.getPublisher(publisherId, traceId), HttpStatus.OK);
}
}

spring security OIDC keycloak unable to get Authorities and Apply Authorization

I've Spring Security Oauth2 app, connected to OIDC server keycloak, I'm able to connect and get access token and perform authentication, however unable to perform Authorization.
The introspect of token responds with Authorities in json response as shown below.
{
"jti": "f21b1ecd-05b7-435b-a571-1b8554ae3666",
"exp": 1583995545,
"nbf": 0,
"iat": 1583994645,
"iss": "http://192.168.56.101:8080/auth/realms/master",
"sub": "e7462035-316e-4970-afde-e44ffd9f169e",
"typ": "Bearer",
"azp": "app1_client",
"auth_time": 1583994645,
"session_state": "7a36dc7f-dd5d-42cb-8684-398825fcacde",
"name": "Administrator 1",
"given_name": "Administrator",
"family_name": "1",
"preferred_username": "admin1",
"email_verified": false,
"acr": "1",
"resource_access": {
"app1_client": {
"roles": [
"APP1_ADMIN"
]
}
},
"scope": "email app1 profile",
"authorities": [
"ROLE_APP1_ADMIN"
],
"client_id": "app1_client",
"username": "admin1",
"active": true
}
However when I print Authorities in log I'm unable to get the Authorities ROLE_APP1_ADMIN instead in prints below log.
K-[ROLE_USER, SCOPE_address, SCOPE_app1, SCOPE_email, SCOPE_microprofile-jwt, SCOPE_offline_access, SCOPE_openid, SCOPE_phone, SCOPE_profile]
Below is HelloRest.java
#RestController
#Slf4j
#RequestMapping("/api")
public class HelloRest {
//#PreAuthorize("hasRole('APP1_ADMIN')")
#GetMapping("/admin")
public String admin(OAuth2AuthenticationToken e1) {
log.info("K-{}", e1.getAuthorities());
log.info("K-{}", e1.getAuthorizedClientRegistrationId());
log.info("K-{}", e1.getDetails());
log.info("K-{}", e1.getPrincipal().getAttributes());
log.info("K-{}", e1.getPrincipal().getAuthorities());
log.info("K-{}", e1.getName());
return "Hello from Admin of APP1";
}
#PreAuthorize("hasRole('APP1_USER')")
#GetMapping("/user")
public String user() {
return "Hello from User of APP1";
}
}
application.yml
server:
port: 8082
spring:
security:
oauth2:
# resourceserver:
# jwt:
# issuer-uri: http://192.168.56.101:8080/auth/realms/master
client:
provider:
keycloak:
issuer-uri: http://192.168.56.101:8080/auth/realms/master
registration:
keycloak:
client-id: app1_client
client-secret: <secret>
provider: keycloak
And finally 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 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.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.github.kprasad99</groupId>
<artifactId>app1-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>app1-backend-1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>Hoxton.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</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-web</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-configuration-processor</artifactId>
<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>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</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>
</project>
How to apply Authorization using spring security with keycloak?
From source code it looks like, we need to write custom mapper, spring security by default adds scope as role and default Role ROLE_USER. Added below custom mapper.
#Component
#Slf4j
public class KGrantedAuthoritiesMapper implements GrantedAuthoritiesMapper {
#Override
public Collection<? extends GrantedAuthority> mapAuthorities(Collection<? extends GrantedAuthority> authorities) {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(mappedAuthorities::add);
authorities.forEach(authority -> {
if (OidcUserAuthority.class.isInstance(authority)) {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
Optional.ofNullable(userInfo.getClaimAsStringList("authorities")).orElse(Collections.emptyList())
.stream().map(SimpleGrantedAuthority::new).forEach(mappedAuthorities::add);
// Map the claims found in idToken and/or userInfo
// to one or more GrantedAuthority's and add it to mappedAuthorities
} else if (OAuth2UserAuthority.class.isInstance(authority)) {
OAuth2UserAuthority oauth2UserAuthority = (OAuth2UserAuthority) authority;
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
log.info("{}", userAttributes);
// Map the attributes found in userAttributes
// to one or more GrantedAuthority's and add it to mappedAuthorities
// Not sure when this is being used
}
});
return mappedAuthorities;
}
}
Any configuration or in-built mappers available, please post, I will mark that as answer.

MultipartFormDataInput error when using java spring boot

I am using Angular 8 for front-end and Java Spring boot for back-end and on submit button the formdata along with a file attached in the form should post to the server. But I am getting an error at the backend when I click on the submit button as this-
2020-01-16 10:09:20.317 ERROR 4764 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput] with root cause
java.lang.NoSuchMethodException: org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput.<init>()
Front-end code snippet:
createMaintenanceRequest(data: FormData): Observable<any> {
return this.http.post(this.MAINTENANCE_URL, data,{headers: this.HEADERS})
.map(this.extractData)
.catch(err => this.handleError(err));
}
Back-end code snippet:
#CrossOrigin(origins = "*")
#RequestMapping(value="/api/maintenance",method= RequestMethod.POST)
#ResponseBody
#Consumes(javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA)
public Response postMaintenanceRequest ( MultipartFormDataInput maintenanceData) throws IOException
{
System.out.println("postMaintenanceRequest - ENTER");
MaintenanceService maintenanceService = MaintenanceService.getInstance();
ServiceResponse serviceResponse = maintenanceService.createMaintenanceStory(maintenanceData);
Response response;
switch (serviceResponse.getServiceOutcome())
{
case SUCCESS:
JsonObject payload = new JsonObject();
JsonObject data = new JsonObject();
data.addProperty("url", serviceResponse.getStoryURL());
System.out.println("postIncident responding with story url: " + serviceResponse.getStoryURL());
payload.add("data", data);
response = Response.ok(payload.toString()).build();
break;
case INVALID_DATA:
response = Response.status(Response.Status.BAD_REQUEST).build();
break;
case RALLY_ERROR:
default:
response = Response.serverError().build();
break;
}
This is my pom.xml:
<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>com.test.hello</groupId> <!--com.test.hello.firstone-->
<artifactId>DashboardService</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<name>DashboardService</name>
<description>Spring Boot base web application</description>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<start-class>com.test.si.main.Main</start-class>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
<dependency>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
<version>0.0.20131108.vaadin1</version>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.rallydev.rest</groupId>
<artifactId>rally-rest-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>3.9.3.Final</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
MultipartFormDataInput is resteasy (jboss) api and will not work with tomcat servlet container. Either use spring (as someone suggested) or use jersey one.
In spring change your controller method to
#RequestMapping(value="/api/maintenance",method= RequestMethod.POST
postMaintenanceRequest(#RequestParam("file") MultipartFile file) {
.....
.....
}
In your front be sure that you put the file like that
formData = new FormData();
formData.append('file', myFileData);
If you don't have authorization data on your header, dont create a custom header, angular will do it for you

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}

Resources