Class file for org.springframework.security.authentication.encoding.PasswordEncoder not found - spring

I've made a simple restAPI with Spring-boot and spring security, implementing Basic Authentication. I want to use inMemoryAuthentication, and bcryptPasswordEncoder, but for some reason my compiler is looking for the passwordEncoder in the wrong place, See title vs security.crypto.password.PasswordEncoder.
My Basic auth looks like this:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
Configuration
#EnableWebSecurity
public class BasicAuthConfig extends WebSecurityConfigurerAdapter {
// Authentication : User --> Roles
// NoOpPasswordEncoder has been deprecated in Spring security so {noop} is being used to avoid errors
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("user1")
.password("{noop}secret1")
.roles("USER")
.and().withUser("admin1")
.password("{noop}secret1")
.roles("USER", "ADMIN");
}
// Authorization : Role -> Access
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and().authorizeRequests()
.antMatchers("/tokenservice/**")
.hasRole("USER")
.antMatchers("/**")
.hasRole("ADMIN")
.and().csrf()
.disable()
.headers()
.frameOptions()
.and().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
I get this error when trying to compile:
Error:(21, 7) java: cannot access org.springframework.security.authentication.encoding.PasswordEncoder
class file for org.springframework.security.authentication.encoding.PasswordEncoder not found
Disregard the {noop} in front of the password. is there for testing without passwordEncoder.
I'm very new to Spring and gradle, and java all in all. Could i be using a wrong version of Spring? If thats the case, how do i fix it?

If your using latest spring-security version, you should find PasswordEncoder class in org.springframework.security.crypto.password package.
PasswordEncoder in package org.springframework.security.authentication.encoding.PasswordEncoder has been deprecated

Looks like it is caused by incompatible versions of spring-security-config (4.0.2.RELEASE) and spring-security-core (5.0.3.RELEASE)
The newer version of spring-security-core only accepts org.springframework.security.crypto.password.PasswordEncoder
I fixed this by downgrading spring-security-core to match spring-security-config.

It was due to version mismatch in spring security config jar.
When you are upgrading your spring version from 4.x to 5.x , this issue occurs as PasswordEncoder class object is restricted in use.
In spring-security-config 4.x version in AbstractDaoAuthenticationConfigurer the passwordEncoder() is overloading both the org.springframework.security.crypto.password.PasswordEncoder and org.springframework.security.authentication.encoding.PasswordEncoder, where else in spring-security-config 5.x it is only the org.springframework.security.crypto.password.PasswordEncoder
spring-security-config 4.x
public C passwordEncoder(org.springframework.security.crypto.password.PasswordEncoder passwordEncoder)
{
this.provider.setPasswordEncoder(passwordEncoder);
return this;
}
public C passwordEncoder(org.springframework.security.authentication.encoding.PasswordEncoder passwordEncoder)
{
this.provider.setPasswordEncoder(passwordEncoder);
return this;
}
spring-security-config 5.x
import org.springframework.security.crypto.password.PasswordEncoder;
public C passwordEncoder(PasswordEncoder passwordEncoder)
{
this.provider.setPasswordEncoder(passwordEncoder);
return this;
}
Most probably solution is to downgrade your spring version to 4.x.

Related

401 sent to angular frontend by spring boot backend after successful oauth2 authetication with google

Spring Boot rest api in the back and angular in the front.
Hi all, I have a problem after successful oauth2 authentication with google.
In srping boot debug I can read the following:
o.s.web.cors.DefaultCorsProcessor : Skip: response already contains "Access-Control-Allow-Origin".
Then a 401 is sent to angular with full authentication required to access /api/user/ resource which is the root to access user details in the backend side.
WebConfig.java
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
#Configuration
public class WebConfig implements WebMvcConfigurer {
private final long MAX_AGE_SECS = 3600;
#Override
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("*")
.allowedMethods(
"HEAD",
"OPTIONS",
"GET",
"POST",
"PUT",
"PATCH",
"DELETE"
)
.maxAge(MAX_AGE_SECS);
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver() {
final CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(Locale.ENGLISH);
return cookieLocaleResolver;
}
#Override
public Validator getValidator() {
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource());
return validator;
}
}
SecurityConfig.java
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.client.RestTemplate;
import com.springboot.dashboard.security.jwt.TokenAuthenticationFilter;
import com.springboot.dashboard.security.oauth2.DashBoardOAuth2UserService;
import com.springboot.dashboard.security.oauth2.DashBoardOidcUserService;
import com.springboot.dashboard.security.oauth2.HttpCookieOAuth2AuthorizationRequestRepository;
import com.springboot.dashboard.security.oauth2.OAuth2AccessTokenResponseConverterWithDefaults;
import com.springboot.dashboard.security.oauth2.OAuth2AuthenticationFailureHandler;
import com.springboot.dashboard.security.oauth2.OAuth2AuthenticationSuccessHandler;
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(
prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private DashBoardOAuth2UserService dashBoardOAuth2UserService;
#Autowired
private DashBoardOidcUserService dashBoardOidcUserService;
#Autowired
private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;
#Autowired
private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable()
.formLogin()
.disable()
.httpBasic()
.disable()
.exceptionHandling()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers("/", "/error", "/api/all", "/api/auth/**", "/oauth2/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.authorizationEndpoint()
.authorizationRequestRepository(cookieAuthorizationRequestRepository())
.and()
.redirectionEndpoint()
.and()
.userInfoEndpoint()
.oidcUserService(dashBoardOidcUserService)
.userService(dashBoardOAuth2UserService)
.and()
.tokenEndpoint()
.accessTokenResponseClient(authorizationCodeTokenResponseClient())
.and()
.successHandler(oAuth2AuthenticationSuccessHandler)
.failureHandler(oAuth2AuthenticationFailureHandler);
// Add our custom Token based authentication filter
http.addFilterBefore(
tokenAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class
);
}
#Bean
public TokenAuthenticationFilter tokenAuthenticationFilter() {
return new TokenAuthenticationFilter();
}
/*
* By default, Spring OAuth2 uses
* HttpSessionOAuth2AuthorizationRequestRepository to save the authorization
* request. But, since our service is stateless, we can't save it in the
* session. We'll save the request in a Base64 encoded cookie instead.
*/
#Bean
public HttpCookieOAuth2AuthorizationRequestRepository cookieAuthorizationRequestRepository() {
return new HttpCookieOAuth2AuthorizationRequestRepository();
}
// This bean is load the user specific data when form login is used.
#Override
public UserDetailsService userDetailsService() {
return userDetailsService;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
#Bean(BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> authorizationCodeTokenResponseClient() {
OAuth2AccessTokenResponseHttpMessageConverter tokenResponseHttpMessageConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
tokenResponseHttpMessageConverter.setTokenResponseConverter(
new OAuth2AccessTokenResponseConverterWithDefaults()
);
RestTemplate restTemplate = new RestTemplate(
Arrays.asList(
new FormHttpMessageConverter(),
tokenResponseHttpMessageConverter
)
);
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
tokenResponseClient.setRestOperations(restTemplate);
return tokenResponseClient;
}
}
Thanks in advance for your help.
oauth2 login successful cause user data is successfully to database, but can access to full authentication resource.
WebSecurityConfigurerAdapter is deprecated, don't use it (it is not even there any more in spring-boot 3). Expose a SecurityFilterChain bean instead:
#Bean
SecurityFilterChain filterChain(HttpSecurity http) {
// http configuration
return http.build();
}
Resource-server (REST API)
Instead of writing all of spring-boot-starter-oauth2-resource-server security configuration in java #Configuration (CSRF, CORS, JWT decoder or token introspector, authorities mapping, public routes), you can use one of the spring-boot starters here:
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<!-- replace "webmvc" with "weblux" if your app is reactive -->
<!-- replace "jwt" with "introspecting" to use token introspection instead of JWT decoding -->
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<!-- this version is to be used with spring-boot 3.0.0-RC2, use 5.x for spring-boot 2.6.x or before -->
<version>6.0.5</version>
</dependency>
#EnableMethodSecurity
public static class WebSecurityConfig { }
com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/master
com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,ressource_access.client-id.roles
com.c4-soft.springaddons.security.cors[0].path=/**
Client (Angular app)
Use an OAuth2 client library. My favorite for Angular is angular-auth-oidc-client. It will save you tones of efforts to:
redirect users to authorisation-server for login
handle redirect back from authorization-server with authorization-code
exchange authorization-code for tokens (access-token of course, but also refresh and ID tokens if you requested offline_access and openid scopes)
auto-refresh access tokens before it expires (if you got a refresh-token)
automatically authorize request matching configured patterns (add Authorization Bearer header with access-token)
provide with Angular route guards
...
Authorization-server
Unless you deploy your resource-server to Google cloud, it is likely it can't use Google authorization-server directly. You might use an other authorization-server capable of identity federation in front of it. Keycloak does it pretty well:
run a Keycloak instance and configure it with Google as identity provider
configure your resource-server to use Keycloak as authorization-server (as done in code above)
configure Angular to use Keycloak as authorization-server too
I refer to Keycloak here, but most serious OIDC providers (either on premize or SaaS like Auth0, Okta, etc.) support "social" login and will allow Google users to login (as well as Facebook, Github, Tweeter, etc.)

How single authentication can work for multiple server nodes in Spring Security

I am using weblogic for deploying my spring boot application, and my same application is deployed on multiple nodes.
For example the two node in which the application is deployed is 9001 and 9002.
With basic security even if I am authenticated on the Node 9001 and trying to access the same URL on second node i.e on 9002, I am again getting redirected again to spring login page for authentication.
I want that once I authenticate using username and password on any node. I need not to authenticate again, Even if I am requesting to any other node.
Any kind of clue or help will be appreciated.
Thanks in advance.
The Security configuration file is
package com.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("test")
.password("{noop}test")
.authorities("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/userdetail").authenticated()
.anyRequest().permitAll()
.and()
.formLogin();
}
}
In my case it worked for both node when I enabled RedisHttpSession.
Below is the code which worked for me.
#Configuration
#EnableRedisHttpSession
public class RedisConfig {
#Bean
public JedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
}
}
also in pom.xml I needed to make two dependencies(For Spring boot).
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
You can also take reference about EnableRedisHttpSession from spring docs, and about spring session from
https://docs.spring.io/spring-session/docs/current/api/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSession.html
https://www.baeldung.com/spring-session

Spring Security WebFlux IP Whitelist

In the latest Spring Security which leverages WebFlux, the security config works like below,
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http.authorizeExchange().pathMatchers("/**") ....
Before there is a method hasIpAddress("xxx.xxx.xxx.xxx") we can use to config IP whitelist, now it's gone.
How to specify IP whitelist for new Spring Security Webflux?
Based on idea from #özkan pakdil below, here is my code, but IP filter does not work - The request from IP which is not on whitelist still can go through.
private Mono<AuthorizationDecision> isAuthorizedIP(Mono<Authentication> authentication, AuthorizationContext context) {
String ip = context.getExchange().getRequest().getRemoteAddress().getAddress().toString().replace("/", "");
return authentication.map((a) -> new AuthorizationDecision(
ipWhiteList.contains(ip)));
}
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
http.authorizeExchange().anyExchange().access(this::isAuthorizedIP).and().oauth2Login();
return http.build();
}
Took me a while to figure out but finally, I found a way it works. please check https://github.com/ozkanpakdil/spring-examples/tree/master/webflux-ip-whitelist and tell me if that does not help.
simply you can define WebSecurityConfig like this
import org.springframework.context.annotation.Bean;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
#EnableWebFluxSecurity
public class WebSecurityConfig {
ArrayList<String> whiteListIp = new ArrayList();
public WebSecurityConfig() {
whiteListIp.add("0:0:0:0:0:0:0:1");
whiteListIp.add("192.168.1.1");
whiteListIp.add("127.0.0.1");
}
#Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
http
.authorizeExchange()
.anyExchange()
.access(this::whiteListIp)
.and()
.httpBasic();
return http.build();
}
private Mono<AuthorizationDecision> whiteListIp(Mono<Authentication> authentication, AuthorizationContext context) {
String ip = context.getExchange().getRequest().getRemoteAddress().getAddress().toString().replace("/", "");
return authentication.map((a) -> new AuthorizationDecision(a.isAuthenticated()))
.defaultIfEmpty(new AuthorizationDecision(
(whiteListIp.contains(ip)) ? true : false
));
}
}
and have your IP whitelisted.

How to set WebSSOProfileConsumerImpl in your Spring Configuration file

I am facing issue of specifying WebSSOProfileConsumerImpl to my Spring Configuration file. I am trying to modify responseSkew in this bean but after adding configuration for WebSSOProfileConsumerImpl I am getting MetadataManager issue
APPLICATION FAILED TO START
Description:
Parameter 0 of method setMetadata in org.springframework.security.saml.websso.AbstractProfileBase required a bean of type 'org.springframework.security.saml.metadata.MetadataManager' that could not be found.
Action:
Consider defining a bean of type 'org.springframework.security.saml.metadata.MetadataManager'
Can anyone help me in resolving this issue?
I have already gone through the link : http://docs.spring.io/spring-security-saml/docs/current/reference/html/configuration-advanced.html but it does not specify how to set this in configuration.
My Code
import static org.springframework.security.extensions.saml2.config.SAMLConfigurer.saml;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.saml.websso.WebSSOProfileConsumer;
import org.springframework.security.saml.websso.WebSSOProfileConsumerImpl;
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("${security.saml2.metadata-url}")
String metadataUrl;
#Value("${server.ssl.key-alias}")
String keyAlias;
#Value("${server.ssl.key-store-password}")
String password;
#Value("${server.port}")
String port;
#Value("${server.ssl.key-store}")
String keyStoreFilePath;
#Value("${security.saml2.responseSkew}")
int responseSkew = 0;
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/saml*").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.serviceProvider()
.keyStore()
.storeFilePath(this.keyStoreFilePath)
.password(this.password)
.keyname(this.keyAlias)
.keyPassword(this.password)
.and()
.protocol("https")
.hostname(String.format("%s:%s", "localhost", this.port))
.basePath("/")
.and()
.identityProvider()
.metadataFilePath(this.metadataUrl).and();
/* Map<? extends Object, Object> sharedObjects = new Map<? extends Object>, Object>(http.getSharedObjects());
sharedObjects.put(WebSSOProfileConsumer.class, webSSOprofileConsumerImpl());*/
}
#Bean
#Qualifier("webSSOprofileConsumer")
public WebSSOProfileConsumer webSSOprofileConsumerImpl() {
WebSSOProfileConsumerImpl consumerImpl = new WebSSOProfileConsumerImpl();
consumerImpl.setResponseSkew(this.responseSkew);
return consumerImpl;
}
}
If you do not need the WebSSOProfileConsumer to be accessible as a bean to the rest of the application, you can create it inside the configure method like this:
#Override
protected void configure(final HttpSecurity http) throws Exception {
WebSSOProfileConsumerImpl consumerImpl = new WebSSOProfileConsumerImpl();
consumerImpl.setResponseSkew(this.responseSkew);
http
.authorizeRequests()
.antMatchers("/saml*").permitAll()
.anyRequest().authenticated()
.and()
.apply(saml())
.serviceProvider()
.ssoProfileConsumer(consumerImpl) // <-- added here
.keyStore()
// Your method continues as before
I do not remember the exact reason regular wiring fails in your case, but the gist of it is that configure sets up a builder object rather than regular beans. Normally the ServiceProviderBuilder provides the MetadataManager needed by your WebSSOProfileConsumer during its build step, but if you autowire the profile consumer you won't get the MetadataManager provided for you since your autowired object is assumed to be complete already.
(I learned this when looking for a way to configure the max authentication age, since the two hour default in spring-security-saml in some cases is lower than the defaults used by identity providers. This effectively locks your users out of your application until the identity provider's max authentication age has passed.)

401 unauthorized page for swagger?

I am enable swagger2 by #EnableSwagger2. However, when I try to hit "/swagger-ui.html", it first hit my Authentication Filter. Then, I wrote the following code to bypass the authentication check
String resourcePath = new UrlPathHelper().getPathWithinApplication(httpRequest);
if ("/swagger-ui.html".equalsIgnoreCase(resourcePath)) {
filterChain.doFilter(request, response);
}
I can see the filterChain.doFilter(request, response); was hit. However, when I let the debug go, it returns a page with information below
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Apr 04 15:41:50 EDT 2018
There was an unexpected error (type=Unauthorized, status=401).
No message available
Any idea, guys?
I encountered the same issue in my project and discovered this solution, so first add this config file to the project
package bla.bla.conf;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#Configuration
#EnableSwagger2
public class Swagger2Config {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors
.basePackage("bla.bla.controllers"))
.paths(PathSelectors.any())
.build();
}
}
and then add this code block to you WebSecurityConfig
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().mvcMatchers(HttpMethod.OPTIONS, "/**");
web.ignoring().mvcMatchers("/swagger-ui.html/**", "/configuration/**", "/swagger-resources/**", "/v2/api-docs","/webjars/**");
}
my problem fixed
source : swagger.io
Think you can add your ownWebSecurityConfig extends WebSecurityConfigurerAdapter, than override configure(WebSecurity web) method and there put web.ignoring().antMatchers("/swagger-ui.html") ofc annotate that class with #Configuration
I have the same error and I add this code inside the class websecurityConfig
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll() // permit the class of test
.antMatchers("/**").permitAll() // permit all the routers after swagger-ui.html
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
As answered by Georgi Stoyanov , adding that much code removed Whitelabel Error Page error but my swagger UI home page was blank as there was 401 issue in loading some css & js files.
Swagger-ui with Spring security
Also, important point that I want to mention is that my swagger UI was working for Weblogic deployment without above code (only HttpSecurity override was enough ) and I was facing issue only when running app in embedded tomcat.
Spring Boot Version : 1.5.2.RELEASE
SpringFox Version 2.8.0
So I had to made code changes as answered by me in linked question to load all CSS & JS files also.
I had the same problem and this was my solution.
if do you have a Spring security config, you must to give authorization at all urls that swagger needs
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST,"/api/loggin").permitAll()
.antMatchers(HttpMethod.GET,"/swagger-resources/**").permitAll()
.antMatchers(HttpMethod.GET,"/swagger-ui/**").permitAll()
.antMatchers(HttpMethod.GET,"/v2/api-docs").permitAll()
.anyRequest()
.authenticated();
}
and in your class main you shuld to add this notation
#EnableSwagger2
and finally in yor pom.xml this dependencies.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
for use http://localhost:8090/swagger-ui/

Resources