When I develop a non-reactive application and use rememberMe feature in authentication, I just extending WebSecurityConfigurerAdapter class and overriding configure(HttpSecurity httpSecurity) method. In that case, I have a rememberMe() method in a httpSecurity object.
But there is a difference when I use Spring WebFlux. As far as I know, all I have to do is defining a SecurityWebFilterChain bean using the instance of ServerHttpSecurity class, by invoking chain like:
serverHttpSecurity.authorizeExchange()
.anyExchange().authenticated()
.and()
.httpBasic()
.build();
But there is no method to handle rememberMe cookie here like in the HttpSecurity object where I could handle it in that way:
httpSecurity.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and()
.rememberMe()
Do you know any solution?
Unfortunately, it seems impossible to do this.
There is an old issue on github and unfortunately, it is not known when it is going to be solved.
The comments recommend using a longer session expiration and offloading the sessions into an external data store (i.e. Redis). This way, you can store information in a database instead of in cookies.
They recommend using the Spring Session project.
The comments say that using a longer session expiration and offloading the sessions into an external data store (i.e. Redis). This way, you can store information in a database instead of in cookies.
They say use the Spring Session project.
Related
I export my React build folder to the SpringBoot resources folder and want to serve them statically. I set the antMatcher for my backend endpoints to permit some of urls access,
and rest of urls which are not permitted would need some authentication.
http
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/v1/registration","/api/v1/login")
.permitAll()
.anyRequest()
.authenticated().and()
.exceptionHandling().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
The current situation is that, my frontend React Router URL is also blocked by the antMatcher.
e.g.
http://localhost:8080/login being blocked
I can solve it by just manully hard coding the frontend url into antMatchers, like
.antMatchers("/api/v1/registration","/api/v1/login", "/login","/registration"...)
.permitAll()
but I wonder if there is any elegant way to tell backend not to block frontend url? If the website is growing big, adding URL into antMatcher would be time-consuming.
First of all, we have some basic principles to think about:
Your web server could have some files that should be open to all (such as robots.txt and favicon.ico), on top of the static frontend (which may or may not need to be public without respect to this).
When configuring security, it's better to have a baseline which is to deny all requests and then instead whitelist the requests you want to let through, as opposed to permit all except for a few which you deny. It is easier to forget about paths this way and accidentally allow access to things that should be restricted.
Typically with an open static frontend, the sensitive content is provided from api endpoints which serve the dynamic content (this is NOT the case with a dynamic frontend rendered on the server of course).
An approach that I like is to use multiple ordered configurations for different groups. As far as I know, this can't be accomplished so easily with one configuration, and since complexity is also an enemy of security, this is an approach I like:
#EnableWebSecurity(debug = true)
#Order(1)
class OpenConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.requestMatchers()
.antMatchers("/*", "/locales", "/avatars", "robots.txt")
.and()
.authorizeRequests()
.anyRequest()
.permitAll()
}
}
#EnableWebSecurity
#Order(2)
class RestrictedConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.requestMatchers()
.antMatchers("/api/**")
.and()
.authorizeRequests()
// more fine-grained control within matched group of requests here
.anyRequest()
.authenticated()
.and()
.httpBasic()
}
}
#EnableWebSecurity
#Order(3)
class CatchAllConfig: WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.authorizeRequests()
.anyRequest()
.denyAll()
}
}
With .requestMatchers() you determine which requests you want to process in this config and after .authorizeRequests(), you can determine more in details what you want to do with the matched requests. If .requestMatchers() (or a similar method) is omitted, all requests are matched by the configuration. The configurations are looked up in order and the first that matches the request in question is used.
You CAN do something similar to the above with one configuration but I think both that it's easier to think about it structurally when dividing it into multiple configurations and also Spring security seems to behave more consistently (once you involve authentication methods, your choices after .authorizeRequests() can sometimes not have the intended results if you try to control paths in widely different ways).
If you want to do it in the most secure way, then you should explicitly whitelist every static asset that you want public access to, but given that you rebuild the frontend every now and then with new hashes attached to filenames, this becomes tedious. The above is a middle way where you assume that all content that is one level under / belongs to the static frontend and should thus be available without authentication (you could work with file suffixes here as a complement if you want). Any folders under the static frontend must be specifically specified. All you have to do now is make sure that any dynamic content is placed in some path which is secured and that you don't have any packages which automatically adds paths to your application which you don't want to be open and that are added at the root (typically Swagger UI and actuators can do this even though the latter often put them under the /actuator/ path.
I have override the configure method of WebSecurityConfigurerAdapter class as:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin();
}
I have APIs as /admin, /admin/user, /admin/user/test. When i login as admin i can access all the three URLs. I just wanted to know the difference between '/admin/**' and '/admin',
In case of /api/**, hasRole(...) will be authorized to all the requests that starts with the pattern /api.
And in case of /api, hasRole(...) will be authorized to only one request i.e. /api
In the above question only the '/admin' request is authorized to 'ADMIN' role. We can also access the other URLs because other URLs just need to be authenticated ignoring the role. We can also access the '/admin/user' or '/admin/user/test' while logging with user. If we have used antPattern as '/admin/**', then we won't be able to access those APIs through the session of user.
I am new to Spring Security and i was about to post the question but after spending some time, i came to know a little about it, so i also included my understanding for suggestions.
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 read a lot of manual of how to configure spring security, but still stuck with configuration.
So i want to configure rest calls and other http calls. As i understand i can create urls like /server/** - for web application and /rest/** - for rest application. For any call of web application urls i want to create a login page (when user not authenticated), but for rest app, i want to fire Unauthorised code.
I do it with spring annotations by extend WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.antMatchers("/").access("hasRole('ROLE_USER')")
.antMatchers("/server/*").access("hasRole('ROLE_USER')")
.and()
.formLogin().loginPage("/login").permitAll().failureUrl("/login?error")
.usernameParameter("username")
.passwordParameter("password")
.and()
.exceptionHandling()
.accessDeniedPage("/accessDenied");
}
for server it works fine, but if i try to add /rest here when i try to call /rest/[something] (in browser), it always forwards me to /login page.
I don't understand why and it is break my mind.
Thanks for any helpful responses.
You have this:
.antMatchers("/").access("hasRole('ROLE_USER')")
.antMatchers("/server/*").access("hasRole('ROLE_USER')")
.and()
.formLogin()
means / access need ROLE_ACCESS and for authentication, direct to formLogin
You need multiple authentication conf.
see http://docs.spring.io/autorepo/docs/spring-security/4.0.0.CI-SNAPSHOT/reference/htmlsingle/
And in one of them you need something like this
http
.antMatcher("/rest/**")
.exceptionHandling().authenticationEntryPoint(new AccessDenyEntryPoint()).and()
.authorizeRequests().antMatchers("/spring/**").denyAll();
You have to add one more .antMatchers("/rest/*").permitAll() if you don't want to validate your rest urls.
I am using the following Java Config with Spring Security:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
Based on this configuration, all requests are authenticated. When you hit a controller without being authenticated, the AnonymousAuthenticationFilter will create an Authentication object for you with username=anonymousUser, role=ROLE_ANONYMOUS.
I am trying to provide anonymous access to a a specific controller method and have tried to use each of the following:
#Secured("ROLE_ANONYMOUS")
#Secured("IS_AUTHENTICATED_ANONYMOUSLY")
When the controller methods get invoked, the following response is given:
"HTTP Status 401 - Full authentication is required to access this resource"
Can someone help me understand why we are receiving this message and why ROLE_ANONYMOUS/IS_AUTHENTICATED_ANONYMOUSLY don't seem to work using this configuration?
Thanks,
JP
Your security configuration is blocking all unauthenticated requests.
You should allow access to the controller with
.antMatchers("/mycontroller").permitAll()
See also:
http://spring.io/blog/2013/07/03/spring-security-java-config-preview-web-security/