I'm implementing OAuth2 on my application using Spring Boot and Spring Security OAuth with JDBC client support.
I can generate tokens, when I make a POST request to http://localhost:8080/oauth/token I get a valid response like:
{
"access_token": "359e93b2-555a-477b-9a65-e5062314fc23",
"token_type": "bearer",
"refresh_token": "6fd1ae31-8129-4729-a86b-e756c453a58a",
"expires_in": 899,
"scope": "read"
}
Now the strange this is, I cannot find this token anywhere in the database. If I make another request to /oauth/token I get the same token but with a lower value for expires_in as expected. I get to the conclusion that this token information must be stored somewhere but I can not find it.
01:24:41 SELECT * FROM dummy.oauth_access_token LIMIT 0, 1000 0 row(s) returned 0.000 sec / 0.000 sec
All OAuth related tables are empty except oauth_client_details which has the client details to generate the token.
Here's my code.
AuthServerOAuth2Config
#Configuration
public class AuthServerOAuth2Config extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
private final AppConfig appConfig;
#Autowired
public AuthServerOAuth2Config(AuthenticationManager authenticationManager, AppConfig appConfig) {
this.authenticationManager = authenticationManager;
this.appConfig = appConfig;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(appConfig.dataSource());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("permitAll()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
AppConfig Class
#Configuration
#PropertySource(value = "classpath:application.properties")
public class AppConfig {
#Value("${spring.datasource.url}")
private String datasourceUrl;
#Value("${spring.database.driverClassName}")
private String dbDriverClassName;
#Value("${spring.datasource.username}")
private String dbUsername;
#Value("${spring.datasource.password}")
private String dbPassword;
#Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(dbDriverClassName);
dataSource.setUrl(datasourceUrl);
dataSource.setUsername(dbUsername);
dataSource.setPassword(dbPassword);
return dataSource;
}
#Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource());
}
}
And here's my pom.xml in case it is of any help to find why there are no tokens persisted in the database.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.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>
<!-- Defining which version of Spring Framework we are using -->
<spring-cloud.version>Dalston.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-aws-context</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
</dependencies>
My question is, why are the generated tokens not being persisted to the mysql database and how can I fix it?
Spring Security OAuth 2 uses an in-memory implementation of the token store by default, see OAuth 2 Developers Guide:
When creating your AuthorizationServerTokenServices implementation, you may want to consider using the DefaultTokenServices which has many strategies that can be plugged in to change the format and storage of access tokens. By default it creates tokens via random value and handles everything except for the persistence of the tokens which it delegates to a TokenStore. The default store is an in-memory implementation, but there are some other implementations available. Here's a description with some discussion of each of them
The default InMemoryTokenStore is perfectly fine for a single server (i.e. low traffic and no hot swap to a backup server in the case of failure). Most projects can start here, and maybe operate this way in development mode, to make it easy to start a server with no dependencies.
You can change the used implementation of the token store with AuthorizationServerEndpointsConfigurer#tokenStore.
Your modified authorization server endpoint configuration:
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenStore(appConfig.tokenStore());
}
By default, an in memory token store is configured. If you want to persist the tokens between restarts then you need to configure a persistent token store.
Please find following working example. : https://github.com/spring-projects/spring-security-oauth/tree/master/tests/annotation/jdbc
Related
Error: I get the following in Firefox: Foreign Site Query Blocked: The same origin policy does not allow reading of the remote resource http: // localhost: 8080 / api / v1 / post /. (Cause: The 'Access-Control-Allow-Origin' CORS header does not exist)
I have spent several hours to allow CORS communication with my Spring Boot server in order to make my REACT UI communicate with the server. There are lot of similarly phrased questions on Stack Overflow, but non of the suggested solutions have solved my problem...
Spring Boot suggests different solutions on https://spring.io/guides/gs/rest-service-cors/. One local solution is using annotations. A global solution can be obtained with a config file.
I have tried annotating the controller with #CrossOrigin as seen in my code below:
package com.example.Blogging.api;
import com.example.Blogging.model.Post;
import com.example.Blogging.service.PostService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
#CrossOrigin(origins = "http://localhost:3000")
#RequestMapping("api/v1/post")
#RestController
public class PostController {
private final PostService postService;
#Autowired
public PostController(PostService postService) {
this.postService = postService;
}
#PostMapping
public void addPost(#RequestBody Post post){
postService.addPost(post);
}
#GetMapping
public List<Post> getAllPosts(){
return postService.getAllPosts();
}
#GetMapping(path = "{id}")
public Optional<Post> getPostById(#PathVariable("id") UUID id){
return postService.getPostById(id);
}
#PutMapping(path="{id}")
public void updatePostById(#PathVariable("id") UUID id, #RequestBody Post post){
postService.updatePost(id,post);
}
#DeleteMapping(path="{id}")
public void deletePostById(#PathVariable("id") UUID id){
postService.deletePost(id);
}
}
This did not work.. I have also tried annotating on each method instead of the whole controller class.
Furthermore I have tried to make a config file:
package com.example.Blogging.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*");
}
}
Nothing really seems to work. The console in my browser keeps saying 'access-control-allow-origin' is missing in the response header..
For reference, I will also put my pom.xml 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.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>Blogging</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Blogging</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- SPRING SECURITY -->
<!--<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<scope>test</scope>
</dependency>-->
<!-- SPRING BOOT STARTER SECURITY -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
</plugins>
</build>
</project>
Anyone who can suggest a solution? Thank you in advance!
I just noticed, you have Spring Security in your dependencies.
You might missed to enable CORS in your WebSecurityConfig.
Eg. something like this:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()...
}
}
I am trying to access my API through Postman. In the config, I have set /authenticate to be permitted, but I get 401 unauthorized all the time.
The relevant function:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// dont authenticate this particular request
.authorizeRequests().antMatchers("/authenticate").permitAll().
// all other requests need to be authenticated
anyRequest().authenticated().and().
// make sure we use stateless session; session won't be used to
// store user's state.
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
My dependencies
<dependencies>
<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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
</dependencies>
Any help would be appreciated
The problem here is that even if you are configuring Spring Security to allow every user, your request is going thru the same security chain as for the other requests. I am guessing that your call to the authentication endpoint does not contain anything in the authorization header, or to say in other way, your token is empty, therefore you are getting a 401. In this case, one solution can be to say to spring security that for the URL for the authentication, the request wont travel thru the security chain. You can achieve that with the following code in your Spring Security configuration.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/authenticate");
}
I hope this can solve your problem.
I have a very simple demo application using the Spring Boot 2.0.x.RELEASE
In my POM I have:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.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>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
<exclusions>
<exclusion>
<!-- We're using undertow as our embedded web container instead of tomcat -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Embedded web container- serves Jersey resources -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- Support for Spring Actuator & Health Check Endpoints -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
My main application just looks like:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
ResourceConfig getJerseyConfig() {
final HashMap<String, Object> jerseyProperties = new HashMap<>();
jerseyProperties.put(ServerProperties.MEDIA_TYPE_MAPPINGS, "json : application/json");
ResourceConfig resourceConfig = new ResourceConfig()
.register(TestEndpoints.class);
resourceConfig = resourceConfig.setProperties(jerseyProperties);
return resourceConfig;
}
}
When I then try and hit an actuator endpoint such as /actuator I receive a 404, but I can hit the endpoints in TestEndpoints.java with no problem. I had this working with Spring Boot 1.5.x, but now it seems that Jersey is not allowing the actuator endpoints through. If I remove the ResourceConfig bean completely, then I can hit the actuator endpoints. Is there some configuration I have to add to allow the actuator endpoints through jersey?
It's because by default Jersey will use the url mapping /*, which will hog up all requests, including those to the actuator endpoints, which it will not find. There are two solutions; you can either change the base URL for Jersey to something else, e.g. /api/* or you can configure Jersey as a filter (instead of the default servlet) and set a property to make Jersey forward all requests it doesn't know down to the servlet container. Both examples can be found in this post.
I am using the H2 database in a Spring boot application. But unable to open it in the browser at http://localhost:8080/console. My pom.xml is as below:
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.192</version>
</dependency>
Spring boot Configuration :
Springboot configuration file
#Configuration
public class WebConfiguration {
#Bean
ServletRegistrationBean h2servletRegistration(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean( new WebServlet());
registrationBean.addUrlMappings("/console/*");
return registrationBean;
}
}
to use the H2 console you need to configure it in your .properties file
spring.h2.console.enabled=true
spring.h2.console.path=/h2console/
where /h2console/ is the path you want to use on the browser so you can change it to anything. Also if you have security enabled you might want to add it to the permitted paths
also add this to your HttpSecurity configuration http.headers().frameOptions().disable();
Edit
change your security configuration i'm pretty sure you might have spring security in your pom so use this instead, if not it should work
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
public class WebConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests().antMatchers("/").permitAll().and()
.authorizeRequests().antMatchers("/console/**").permitAll();
httpSecurity.csrf().disable();
httpSecurity.headers().frameOptions().disable();
}
}
If have included spring-boot-starter-security artifact in your pom then by default basic authentication is enabled. Hence, to access your console either you disable the basic authentication by adding security.basic.enabled=false in your application.properties or allow the access in your configure method as below:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests().antMatchers("/").permitAll().and().authorizeRequests()
.antMatchers("/console/**").permitAll();
httpSecurity.headers().frameOptions().disable();
}
}
Thank you all for your generous help.The application class (Springboot) was in a separate package and it was not scanning other packages.Also I modified my Pom.xml a bit which finally helped me to access the console.Attached is my new 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>
<groupId>com.spring.app</groupId>
<artifactId>Demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SpringBootApp</name>
<description>Generator of statistics </description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</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>
<!--WebJars -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring AOP + AspectJ -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!-- JavaConfig need this library -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!-- Jackson JSON Mapper -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
go the POM file and add the dependency :
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
rebuild your project
this might help folks , all the configuration above is correct
Note - if you are not using any security then adding spring security is not required
Actualy problem is - when you open this url in chrome
http://localhost:8080/h2 chrome makes it --> https://localhost:8080/h2
To get rid of this issue - Below reference will help -
Google Chrome redirecting localhost to https
You might have face 2 situation including following errors:
localhost refused to connect
Double check the URL. Chrome automatically try to change http:// to https://
Check spring.h2.console.path (Path at witch the console avilible) to get your URL:
Default: /h2-console --> URL: http://localhost:8080/h2-console/
If you running IDE (e.g. IntelliJ Idea), make sure your app is running witch means your H2 data base is running!
You face 404 Error:
In this case your H2 Data base is correctly running on Port 8080 and you already have the connection with it.
Check spring.h2.console.path (Path at witch the console avilible) to get your URL:
Default: /h2-console --> URL: http://localhost:8080/h2-console/
Enable H2 Console
spring.h2.console.enabled=true
The issue might be also be caused by adding server.servlet.context-path to properties. The new url will be composed of server.servlet.context-path plus spring.h2.console.path
If you have renamed the h2 path in the application.properties to "console" you've to add it in your antMatcher like .antMatcher("/console/**") with two asterisks after the "console" because there are much more appendings.
If none of the above solution works, try below one, this worked for me :
Add below property in your application.propertiesfollowing
spring.data.jpa.repositories.bootstrap-mode=default
Open console in browser using this URL : http://localhost:8080/h2-console
On a login page make sure that you use jdbc:h2:mem:testdb as JDBC URL.
As h2 database console is mapped to "h2-console".
Use this:
http.csrf().disable().authorizeRequests()
.antMatchers("/h2-console/**").permitAll()
.anyRequest().authenticated();
// disable frame options
http.headers().frameOptions().disable();
`
You don't need permit root access:
.antMatchers("/") * NOT NEEDED *
This question already has answers here:
Spring boot Security Disable security
(24 answers)
Closed 2 years ago.
I have a spring boot web app with spring security configured. I want to disable authentication for a while (until needed).
I add this to the application.properties:
security.basic.enable: false
management.security.enabled: false
Here is some part of my
But I still have a basic security included : There is a default security password generated at startup and I am still getting HTTP Authentication prompt box.
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>fr.test.sample</groupId>
<artifactId>navigo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.1.RELEASE</version>
</parent>
<properties>
<java.version>1.7</java.version>
<jsoup.version>1.8.3</jsoup.version>
<guava.version>18.0</guava.version>
<postgresql.version>9.3-1103-jdbc41</postgresql.version>
</properties>
<!-- Add typical dependencies for a web application -->
<dependencies>
<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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
<!-- Package as an executable jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- Add Spring repositories -->
<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
The security is configured in WebSecurityConfig.java (I have commented the annotation to disable it) :
//#Configuration
//#EnableWebSecurity
//#EnableGlobalMethodSecurity(prePostEnabled = true)
//#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserDetailsService userDetailsService;
#Autowired
UserService userService;
#Autowired
private DataSource datasource;
#Override
protected void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests().antMatchers("/bus/topologie", "/home")
// http.authorizeRequests().anyRequest().authenticated()
// .antMatchers("/admin/**").access("hasRole('ADMIN')").and()
// .formLogin().failureUrl("/login?error")
// .defaultSuccessUrl("/bus/topologie").loginPage("/login")
// .permitAll().and().logout()
// .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
// .logoutSuccessUrl("/login").permitAll().and().rememberMe()
// .rememberMeParameter("remember-me")
// .tokenRepository(persistentTokenRepository())
// .tokenValiditySeconds(86400).and().csrf();
}
#Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(datasource);
return tokenRepositoryImpl;
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
auth.jdbcAuthentication().dataSource(datasource);
if (!userService.userExists("user")) {
User userAdmin = new User("user", encoder.encode("password"), true);
Set<Authorities> authorities = new HashSet<Authorities>();
authorities.add(new Authorities(userAdmin,"ADMIN"));
authorities.add(new Authorities(userAdmin,"CRIP"));
authorities.add(new Authorities(userAdmin,"USER"));
userAdmin.setAuthorities(authorities);
userService.createUser(userAdmin);
}
}
}
Use security.ignored property:
security.ignored=/**
security.basic.enable: false will just disable some part of the security auto-configurations but your WebSecurityConfig still will be registered.
There is a default security password generated at startup
Try to Autowired the AuthenticationManagerBuilder:
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... }
Try this. Make a new class
#Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests().antMatchers("/").permitAll();
}
}
Basically this tells Spring to allow access to every url. #Configuration tells spring it's a configuration class
security.ignored is deprecated since Spring Boot 2.
For me simply extend the Annotation of your Application class did the Trick:
#SpringBootApplication(exclude = SecurityAutoConfiguration.class)
With this solution you can fully enable/disable the security by activating a specific profile by command line. I defined the profile in a file application-nosecurity.yaml
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
Then I modified my custom WebSecurityConfigurerAdapter by adding the #Profile("!nosecurity") as follows:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#Profile("!nosecurity")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {...}
To fully disable the security it's enough to start the application up by specifying the nosecurity profile, i.e.:
java -jar target/myApp.jar --spring.profiles.active=nosecurity
I think you must also remove security auto config from your #SpringBootApplication annotated class:
#EnableAutoConfiguration(exclude = {
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class,
org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration.class})
Since security.disable option is banned from usage there is still a way to achieve it from pure config without touching any class flies (for me it creates convenience with environments manipulation and possibility to activate it with ENV variable) if you use Boot
spring.autoconfigure.exclude: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
For me only excluding the following classes worked:
import org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
#SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class}) {
// ...
}
This was the only thing that worked for me, I added the following annotation to my Application class and exclude SecurityAutoConfiguration
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
#EnableAutoConfiguration(exclude = {
SecurityAutoConfiguration.class
})
just add
#SpringBootApplication(exclude = SecurityAutoConfiguration.class)
You could just comment the maven dependency for a while:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>-->
</dependencies>
It worked fine for me
Disabling it from application.properties is deprecated for Spring Boot
2.0
Change WebSecurityConfig.java: comment out everything in the configure method and add
http.authorizeRequests().antMatchers("/**").permitAll();
This will allow any request to hit every URL without any authentication.
Use #profile("whatever-name-profile-to-activate-if-needed") on your security configuration class that extends WebSecurityConfigurerAdapter
security.ignored=/**
security.basic.enable: false
NB. I need to debug to know why why exclude auto configuration did not work for me. But the profile is sot so bad as you can still re-activate it via configuration properties if needed
Just add the following line to disable spring auto configuration in application.properties file
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
it works on spring 2.0.5 :)
The accepted answer didn't work for me.
If you have a multi configuration, adding the following to your WebSecurityConfig class worked for me (ensure that your Order(1) is lower than all of your other Order annotations in the class):
/* UNCOMMENT TO DISABLE SPRING SECURITY */
/*#Configuration
#Order(1)
public static class DisableSecurityConfigurationAdapater extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().permitAll();
}
}*/