Getting error as "The method filterChain(HttpSecurity) of type SecurityConfig must override or implement a supertype method" - spring

I am getting error as
The method filterChain(HttpSecurity) of type SecurityConfig must override or implement a supertype method
My code are
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig{
#Autowired private AuthSecurity filter;
#Bean
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf().disable()
.httpBasic().disable()
.cors()
.and()
.authorizeRequests()
.antMatchers("/prod/api/v1/open/status").permitAll()
.antMatchers("/prod/api/v1/open/**").authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) ->
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized")
)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilter(filter);
return http.build();
}
}
AuthSecurity.java
#Component
public class AuthSecurity extends OncePerRequestFilter{
#Override
#ResponseBody
public void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException
{
String authHeader = response.getHeader("Authorization");
if(authHeader != null && authHeader.length()>0 && authHeader.startsWith("Bearer "))
{
String jwt = authHeader.substring(7);
if(jwt == null || jwt.length()==0){
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid Token in Bearer Header");
}
else
{ if(SecurityContextHolder.getContext().getAuthentication() == null && jwt.equals("asd123")){ SecurityContextHolder.createEmptyContext();
}
else{
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid Token");
}
}
}
}
I just want to check if the Header token matches my personal token and if it is allow it to visit other endpoints.
The error log is
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method filterChain in com.company.framework.Security.SecurityConfig required a bean of type 'org.springframework.security.config.annotation.web.builders.HttpSecurity' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.security.config.annotation.web.builders.HttpSecurity' in your configuration.
I have just started working on Spring boot, so I am not able to understand the things that are going back in there. If you have any ideas or documentation to easily understand all these things, iT would be great.
Before questioning, I looked through
Spring Security: Upgrading the deprecated WebSecurityConfigurerAdapter in Spring Boot 2.7.0
But the solution there isn't working for me.

Related

How to configure Spring-Security (Spring 6) for not having Filters executed on unsecured routes?

somewhat related to this other stackoverflow topic which doesn't give a proper solution nor is applicable to Spring 6 (Spring Boot 3).
I came up with a basic spring-boot app to make my case.
There is a controller with two end-points, where one must be secured and the other accessible.
#RestController
public class TestController {
#GetMapping("/secured-api")
public String securedApi() {
return "secured";
}
#GetMapping("/public/open-api")
public String openApi() {
return "open";
}
}
Security context as follow, imagine that MyFilter is doing something fancy, e.g: validating a JWT token and firing an exception if the token is invalid / expired.
#Configuration
public class ComponentSecurityContext {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.addFilterAt(new MyFilter(), BasicAuthenticationFilter.class)
.authorizeHttpRequests(customizer -> customizer
.requestMatchers(new AntPathRequestMatcher("/public/**"))
.permitAll()
.anyRequest()
.authenticated())
.build();
}
public static class MyFilter extends OncePerRequestFilter {
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
System.out.println("Filter is called for uri: " + request.getRequestURI());
// performs some authentication
filterChain.doFilter(request, response);
}
}
}
Executing the following two curls on the server
curl http://localhost:9003/public/open-api
curl http://localhost:9003/secured-api
is triggering MyFilter
Filter is called for uri: /public/open-api
Filter is called for uri: /secured-api
I would expect MyFilter to be called only for secured end-points, I don't care if an expired token is used to access an unprotected end-point.
Any advise on how to properly wire spring-security to achieve just that?
Working solution where the filter is scoped by the securityMatcher:
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.securityMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher("/public/**")))
.addFilterAt(new MyFilter(), BasicAuthenticationFilter.class)
.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated())
.build();
}

Spring-Security OAUTH2 and PKCE, IdentityServer4 How do I add code_challenge info

I am trying to access Identity Server. When I try to access I get an error that says
MessageTemplate: code_challenge is missing
I have a basic Spring Boot Application. How do I get the app to add in the Code Challenge and code Challenge type.
I have tried to add in this:
#Configuration
public class OAuth2ClientConfiguration {
#Bean
public SecurityWebFilterChain pkceFilterChain(ServerHttpSecurity http, ServerOAuth2AuthorizationRequestResolver resolver) {
http.authorizeExchange(r -> r.anyExchange().authenticated());
http.oauth2Login(auth -> auth.authorizationRequestResolver(resolver));
return http.build();
}
#Bean
public ServerOAuth2AuthorizationRequestResolver pkceResolver(ReactiveClientRegistrationRepository repo) {
DefaultServerOAuth2AuthorizationRequestResolver resolver = new DefaultServerOAuth2AuthorizationRequestResolver(repo);
resolver.setAuthorizationRequestCustomizer(OAuth2AuthorizationRequestCustomizers.withPkce());
return resolver;
}
but that causes an error saying that
Description:
Parameter 0 of method pkceFilterChain in com.landstar.security.poc.securitypoc.config.OAuth2ClientConfiguration required a bean of type 'org.springframework.security.config.web.server.ServerHttpSecurity' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.security.config.web.server.ServerHttpSecurity' in your configuration.
Additional Info
#Configuration
#EnableWebSecurity
public class SecurityConfig {
private static final String[] WHITE_LIST_URLS = {
"/user",
"/helloPublic",
"/register",
"/verifyRegistration*",
"/resendVerifyToken*"
};
#Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf()
.disable()
.authorizeHttpRequests()
.antMatchers(WHITE_LIST_URLS).permitAll()
.antMatchers("/api/**").authenticated()
.and()
.oauth2Login(oauth2login ->
oauth2login.loginPage("/auth2/authorization/landstar"))
.logout(l -> l
.logoutSuccessUrl("/").permitAll()
)
.oauth2Client(Customizer.withDefaults());
return http.build();
}
}
Please, any help.!!! thanks

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).

Spring oauth2 SimpleUrlAuthenticationFailureHandler two redirects on failure

For some reason spring with oauth2 and custom SimpleUrlAuthenticationFailureHandler redirects twice on login failure.
It calls http://localhost:8081/login?error as expected but with a location header http://localhost:8081/login therefore I see an extra redirect.
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/" + URLConstants.LOGIN)
.loginProcessingUrl("/" + URLConstants.LOGIN)
//.failureUrl("/login?error")
.failureHandler(authFailureHandler)
.permitAll();
And SimpleUrlAuthenticationFailureHandler
#Component
public class AuthFailureHandler extends
SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
// some code
saveException(request, exception);
getRedirectStrategy().sendRedirect(request, response, "/login?error");
Above code onAuthenticationFailure pretty much calls same methods as original code in onAuthenticationFailure. I've also tried
super.onAuthenticationFailure(request, response, exception);
But I do get same results (an extra redirect)
If I remove .failureHandler(authFailureHandler) then the code works as expected. Any ideas?
See images attached
Extra redirect - with SimpleUrlAuthenticationFailureHandler
As expected - without SimpleUrlAuthenticationFailureHandler

How to implement Spring Security Ldap authentication using the configurer class correctly?

Hi I'm trying to implement spring's ldap authentication using the WebSecurityConfigurerAdapter class.
So far I can authenticate through the in memory method and even my corp's ldap server, however the latter method I'm only able to authenticate if I pass a hardcoded userDN and password when I create the new context, if I don't create a new context or I don't put the userDN and password, jvm throws me:
Caused by: javax.naming.NamingException: [LDAP: error code 1 - 000004DC: LdapErr: DSID-0C0906E8, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v1db1\u0000]; Remaining name: '/'
My question is, how can I get the user password and userDN from the login form so I can put it in the context? If that is not possible how can I get the context that the password and userDn are?
This is the code that I have:
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication().userSearchFilter("(&(objectClass=user)(sAMAccountName={0}))")
.groupSearchFilter("(&(memberOf:1.2.840.113556.1.4.1941:=CN=DL - DC859 - MIDDLEWARE,OU=Dyn,OU=Dist,OU=Security Groups,OU=POP,DC=pop,DC=corp,DC=local))")
.contextSource(getLdapContextSource());
}
private LdapContextSource getLdapContextSource() throws Exception {
LdapContextSource cs = new LdapContextSource();
cs.setUrl("ldap://tcp-prd.pop.corp.local:389");
cs.setBase("DC=pop,DC=corp,DC=local");
cs.setUserDn("t8951435#pop.corp.local");
cs.setPassword("mypassword");
cs.afterPropertiesSet();
return cs;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
Thank you.
I've finally figured it out from this post. I still don't know how to set the group filters, but at least now I can bind to the server.
#Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider("pop.corp.local",
"ldap://tcp-prd.pop.corp.local:389");
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
#Bean
public LoggerListener loggerListener() {
return new LoggerListener();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
EDIT: I finally found out how to filter by groups. It turns out that they added a setSearchFilter() method in ActiveDirectoryLdapAuthenticationProvider class v3.2.6. As I am using an older version I never knew about this. So I made a copy of the class with the method and just created a buildFilter method to create the filter string that is passed to the setSearchFilter.

Resources