I override configure(HttpSecurity http) method in SampleSecurityConfig Class like this
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/delete/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().and().httpBasic();
}
If i don't use httpBasic method, it seems no problem occurred.
what does httpBasic method exactly do?
Calling this method on HttpSecurity will enable Http Basic Authentication for your application with some "reasonable" defaults.
It will return a HttpBasicConfigurer for further customization.
You can test this by curl and passing a header like Authorization: Basic bzFbdGfmZrptWY30YQ== but base64 encoding a valid username/password combination.
Documentation for httpBasic
What are we saying by calling httpBasic() ?
When httpBasic() is called, we are telling Spring to authenticate the request using the values passed by the Authorization request header. If the request is not authenticated you will get a returned status of 401 and a error message of Unauthorized
What is actually happening when httpBasic() is called ?
By calling httpBasic(), an instance of the BasicAuthenticationFilter is added to the filter chain. The BasicAuthenticationFilter will then proceed with trying to authenticate the request in the typical Spring Security fashion. If authentication is successful, the resulting Authentication object will be placed into the SecurityContextHolder, which can then be used for future authentication purposes.
Related
I am trying to migrate spring security to latest version (spring security 5.2.2 and Cloud OAuth2). As #EnableOAuth2Client is in maintenance mode now, I am trying to use http.oauth2Login() with customization for success handler. Following is my security class -
#Configuration
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login().successHandler(new SimpleUrlAuthenticationSuccessHandler("<url to redirect>"));
}
}
I have registered client with name as 'custom'. Following is the flow in the browser -
http://localhost:9000/oauth2/authorization/custom -> IDP's login page and successful login -> Get Authorization code on URL http://localhost:9000/login/oauth2/code/custom -> it again goes to http://localhost:9000/oauth2/authorization/custom and infinite loop. Successhandler is not invoked. Also, I don't see access token generation in logs.
I have tried many things in last two days like tweaking security config etc but nothing works.
Any help is appreciated.
The problem was with user info endpoint. My IDP has not exposed user info endpoint while it is mandatory in spring oauth2 where the request was failing. I needed to override the default OAuth2UserService implementation to resolve the issue.
I am trying to configure spring boot-Embedded Tomcat basic HTTP authentication with multiple roles, with most of the url's similar but few of them specific to each role. Here for first role the basic HTTP authentication pops up and working fine. With below code,
#Configuration
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class TestSecurityAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests().antMatchers(null, getAppAdminRolePaths()).authenticated()
.anyRequest().hasAnyRole("APPADMIN")
.and()
.httpBasic();
http.csrf().disable()
.authorizeRequests().antMatchers(null, getAppUserRolePaths()).authenticated()
.anyRequest().hasAnyRole("APPUSER")
.and()
.httpBasic();
http.authorizeRequests().antMatchers(null, new String[]{"/app/appOwnerView.html"}).authenticated()
.anyRequest().hasAnyRole("APPOWNER")
.and()
.httpBasic();
}
#Override
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("appadminname").password("appadminpwd").roles("APPADMIN").and()
.withUser("appusername").password("appuserpwd").roles("APPUSER").and()
.withUser("appownername").password("appoownerpwd").roles("APPOWNER");
}
private static String[] getAppAdminRolePaths(){
return new String[]{"/appweb/*",
"/app/checkService.html",
"/app/index.html",
"/app/testData.html",
"/app/adminView.html",
"/app/demo.html"};
}
private static String[] getAppUserRolePaths(){
return new String[]{"/appweb/*",
"/app/checkService.html",
"/app/index.html",
"/app/testData.html",
"/app/userView.html",
"/app/demo.html"};
}
}
For HTTP username/password popup in browser with url http://localhost:8080/app/index.html say with appadminname/appadminpwd it works fine. But for same url if I enter appusername/appuserpwd it throws HTTP 403 Forbidden access error. Here why is the second role APPUSER configured is throwing this error is I am not sure. Please let know if some way to get this resolved.
Thanks
I appreciate this question is a little old now, but this may still be useful to someone.
Firstly, I'm not sure why your calls to antMatchers() supply null as the first argument; antMatchers() expects a list of strings defining the URLs to be covered by this rule, so I'm not sure what null is expected to match in this case.
Secondly, anyRequest() means that this rule will be applied to any request made to the application regardless of the URL used, and Spring will apply security rules in the order that they are defined. You would typically define URLs and their associated roles first, and then default to a rule for any other request that must be authenticated (but does not necessarily need any specific roles) with something like anyRequest().authenticated()
Your first rule says that any request made to the application must be made by users with the role APPADMIN, which denies you access when you try to log in as appusername, so the second rule to allow APPUSERs is not even processed.
Thirdly, you are making multiple calls to http.authorizeRequests() when you should probably actually be chaining them together, for example:
http.csrf().disable().authorizeRequests()
.antMatchers( getAppAdminRolePaths() ).hasRole("APPADMIN")
.antMatchers( getAppUserRolePaths() ).hasRole("APPUSER")
.anyRequest().authenticated();
Lastly, when you have just a single role to check against, you can use hasRole() instead of hasAnyRole().
You also don't need to supply authenticated() and hasRole() in the same rule because hasRole() implies that the user is already authenticated.
You can find more explanations and examples in the Spring documentation: http://docs.spring.io/spring-security/site/docs/4.0.3.RELEASE/reference/htmlsingle/#authorize-requests
I have a spring-boot application with spring-security enabled. I have a custom AbstractPreAuthenticatedProcessingFilter that checks request header for some authentication token set by external system. In case token is absent or invalid corresponding AuthenticationManager throws AuthenticationException. Looks pretty simple.
My problem is that I'd like to be able to handle this AuthenticationException by replying with a 403 (Forbidden) status. How can I do it? I tried adding the following to WebSecurityConfigurerAdapter:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint());
...
but it doesn't work. The issue is that ExceptionTranslationFilter that is supposed (if I understand it correctly) to handle these things is the last filter in the default security filter chain and exceptions thrown just never get to it. I'm totally stuck. How is this supposed to work? Please help!
A long time ago you question was done, but I was stucked in the same question without solution, so I decided to explain how to resolve this.
You are allowed to edit the FilterChain, you may put one ExceptionTranslationFilter before your PreAuthenticationFilter as ...
http
.csrf().disable()
.addFilter(myPreAuthenticationFilter)
.addFilterBefore(new ExceptionTranslationFilter(
new Http403ForbiddenEntryPoint()),
myPreAuthenticationFilter.getClass()
)
.authorizeRequests()
.antMatchers(authSecuredUrls).authenticated()
.anyRequest().permitAll()
.and()
.httpBasic()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint())
;
Your AbstractPreAuthenticatedProcessingFilter getPreAuthenticatedCredentials or getPreAuthenticatedPrincipal methods may throw AuthenticationException if any credential is not provided as ...
if ( !StringUtils.hasText(request.getParameter("MY_TOKEN")) ) {
throw new BadCredentialsException("No pre-authenticated principal found in request");
}
Or your AuthenticationManager authenticate method can throw AuthenticationException too.
Using Spring Security
Basic authentication setup works against some hardcoded username passwords as shown here:
http://thoughtfulsoftware.wordpress.com/2013/12/08/adding-security-to-spring-guides-rest-service/
So trying to extend it to use LDAP.
Completed the set up for LDAP authentication with our LDAP server
Now when I try to call my rest service through REST Console plug-in an authorization window keeps on popping up for username password. If I cancel it authorization fails, not sure where I am going wrong
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable()
.httpBasic();
#Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder
.ldapAuthentication()
.userSearchFilter("(uid={0})").userSearchBase("ou=people,dc=zzz,dc=xxxx,dc=yyy")
.groupRoleAttribute("cn").groupSearchFilter("(member={0})")
//.userDnPatterns("uid={0},ou=people")
//.groupSearchBase("ou=groups")
.contextSource().url("ldaps://ldap.xxxx.yyy:636/cn=cw-grpreader,ou=people,dc=xxx,dc=xxxx,dc=xxx")
.managerDn("cn=xx-xxr,ou=people,dc=med,dc=xxxx,dc=xxx")
.managerPassword("#$%^^");
}
This is one way I tried which give the recurring authentication popup
if I cancel the popup I get
HTTP Status 401 - [LDAP: error code 49 - NDS error: failed authentication (-669)]; error even if the credentials are correct
Link to some tutorial will be really helpful
This is due to httpbasic authentication that you have set up. Spring boot generates a random password thats shown on console which you could use.
To disable that pop-up simply add this to your application.properties file.
security.basic.enabled: false
I am pretty new to Spring Security land. I am using programmatic configuration of Spring Security with servletApi() which is pretty neat.
Here is the configuration:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.securityContext().and()
.servletApi().and()
.authorizeUrls()
.antMatchers("/login").permitAll()
.antMatchers("/").permitAll()
.antMatchers("/**").authenticated();
}
I am using http servlet api login I am not using any filter for this.
In case a unauthorised request, ExceptionTranslationFilter uses Http403EntryForbiddenEntryPoint to return 403 forbidden status.
In my scenario:
If user does not authenticated, a 401 status code should return.
If user authenticated but not authorised, a 403 status code should return.
But default configuration creates 403 status for both case.
Here are my questions:
Why is the default entry point is Http403EntryForbiddenEntryPoint? It can be 401?
If I change Http403EntryForbiddenEntryPoint to Http401EntryForbiddenEntryPoint, does It create a problem?
Thanks