Unable to get Swagger ui working with springboot getting white label error (403) - spring-boot

Hello I've been trying to setup swagger to my spring-boot project but I'm getting the white label error when i open the port 8080 in my localhost to open the swagger api
This is the error I get in my browser when I enter http://localhost:8080/swagger-ui.html
Swagger dependencies in my pom.xml:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
SwaggerConfig class:
public class SwaggerConfig {
private static final String SWAGGER_API_VERSION = "1.0";
private static final String LICENSE_TEXT = "License";
private static final String title = "Inhalo REST API";
private static final String description = "RESTful API for Inhalo";
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title(title)
.description(description)
.license(LICENSE_TEXT)
.version(SWAGGER_API_VERSION)
.build();
}
#Bean
public Docket productsApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.pathMapping("/")
.select()
.paths(PathSelectors.regex("/api.*"))
.build();
}
This is my WebSecurity class:
private static final String[] AUTH_WHITELIST = {
// -- swagger ui
"/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**"
// other public endpoints of your API may be appended to this array
};
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL).permitAll()
.antMatchers(SecurityConstants.MEDICINE_ALL, String.valueOf(AUTH_WHITELIST)).permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
// this disables session creation on Spring Security
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
I tried various options but still getting the same white label error

Related

Spring boot app with OAuth 2.0 Azure AD Authentication throws invalid credentials in Azure App Services

I have deployed on Azure App Service. This web app is required authentication. I have config all Authencation base on Azure Document. All most are finished . When I tried Login into App Services I've gotten invalid Credential.
So What I need to do ?
[enter image description here][1]
Java.file
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
#Autowired
ClientRegistrationRepository clientRegistrationRepository;
private OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler() {
OidcClientInitiatedLogoutSuccessHandler successHandler = new OidcClientInitiatedLogoutSuccessHandler(clientRegistrationRepository);
successHandler.setPostLogoutRedirectUri("http://XXXXXX:4200/");
return successHandler;
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", "/swagger-resources/**",
"/");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
http
.authorizeRequests()
.antMatchers("/organisation/**").permitAll()
.anyRequest().authenticated().and()
.logout()
.logoutSuccessHandler(oidcLogoutSuccessHandler())
.invalidateHttpSession(true)
.clearAuthentication(true)
.deleteCookies("JSESSIONID")
.and()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(oidcUserService);
}
application.properties
azure.activedirectory.tenant-id=0ae51e19-07c8-4e4b-bb6d-648ee58410f4
azure.activedirectory.client-id=232c2998-f0d1-4062-b4fa-33abd0d6af87
azure.activedirectory.client-secret=###
spring.main.allow-bean-definition-overriding=true
pom.file
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-oauth2-client -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
<version>2.7.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.azure.spring/spring-cloud-azure-starter-active-directory -->
<dependency>
<groupId>com.azure.spring</groupId>
<artifactId>spring-cloud-azure-starter-active-directory</artifactId>
<version>4.3.0</version>
</dependency>

401 unauthorized page for swagger-ui

I have a problem with springfox in particular with swagger-ui. I have added this dependencies of springfox in my pom.xml:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
but when I reach swagger-ui with the url localhost:8889/app/swagger-ui.html it come back to me error 401 (my context path is '/app' and my web server start on port 8889(http)). I have also tried with the following url:
localhost:8889/app/swagger-ui
localhost:8889/swagger-ui.html
localhost:8889/swagger-ui
but the result is always the same. I have tried to reach the localhost:8889/app/v2/api-docs and this works fine (I see the json value not in human format), so swagger is working
I have configured a class of configuration for swagger in this way:
#Configuration
#EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer{
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.apiInfo(this.apiInfo())
.useDefaultResponseMessages(false);
}
private ApiInfo apiInfo() {
ApiInfoBuilder apiInfoBuilder = new ApiInfoBuilder();
apiInfoBuilder.title("REST API");
apiInfoBuilder.description("REST API GENERATION");
apiInfoBuilder.version("1.0.0");
apiInfoBuilder.license("GNU GENERAL PUBLIC LICENSE, Version 3");
apiInfoBuilder.licenseUrl("https://www.gnu.org/licenses/gpl-3.0.en.html");
return apiInfoBuilder.build();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/api/v2/api-docs", "/v2/api-docs");
registry.addRedirectViewController("/api/swagger-resources/configuration/ui", "/swagger-resources/configuration/ui");
registry.addRedirectViewController("/api/swagger-resources/configuration/security", "/swagger-resources/configuration/security");
registry.addRedirectViewController("/api/swagger-resources", "/swagger-resources");
}
}
I have configured also a spring security class and I have modified the configure method to ignore this request pattern:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#PropertySource(encoding = "UTF-8", value = {"classpath:commons-web-
config.properties"}, ignoreResourceNotFound = false)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
private TokenAuthenticationProvider authenticationProvider;
private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("/public/login/login-user")
);
private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
#Override
public void configure(WebSecurity web) {
web
.ignoring()
.requestMatchers(PUBLIC_URLS);
web
.ignoring()
.antMatchers("/v2/api-docs/**", "/swagger-ui/**", "/swagger-ui.html", "/public/**", "/websocket/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception{
http
.sessionManagement().sessionCreationPolicy(STATELESS)
.and()
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/protected/my-controller")
.hasAnyRole("SUPER-ADMIN","ADMIN","USER")
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
.and()
.authenticationProvider(authenticationProvider)
.addFilterBefore(restAuthenticationFilter(), AnonymousAuthenticationFilter.class)
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin().disable()
.httpBasic().disable()
.logout().disable();
}
#Bean
public AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(FORBIDDEN);
}
#Bean
public TokenAuthenticationFilter restAuthenticationFilter() throws Exception {
TokenAuthenticationFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(successHandler());
return filter;
}
#Bean
public SimpleUrlAuthenticationSuccessHandler successHandler() {
SimpleUrlAuthenticationSuccessHandler successHandler = new SimpleUrlAuthenticationSuccessHandler();
successHandler.setRedirectStrategy(new NoRedirectStrategy());
return successHandler;
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public FilterRegistrationBean<TokenAuthenticationFilter> disableAutoRegistration(TokenAuthenticationFilter filter) {
FilterRegistrationBean<TokenAuthenticationFilter> registration = new FilterRegistrationBean<TokenAuthenticationFilter>(filter);
registration.setEnabled(false);
return registration;
}
}
I can't find the error. I believe it is in the spring security config class. Can anyone help me?
P.S. My spring boot version is 2.4.5

Swagger-ui + Spring Security => localhost:8080/swagger-ui.html <= Not Found 404

I've been doing some investment over this but i couldn't get anywhere, here is my current situation:
1. I'm using Spring Boot + Spring Security and here are my configurations:
.
.
.
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
#Autowired
private UserRepository userRepository;
#Autowired
public WebSecurityConfig(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
};
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests(authorize -> {
authorize
.antMatchers("/h2-console/**").permitAll() //do not use in production!
.antMatchers("/", "/webjars/**", "/login/**", "/resources/**", "/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**").permitAll();
} )
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic()
.and().csrf().ignoringAntMatchers("/h2-console/**", "/api/**");
http.headers().frameOptions().sameOrigin();
};
application.properties:
server.ssl.key-store: classpath:springboot.p12
server.ssl.key-store-password:password
server.ssl.key-store-type: pkcs12
server.ssl.key-alias: springboot
server.ssl.key-password: password
Swagger configuration:
#Configuration
#EnableSwagger2
public class SwaggerConfig { //} extends WebMvcConfigurationSupport {
#Bean
public Docket api(){
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("enide.logicon.backend.controllers"))
.paths(PathSelectors.any())
.build()
.apiInfo(metaData());
}
.
.
.
Own-generated SSL Certificate up&running, generated to fill the
"editor.swagger.io" https requests needs & to make Basic Auth more secure.
.
.
.
WHY DOES NOT FOUND THE SWAGGER-UI.HTML PAGE? here you have my dependencies:
.
.
.
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
.
.
.
**
Also Allowed all paths without need to log in with
antMatchers("/**").permitAll() This allows "editor.swagger.io" to
retrieve data from the API but not /swagger-ui.html, any ideas?
**
Well don't know why that -1 on my question, the answer was there.
What worked for me was changing the dependencies for this one:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

Spring Boot 2.5.3 OAuth2 - Auth-Server and Webservice separate, Login error

Following the example on https://developer.okta.com/blog/2019/03/12/oauth2-spring-security-guide using the projects Create an OAuth 2.0 Server and Build Your Client App I cannot get it running without error.
I don't use Thymeleaf, as my Webservice returns data, not a page.
OAuth 2.0 Server project
#SpringBootApplication
#EnableResourceServer
public class Demo2Application {
public static void main(String[] args) {
SpringApplication.run(Demo2Application.class, args);
}
}
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
public AuthorizationServerConfig(PasswordEncoder passwordEncoder) {
this.passwordEncoder = passwordEncoder;
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("abcd")
.secret(passwordEncoder.encode("fDw7Mpkk5czHNuSRtmhGmAGL42CaxQB9"))
.authorizedGrantTypes("authorization_code")
.scopes("user_info")
.autoApprove(true)
.redirectUris("http://localhost:8082/login/oauth2/code/");
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");;
}
}
#Configuration
#Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("john")
.password(passwordEncoder().encode("doe"))
.roles("USER");
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
#RestController
public class UserController {
#GetMapping("/user/me")
public Principal user(Principal principal) {
return principal;
}
}
application.properties
server.port=8090
pom.xml
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
I omit the context path, which the project originally uses.
Webservice project
#RestController
public class MyRESTController {
#GetMapping("/securedPage")
public String securedPage(Principal principal) {
return "securedPage";
}
#GetMapping("/")
public String index(Principal principal) {
return "index";
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests()
.antMatchers("/", "/login**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
application.properties
server.port=8082
server.servlet.session.cookie.name=UISESSION
spring.security.oauth2.client.registration.custom-client.client-id=abcd
spring.security.oauth2.client.registration.custom-client.client-secret=fDw7Mpkk5czHNuSRtmhGmAGL42CaxQB9
spring.security.oauth2.client.registration.custom-client.client-name=Auth Server
spring.security.oauth2.client.registration.custom-client.provider=custom-provider
spring.security.oauth2.client.registration.custom-client.scope=user_info
spring.security.oauth2.client.registration.custom-client.redirect-uri=http://localhost:8082/login/oauth2/code/
spring.security.oauth2.client.registration.custom-client.client-authentication-method=basic
spring.security.oauth2.client.registration.custom-client.authorization-grant-type=authorization_code
spring.security.oauth2.client.provider.custom-provider.authorization-uri=http://localhost:8090/oauth/authorize
spring.security.oauth2.client.provider.custom-provider.token-uri=http://localhost:8090/oauth/token
spring.security.oauth2.client.provider.custom-provider.user-info-uri=http://localhost:8090/user/me
spring.security.oauth2.client.provider.custom-provider.user-name-attribute=name
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
When running both porojects, with localhost:8082 in the web browser I get index as response.
With localhost:8082/securedPage I get redirected to the login page, entering username john and password doe I get the following error page:
Login with OAuth 2.0
[invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 404 : [{"timestamp":"2021-07-30T07:58:54.529+00:00","status":404,"error":"Not Found","path":"/user/me"}]
Auth Server
Don't know what the error is causing. Looks like it is related to the Webservice application property and the URL to the UserController in the OAuth 2.0 Server project
spring.security.oauth2.client.provider.custom-provider.user-info-uri=http://localhost:8090/user/me
One additional question is:
Can the login form be avoided? The credentials passed somehow.
If the client is not the web browser but some other application which has no UI. Or perhaps curl. I also have MockMvc tests, so far it was Basic Auth, now OAuth2, how will be those affected?

Spring Boot Swagger UI - Protect UI Access

I added a simple swagger UI to my existing springboot REST API by adding the following class to my code:
#EnableSwagger2
#Configuration
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.paths(PathSelectors.regex("/v1.*"))
.build()
.pathMapping("/")
.apiInfo(metadata());
}
private ApiInfo metadata() {
return new ApiInfoBuilder()
.title("My awesome API")
.description("Some description")
.version("1.0")
.build();
}
}
My problem is that the API should be public, but the swagger docs should not. I would like a way of requesting authentication to the swagger documentation, anyone knows any simple way of achieving this?
I tried to google it but I could only find OAth stuff, but this is authentication for the endpoints not the swagger documentation...
Swagger docs will be available at /v2/api-docs endpoint when swagger integrated with spring boot application.
Inorder to protect the resource , make use of spring security and restrict the endpoint for accessing the docs
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Security configuration : restricting access to the endpoint only to the users
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/v2/api-docs").authenticated()
.and()
.httpBasic();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
Additionally, swagger-ui.html can also be secured based on the requirement.
Here's a an alternative solution. This is about limiting access to swagger only in development/qa environment. The production environment will not have access to Swagger. I am using a property (prop.swagger.enabled) as a flag to bypass spring security authentication for swagger-ui only in development/qa environment.
#Configuration
#EnableSwagger2
public class SwaggerConfiguration extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
#Value("${prop.swagger.enabled:false}")
private boolean enableSwagger;
#Bean
public Docket SwaggerConfig() {
return new Docket(DocumentationType.SWAGGER_2)
.enable(enableSwagger)
.select()
.apis(RequestHandlerSelectors.basePackage("com.your.controller"))
.paths(PathSelectors.any())
.build();
}
#Override
public void configure(WebSecurity web) throws Exception {
if (enableSwagger)
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (enableSwagger) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
}
I use this boiler plater to configure and secure swagger
#Configuration
#EnableSwagger2
public class SwaggerConfig extends WebSecurityConfigurerAdapter {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**")
.authenticated().and().httpBasic();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
}

Resources