Springboot configuration 401 Unauthorized - spring-boot

I have this configure method and i want to make user be able to register but i get 401 Unathorized. It is caused by the .apply(**) and i am not able to do it.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/auth/register").permitAll()
.antMatchers("/auth/signin").permitAll()
.anyRequest().authenticated()
.and()
.apply(new JwtConfigurer(jwtTokenProvider, securityUtils));
}
JwtConfigurer.class
public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final JwtTokenProvider jwtTokenProvider;
private final SecurityUtils securityUtils;
public JwtConfigurer(JwtTokenProvider jwtTokenProvider, SecurityUtils securityUtils) {
this.jwtTokenProvider = jwtTokenProvider;
this.securityUtils = securityUtils;
}
#Override
public void configure(HttpSecurity http) {
JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider, securityUtils);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
So when request is sent to /auth/register i dont want to add .apply(**). Do u have any suggestion please?

In your class that extends WebSecurityConfigurerAdapter where your http configure() method with .apply() is written, you can use the following to tell Spring Boot to bypass or ignore the filter if encountered with the uri for user registration.
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
"/auth/register");
}
Edit: Since you are facing the exception:
Cross-origin Request Blocked (Reason: CORS header ‘Access-Control-Allow-Origin’ missing and Reason: CORS request did not succeed)
it means that your OPTIONS request (preflight request) is failing. Are you using a different project as Front End for your application? If yes, you will need to specify in your spring boot configuration to allow origin and allow the specified methods from that particular origin.
Please refer to this official documentation to learn how to do that. You can enable Cors at Controller level or at global level. This StackOverflow thread should also be helpful in doing the implementation in case you are unable to proceed.

Related

Spring security - Specific session creation policy per matchers

I'm trying to implement SessionCreationPolicy.ALWAYS for the /testMVCController/** endpoint and SessionCreationPolicy.STATELESS for rest of endpoints (/**).
Expected scenario:
When accessing to /testMVCController/displayUsers the user logs in once and the log I have implemented in UserDetailsService logs the authorities associated to that user.
After that, all the requests to /testMVCController/displayUsers or other URL under /testMVCController/** will not log the authorities again because the session creation policy is always and the user is already logged in.
This works when I don't specify the 2nd security configuration (X509ClientSessionCreationPolicyStateless) but when I add it, all the requests become session stateless.
It is not working with the current security configuration because after I log in with my client certificate, at any request executed under /testMVCController/** endpoint (e.g. /testMVCController/displayUsers), the authenticationUserDetailsService is consulted and the list of authorities is logged for each file request the browser makes (.js file, .css files, ...), even after the initial login.
So, if there are 3 requests (/testMVCController/displayUsers, displayUsers.js, displayUsers.css) the list of authorities log present in authenticationUserDetailsService is logged 3 times.
I configured SecurityConfiguration as shown below but it is not working:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
public class SecurityConfiguration {
#Configuration
#Order(1)
public static class X509ClientSessionCreationPolicyAlways extends WebSecurityConfigurerAdapter {
#Autowired
private X509CUDService x509CUDService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/testMVCController/**")
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.x509()
.authenticationUserDetailsService(x509CUDService)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
#Configuration
#Order(2)
public static class X509ClientSessionCreationPolicyStateless extends WebSecurityConfigurerAdapter {
#Autowired
private X509CUDService X509CUDService ;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/**")
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.x509()
.authenticationUserDetailsService(X509CUDService);
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
}
I've searched this issue and I found various links (e.g. Spring session creation policy per-request?, Spring Session: How to create separate session management policies for different URLs and Multiple HttpSecurity) but none of them worked.
Thanks in advance!
I was missing some details on my configuration. I was catching all the requests to /testMVCController/** and that was working, but in addition to catch the requests to any endpoint of the type /testMVCController/** (e.g.: /testMVCController/usersList), I also have to catch the requests that these pages make to get their scripts (.js files, .css files, .png files).
What was happening was: the request to /testMVCController/usersList), was configured with SessionCreationPolicy.ALWAYS, but the subsequent requests such as usersList.js, usersList.css, etc were configured with SessionCreationPolicy.STATELESS, and in these cases the X509CustomUserDetailsService was always consulted.
Example:
GET request to /testMVCController/usersList works, but there also requests in this usersList page to usersList.js, usersList.css, etc.
So, once I included these resource paths in the antMatchers all worked perfectly.

Oauth2 security configuration antmatchers request filtering not working as expected

I am working on a simple spring boot project along with spring security oauth2 to use google authentication for a specified endpoint which is /google/login.
With following security configurations everything is working perfectly.
#Configuration
public class SecurityConfigure extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/**")
.and()
.authorizeRequests().antMatchers("/ldap/login").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.oauth2Login();
}
}
But I need to specify only /google/login endpoint to authenticate with oauth2. Therefore I specified it like this.
#Configuration
public class SecurityConfigure extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers().antMatchers("/google/**")
.and()
.authorizeRequests().antMatchers("/ldap/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.oauth2Login();
}
}
with this security configuration http://localhost:8080/google/login endpoint call redirects to another endpoint called http://localhost:8081/oauth2/authorization/google which is I haven't defined.
Please help me to overcome this problem. Thank you.
This configuration works for me. I had to allow all endpoints that were redirecting while Google's authentication process was running. 
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.requestMatchers().antMatchers("/google/**","/oauth2/authorization/google","/login/oauth2/code/google")
.and()
.authorizeRequests().antMatchers("/ldap/**").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.oauth2Login();
}

Custom Authentication Entrypoint not being called on failed Authentication

I have setup an OAUTH Authorization server that's supposed to allow clients request for tokens. It's also supposed to allow admin users carry out other operations.
In my Web Security Configuration:
#Configuration
#EnableWebSecurity
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
private #Autowired CustomAuthenticationProvider authenticationProvider;
private #Autowired CustomAuthenticationEntryPoint entryPoint;
#Override
#Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().httpBasic().and().cors().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(entryPoint)
.defaultAuthenticationEntryPointFor(entryPoint, new AntPathRequestMatcher("/api/v1/**"));
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
Ideally, when an admin user tries to call any endpoint under "/api/v1/**", they should be authenticated - and in fact, they are.
The issue now is, when authentication fails, the authentication entry endpoint is ignored. I don't understand why this is.
I even included the "default authentication entry point for" just to see if that would help, but it didn't.
Please, how do I resolve this?
After playing around with the http security configuration, I took inspiration from this article (https://www.baeldung.com/spring-security-basic-authentication) and changed it to:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().cors().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/oauth/token").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic().authenticationEntryPoint(entryPoint);
}
Honestly, I don't know why what I had before wasn't working. Plenty of people have posted that as the solution to problems about entry end points. But I guess maybe something has changed in Spring that I'm not aware of.

obtain request parameter in Spring security Filter

Can someone help in in obtaining request parameter
in WebsecurityConfig Httpsecurity configure method ? I need to extract the request parameter in the below case acr=loa3 that is coming from request
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.maximumSessions(1)
.expiredUrl(this.uiUri + "/expired")
.maxSessionsPreventsLogin(true)
.and()
.invalidSessionUrl(this.uiUri + "/expired")
.and()
.csrf().disable().cors()
.and()
.authorizeRequests()
.antMatchers("/expired").permitAll()
.anyRequest().authenticated()
.and()
//Can some one help me here on how to extract request param coming in the url for example xyz.com/login?acr=loa3 ? I need to send that as acr value before the configureOIDCfilter executes
.addFilterBefore(configureOIDCfilter(http, acrValue),
AbstractPreAuthenticatedProcessingFilter.class)
.exceptionHandling().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint(this.redirectUri));
}
}
#Bean
public OIDCAuthenticationFilter configureOIDCfilter(HttpSecurity http, String acrValue) throws Exception {
OIDCAuthenticationFilter filter = new OIDCAuthenticationFilter();
StaticSingleIssuerService issuerService = new StaticSingleIssuerService();
issuerService.setIssuer(issuerUrl);
filter.setServerConfigurationService(new DynamicServerConfigurationService());
StaticClientConfigurationService clientService = new StaticClientConfigurationService();
RegisteredClient client = new RegisteredClient();
client.setClientId(clientId);
client.setDefaultACRvalues(ImmutableSet.of(acrValue));
return filter;
}
What you showed in your code is configuration. This is done at startup time and cannot catch any request parameters at this time. However, if you want to need to do something by request, you may want to implement a filter as I wrote in my recent blog post.
You could extend from a filter like this:
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
public MyAuthenticationFilter(AuthenticationManager authenticationManager) {
this.setAuthenticationManager(authenticationManager);
}
}
Then, try to find what methods you want to override. In example:
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
...
}
In the above method you can access the http request parameters.
This filter needs to be added to your configuration as well:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilter(new MyAuthenticationFilter()).
}
A filter will be called for any request and is the only way to receive request parameters (to my knowledge).

Providing custom OAuth2AccessTokenResponseClient to spring

I have a demo spring boot app and I would like to configure oauth login as well my own custom token response client.
This is my configuration:
#Configuration
#EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.and()
.oauth2Client()
.authorizationCodeGrant()
.accessTokenResponseClient(customAccessTokenResponseClient());
}
private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> customAccessTokenResponseClient() {
DefaultAuthorizationCodeTokenResponseClient client = new DefaultAuthorizationCodeTokenResponseClient();
client.setRequestEntityConverter(new CustomOAuth2AuthorizationCodeGrantRequestEntityConverter());
return client;
}
}
The login flow is working find, but it looks like my custom token response client is not getting registered. I put a break point in there, but the flow doesn't go through it. It looks like it is still using the defaults.
Am I missing something here or is the order wrong?
Figured out the issue.
The right way to configure is the following:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.oauth2Login()
.tokenEndpoint()
.accessTokenResponseClient(customAccessTokenResponseClient());
}

Resources