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.
Related
I have backend in spring-boot, exposing REST API, and i have SEPARATED front end in react.
I want to use spring security to secure my back end, and i want to keep spring authentication chain. However, when i use configuration such as:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.cors().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/newUser").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.and()
.formLogin().pertmitAll();
}
This generates /login endpoint and every request that is not authorized will get redirected to login page. However spring generates this /login login page and as i said i have my own stand-alone fornt-end in REACT, so i do not want spring to generate this page, i want it to tell my client to redirect to /login. If i disable formLogin
.formLogin().disable()
then i also lose my /login POST endpoint, and springs default authentication process.
Is there a way to keep to /login POST endpoint but remove the login page and let my frond-end client to redirect.
Thanks for help!
I agree with Toerktumlare 100%. You really should use the default implementations that Spring Security Framework offers and if you really need to add additional configuration that cannot be passed by values, then you should extend the original Spring Security Class.
In this case, you just have to specify the endpoint where your login page is:
.formLogin()
.loginPage("/yourLoginPage.html")
.loginProcessingUrl("/doLgin")
.defaultSuccessUrl("/yourHomePahe.html", true)
When you use the GET method, you will get html page. As I understand you need POST API call, Post API call to get JWT access_tocken and refresh tocken
you can use "/login" as API in post call to send a username and password; in response, you will get a token or anything that you send after successful authentication.
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.
Im new to these frameworks (Vaadin:7.6.1, Spring Security:4.0.3) and I'm asking myself how to configure the authorized requests if I want to build a Vaadin application.
I looked up a few examples where something like this is written:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
[...]
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/login**").permitAll()
.antMatchers("/UIDL/**").permitAll()
.antMatchers("/HEARTBEAT/**").authenticated()
.antMatchers("/VAADIN/**").permitAll()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll()
.and()
.csrf().disable();
}
}
Because I want to design the login page I use the Thymeleaf engine. Therefore I'm using this Controller class:
#Controller
public class LoginController
{
#RequestMapping("/login")
String login(Model model)
{
return "login";
}
}
Which .antMatchers() should I define if I want to block every request of my application if the user isn't logged in? I know that I have to define antMatchers("/resources/**").permitAll() for the login page to get the css and images. But what are these patterns like "/UIDL/**" and what do I need them for?
Which .antMatchers() should I define if I want to block every request
of my application if the user isn't logged in?
If you just want to block every request if the user isn't logged in:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.and()
.logout().permitAll()
.and()
.csrf().disable();
}
You don't really need any antMatcher, not even for the login page, as in the .formLogin() part, you already include .permitAll() for that page.
Now for static resources (css, js, images) and with VAADIN in mind, you can do this overriding another method:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/resources/**", "/VAADIN/**");
}
With a Spring Boot project, i also found issues if i didn't allow requests to "/vaadinServlet/**"in the web.ignoring().antMatchers(...).
what are these patterns like "/UIDL/**" and what do I need them for?
When the server receives a request, Spring Security uses these patterns to determine if it should allow or deny access to the request.
They represent the part of the URI after the context root of your application, e.g. in the case of your context root being /, then a request like http://server.com/UIDL/hello the part of the URI that Spring Security will use to determine wether to give acces or not will be /UIDL/hello
The ** represents anything including any sub level, e.g. for the /UIDL/** pattern, the request /UIDL/hello/world/and/any/more/levels will match.
There's also the single * which represents, anything but not including the sub levels, e.g. for the /UIDL/* pattern, the request /UIDL/hello will match, but not /UIDL/hello/world.
As for VAADIN views and UIs, i'm not sure that it is possible to use the antMatchers to grant or deny access, but instead you can annotate the configuration class with #EnableGlobalMethodSecurity(prePost = enabled) and then be able to use the #PreAuthorize( /* spel expression */) annotation on the views to grant or deny access.
UPDATE : Answering to comment questions:
Why do you use the configure(WebSecurity web) method with ignoring the resources instead of the configure(HttpSecurity http) with allowing access? Are there significant differences?
The difference is that WebSecurity#ignoring() makes the request being skipped from the Spring Security filter chain, and it is the recommended way for static resources, anything else than static resources should be processed inside configure(HttpSecurity http).
source
Why do you ignore the "/VAADIN/**" path?
Because that path is used to serve themes, widget sets, and customizations, which is static content, the path is used to serve it dinamycally from the Vaadin jar, but as suggested in the Vaadin documentation, in production environments should be served statically, as it is faster.
source
I could imagine the meaning of "/*" and "/**", but what does "UIDL" and "HEARTBEAT" actually mean? Why are they permitted?
UIDL:
User Interface Definition Language (UIDL) is a language for
serializing user interface contents and changes in responses from web
server to a browser. The idea is that the server-side components
"paint" themselves to the screen (a web page) with the language. The
UIDL messages are parsed in the browser and translated to GWT widgets.
source
Heartbeat requests are performed periodically to verify that the connection is still alive between server and client, or the session haven't expired.
source - see sections 4.8.5, 4.8.6, 4.8.7 and 4.8.8
My application has an authenticated admin area. My problem is that it also requires authentication for the login page (although it's marked as either "anonymous" or "permitAll" - I've tried both).
My configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin/**")
.authorizeRequests()
.antMatchers("/admin/login.html", "/admin/logout.html").permitAll() //"anonymous()" has same result
.antMatchers("/admin/**").hasAnyRole("ADMIN", "PUBLISHER")
.anyRequest().authenticated()
.and()
.addFilter(preAuthenticationFilter())
.addFilter(adminExceptionTranslationFilter())
.csrf().disable()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/admin/logout.html"))
.logoutSuccessUrl("/index.html")
.invalidateHttpSession(true);
}
The only thing I could think of that might be the culprit is the preAuthenticationFilter which extends the AbstractPreAuthenticatedProcessingFilter class (the authentication is smart card based and that class extracts the credential from a certificate sent by the browser). I'm guess that maybe because it's a type of preAuthenticated filter, then maybe Spring runs it before any request - thus prompting the authentication request in the browser (even if the accessed page "/admin/login.html" doesn't require authentication).
So my question ultimately is how do I actually disable authentication for the login page? As far as I can tell from the documentation, the antMatchers are configured correctly.
It was a proxy problem. The code in question is correct.
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/