I'm creating a Spring boot application with Spring Web,Spring Security and Spring social. The application contains rest services that utilizes basic authentication for security. I"m trying to configure Spring to make the application stateless, however when I use the browser to make requests to the web services the browser prompts for user credential but all prior request use the same user credential because of session creation. I have configured the application to stop this from happening but still having the problem. \
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#override
protected void configure(HttpSecurity http) throws Exception{
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/**")
.hasRole("USER")
.andBasic();
}
#override
protected void configure(AuthenticatioinManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("some#gmail.com")
.password("12345")
.role("USER");
}
}
What should I change or add to get this functionality.
Spring security is based on something called the SecurityContext. This something is a ThreadLocal, e.g only exists on one thread at a time. Each request will be on it's own thread and will have no access to any protected resource unless that SecurityContext is set to contain the appropriate roles. So even though you just logged in, which behind the scenes inserted roles into the SecurityContext, that security context is gone just as though it had been a different user. Tokens are how you want to deal with this issue. Or base64 encode your username and password into every request, whatever floats your boat.
Look at this:
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() //allow CORS option calls
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
Related
Is it possible to create a form login page, where the session creation policy SessionCreationPolicy.STATELESS.
When I configure it without sessionCreationPolicy, the login works.
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.csrf().disable()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll();
// #formatter:on
}
}
When logging in, the POST will be send to /login and apperantly it will look in the session to redirect it back to the /oauth/authorize page (if you were coming from there).
But when I add:
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
It does not know where to redirect it to after login. Does anyone know how to achieve this?
I could not make this work with the .formLogin() options.
What I did is create a new MVC controller, where you could post your username and password. Authenticate against AuthenticationManager, if login was successful, forward the request to where /oauth/authorize is locating.
I'm trying to use spring security to secure a rest/stateless api using JWT tokens. From the research I've been seeing, it involves turning off the spring security session management and then adding some custom filters to handle the user logging in as well as checking for the jwt token.
The problem I'm having is that once i add a filter, it's run on every instead of just the endpoints I want it on. I need to open up the login endpoint as well as a few others that will facilitate enrollment and reference data that doesn't need to be secured.
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/user").permitAll()
.anyRequest().authenticated().and()
.addFilterBefore(new StatelessAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
;
}
}
All StatelessAuthenticationFilter does is print "in here". I'm only expecting to see that message print when you go to localhost:8080/api/order, but i see it show up when you go to localhost:8080/api/user.
Is there a way to get this behavior?
The way you configured, the HttpSecurity will be applied to all the URLs including the user endpoint.
authorizeRequests() .antMatchers("/api/user").permitAll() line won't prevent "user" endpoint from authentication filter being called.
It just says that any authenticated user can call it.
You need to apply the filter to "order" endpoint only. Like this:
http .requestMatchers().antMatchers("/api/user") .and() .authorizeRequests().
#tsolakp's answer sorta works for me. I ended up overriding the
configure(Websecurity) method though
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/user");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated().and()
.addFilterBefore(new StatelessAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
;
}
I'm working with Spring Boot 1.4.2.RELEASE, Spring Security 4.1.3.RELEASE, and Java 8.
For the security configuration I have the following class:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**", "/logout", "/login");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement() // 1
.sessionFixation() // 2
.migrateSession() // 3
.maximumSessions(1) // 4
.maxSessionsPreventsLogin(true).expiredUrl("/login").and() // 5
.invalidSessionUrl("/login") // 6
.and() // 7
.authorizeRequests()
.antMatchers("/app/**").authenticated()
.antMatchers("/about").permitAll()
.anyRequest().authenticated().and()
.formLogin()
.loginPage("/login").permitAll()
.loginProcessingUrl("/auth").permitAll()
.defaultSuccessUrl("/app/index", true)
.failureUrl("/login?error")
.usernameParameter("uid")
.passwordParameter("pwd").and()
.logout()
.permitAll()
.invalidateHttpSession(true)
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/login").permitAll()
.clearAuthentication(true).and()
.exceptionHandling().and()
.csrf().disable()
.headers().frameOptions().disable()
.cacheControl().and();
}
}
When try access to "/about" (permit all everyone), redirects me to "/login". I try it a second time and now it allows me to access "/about".
I have changed the authorization order of requests in the configuration class but don't works. When I delete the lines of sessionManagement (1 to 7), everything works normally.
Do I need any extra configuration?
When you are testing this, did you clear your browser's cookie with regard to your testing site? The session management filter sets a jsessionid cookie, which gets sent back. Your browser has no idea that you reset your server, so thinks the cookie is just fine, and you send back an invalid session.
You may want to take a look at your session creation policies to see whether or not it suits your purpose.
I am using Spring Security in my Spring 4 MVC Rest API application.
I have implemented successfully the authentication process using java configurations. I have also managed to log in properly, and I have used JdbcTemplate to interface with my mysql database.
Tmy SecurityConfig.java
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.failureUrl("/login?error")
.loginPage("/login")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.and().httpBasic().and().csrf().disable();
}
I'm really struggling to understand how I should modify the above configuration to use it in a REST Api application. I need to manage the session for the android app these apis are to be used with, so that, for every request, I do not have to pass the user_id.
If anyone could possibly mention the preferred (standard) way of achieving this (with just enough details), I'll be really really glad :)
I have created a Spring Boot app and I have my front-end app in the /resources/static folder.
For the routing, I am using Angular JS UI Router library.
I have defined a route, which I only want to be accessed by the admin and now I am trying to secure it using Spring Security.
Here is my WebSecurity Configuration class:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/#/admin").hasRole("ADMIN")
.and()
.formLogin()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/member", "/member/**").permitAll()
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js",
"/**/**/*.css",
"/**/**/*.js",
"/**/**/*.html",
"/**/**/**/*.css",
"/**/**/**/*.js",
"/**/**/**/*.html",
"/**/**/**/**/*.css",
"/**/**/**/**/*.js"
).permitAll()
.antMatchers("/auth/**", "/member/**", "/account/**").permitAll()
.and()
.csrf().disable();
}
}
The route I am trying to secure can be accessed through http://localhost:8080/#/admin.
However, whenever I am accessing that route, no login is requested and the page can be viewed by anyone.
Is it there another approach I should follow?
The URL: http://localhost:8080/#/admin is mapped to / in your permitAll list instead of the /#/admin rule, since #/admin part is just URL fragment, and usually not the business of the server side.
You have to define an API between your frontend and backend. Usually in RESTful web services form, and serve at /api/* path. Secure the path, and let your frontend talk to your backend through those APIs only.
It is eaiser to fix your issue,
Update
.antMatchers(HttpMethod.GET, "/#/admin").hasRole("ADMIN")
To
.antMatchers(HttpMethod.GET, "/#/admin").hasRole("ADMIN").anyRequest().authenticated()
For every matchers, you always need with permitAll() or authenticated() for it.