When to use antPattern '/api/**' over '/api' in Spring Security - java

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.

Related

Spring Security anyRequest.authenticated behavior

i am trying to implement a simple Spring security project but I am facing an issue where the behavior of http.authorizeRequests().anyRequest().authenticated(); is not understandable. what i expect from this method is to prevent all incoming requests until the user is authenticated but in my case all the requests are go through and no interception happened. the normal behavior of preventing request to go through took a place when I un-comment the lines which include hasAnyAuthority.
Below is My security configs
#Override
protected void configure(HttpSecurity http) throws Exception {
CustomAuthFilter customAuthFilter = new CustomAuthFilter(authenticationManagerBean());
//override behavior of url for our api
customAuthFilter.setFilterProcessesUrl("/api/login");
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.authorizeRequests().antMatchers("/api/login/**").permitAll();
http.authorizeRequests().antMatchers("/register/**").permitAll();
/////http.authorizeRequests().antMatchers(GET,"/api/users/").hasAnyAuthority("ROLE_USER");
//////http.authorizeRequests().antMatchers(POST,"/api/user/save/**").hasAnyAuthority("ROLE_ADMIN");
http.authorizeRequests().anyRequest().authenticated();
http.addFilter(customAuthFilter);
http.addFilterBefore(new CustomAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
}
i have resolved the issue , it was just a miss-understanding of how authenticated method works.
so first Spring security checks if the user authenticated and and then checks if this endpoint need any type of authorization. if authenticated and not authorization exist the user would be redirected to the endpoint. it make sense for me now.
Thank you.

Java Config for Spring Security with Vaadin

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

Spring security requires authentication for pages marked with "anonymous" or "permitAll"

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.

Chained authentication in Spring Security

Can I chain multiple instances of AuthenticationEntryPoint in Spring Security 3.2.4?
I attempting to create the following scenario:
A certain URL is secured with Spring Security
The AuthenticationEntryPoint used is LoginUrlAuthenticationEntryPoint
An admin interface can spawn services under this URL
The admin can choose to secure these services with CLIENT-CERT
When a user attempts to access the secure URL:
If the path has been secured with CLIENT-CERT then authentication fails unless they have provided a valid certificate the corresponds to a user in the UserService. Standard Spring Security x509 authentication.
Once the user has been authentication as per the first point, or if the URL is not secured with CLIENT-CERT, they are directed to a FORM based authentication page.
Once they successfully authenticate with a username and password, they are directed to a landing page.
I am running on Tomcat 7.0.54 with clientAuth="want". This works perfectly in a "simple" Spring Security set up - i.e. with one WebSecurityConfigurerAdapter set to x509() and another set to formLogin() as per this example
So, I want a process flow something like the following:
I have had some success with dynamically changing the used authentication method by using a DelegatingAuthenticationEntryPoint but:
When using an AntPathRequestMatcher to map, say, /form/** to a LoginUrlAuthenticationEntryPoint the authentication servlet (/j_spring_security_check) gives a HTTP404 error.
When using an AntPathRequestMatcher to map, say, /cert/** to a Http403ForbiddenEntryPoint the user's details are not extracted from the presented client certificate so this gives a HTTP403 error.
I also cannot see how to force a user to authenticate twice.
I am using the java-config and not XML.
My code:
I have a DelegatingAuthenticationEntryPoint:
#Bean
public AuthenticationEntryPoint delegatingEntryPoint() {
final LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> map = Maps.newLinkedHashMap();
map.put(new AntPathRequestMatcher("/basic/**"), new BasicAuthenticationEntryPoint());
map.put(new AntPathRequestMatcher("/cert/**"), new Http403ForbiddenEntryPoint());
final DelegatingAuthenticationEntryPoint entryPoint = new DelegatingAuthenticationEntryPoint(map);
entryPoint.setDefaultEntryPoint(new LoginUrlAuthenticationEntryPoint("/login"));
return entryPoint;
}
And my configure
#Override
protected void configure(final HttpSecurity http) throws Exception {
defaultConfig(http)
.headers()
.contentTypeOptions()
.xssProtection()
.cacheControl()
.httpStrictTransportSecurity()
.addHeaderWriter(new XFrameOptionsHeaderWriter(SAMEORIGIN))
.and()
.authorizeRequests()
.accessDecisionManager(decisionManager())
.anyRequest()
.authenticated()
.and()
.httpBasic()
.authenticationEntryPoint(delegatingEntryPoint())
.and()
.sessionManagement()
.maximumSessions(1)
.sessionRegistry(sessionRegistry())
.maxSessionsPreventsLogin(true);
}
Where decisionManager() returns a UnanimousBased instance. sessionRegistry() returns a SessionRegistryImpl instance. Both methods are #Bean.
I add a custom UserDetailsService using:
#Autowired
public void configureAuthManager(
final AuthenticationManagerBuilder authBuilder,
final InMemoryUserDetailsService authService) throws Exception {
authBuilder.userDetailsService(authService);
}
And I have a custom FilterInvocationSecurityMetadataSource mapped using a BeanPostProcessor as in this example.
Chaining multiple entry points won't really work.
Your best option here might be to just customize the form-login process to check for the certificate if it's needed (before authenticating the user). That would probably simplify the configuration overall. It would really just be the same as a normal form-login setup.
The work done by the X509 filter is quite minimal. So for example, you could override the attemptAuthentication method, call super.attemptAuthentication() and then check that the certificate information matches the returned user authentication information.

Confusion around Spring Security anonymous access using Java Config

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/

Categories

Resources