Spring boot swagger configure global headers for an application - spring

I am working on microservices using spring-boot-1.4.5. We are setting few headers in MDC while the interaction between microservices occurred. These headers are common across the microservices/application.There is an interceptor in each application which will check for this headers if it is not present the call will not reach controller. So for everything works fine. The problem is each application or services exposing a swagger-UI(swagger-ui:2.6.1).
I can able to see swagger-ui and all the endpoints in the application but i don't know how to show the global headers field under each endpoint.
How to customise swagger to show these global headers under each endpoint ?
Any help or hint would be appreciable also i browsed google and saw other posts which are not useful or i couldn't grasp the things properly.

To set global parameters, use ParameterBuilder to build springfox.documentation.service.Parameter and set it to globalOperationParameters.
#Bean
public Docket api() {
Parameter headerParam = new ParameterBuilder().name("TenantId").defaultValue("microservices").parameterType("header")
.modelRef(new ModelRef("string")).description("Tenant Identity").required(true).build();
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.globalOperationParameters(Arrays.asList(headerParam))
.select()
.apis(RequestHandlerSelectors.basePackage("com.app"))
.paths(PathSelectors.any())
.build();
}

Related

swagger ui is not showing unused model

Does swagger ui only display models that are used by controllers?
In my spring boot application, I am using swagger 2 to define my api. Few of the models are being used in apis whereas others are not being used directly but I need them in my api doc.
Now when I see the json in swagger editor it displays everything perfectly but swagger ui is only displaying models that are used by controller. Following are my swagger-ui configurations
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.search.controller"))
.paths(PathSelectors.any())
.build();
}
It will helpful if anyone could share some feedback on this. Also is there any other tool that could serve this purpose?
Thanks
You could check the generated json or yaml file:
localhost:8080/v2/api-docs
localhost:8080/v2/api-docs.yaml
Edit it to your liking, and use your own documentation source instead.
(This might help with that:
http://editor.swagger.io)

403 Forbidden Using Springboot When Hitting Okta Userinfo endpoint

I'm trying to set up Okta as a sign on for a set of subpaths in my spring boot app.
I'm configuring the auth resource details with:
#Bean(name = "oktaOAuthClient")
public AuthorizationCodeResourceDetails oktaOAuthAdminClient(#Qualifier("oktaAdminConfiguration") OktaConfigurationProperties oktaAdminCongfig,
ICredentialsApi credentialsApi) {
String redirectUrl = UriComponentsBuilder.fromUriString("http://localhost:8091/")
.path(ConfigurationRequestPaths.ADMINISTRATION_LANDING)
.build(false)
.toUriString();
AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();
client.setClientId(oktaAdminCongfig.getClientId());
client.setClientSecret(oktaAdminCongfig.getClientSecret());
client.setAccessTokenUri(oktaAdminCongfig.getAccessTokenUri());
client.setUserAuthorizationUri(oktaAdminCongfig.getUserAuthorizationUri());
client.setClientAuthenticationScheme(AuthenticationScheme.header);
client.setPreEstablishedRedirectUri(redirectUrl);
client.setScope(OKTA_SCOPES);
client.setUseCurrentUri(false);
client.setScope(OKTA_SCOPES);
return client;
}
These and other settings are found from the application.properties manually and are set as:
okta.admin.clientId={id}
okta.admin.clientSecret={secret}
okta.admin.accessTokenUri=https://dev-{value}.okta.com/oauth2/default/v1/token
okta.admin.userAuthorizationUri=https://dev-{value}.okta.com/oauth2/default/v1/authorize
okta.admin.issuer=https://dev-{value}.okta.com/oauth2/default
okta.admin.userInfoUrl=https://dev-{value}.okta.com/oauth2/default/v1/userinfo
Then I've made a filter with (Note, is the clientId set in the UserTokenInfoServices meant to be the client id from the okta client id/client secret?):
#Bean(name = "oktaFilter")
public Filter oktaFilter(#Qualifier("oktaOAuthClient") AuthorizationCodeResourceDetails oktaOAuthClient,
#Qualifier("oktaOAuthResource") ResourceServerProperties resource,
#Qualifier("oktaOAuthRestTemplate") OAuth2RestTemplate oktaOAuthRestTemplate) {
ExceptionMappingAuthenticationFailureHandler failureHandler = new ExceptionMappingAuthenticationFailureHandler();
failureHandler.setDefaultFailureUrl("/");
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(ConfigurationRequestPaths.ADMINISTRATION_LANDING);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(resource.getUserInfoUri(), oktaOAuthClient.getClientId());
tokenServices.setRestTemplate(oktaOAuthRestTemplate);
filter.setRestTemplate(oktaOAuthRestTemplate);
filter.setTokenServices(tokenServices);
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setUseReferer(true);
filter.setAuthenticationSuccessHandler(successHandler);
filter.setAuthenticationFailureHandler(failureHandler);
return filter;
}
Finally I've set up the WebSecurityConfigurerAdapter with the following:
http.antMatcher("/config/**")
.authorizeRequests()
.antMatchers("/config")
.permitAll()
.anyRequest().authenticated().and()
.exceptionHandling()
.authenticationEntryPoint(oktaLoginHandler)SimpleUrlAuthenticationSuccessHandler(ConfigurationRequestPaths.ADMINISTRATION_LANDING))
.and()
.logout().addLogoutHandler(oktaLogoutHandler).logoutSuccessUrl(externalAccessUrl).permitAll().and()
.addFilterBefore(oktaFilter, BasicAuthenticationFilter.class);
}
The redirect for the subpath works correctly and goes to a sign in page, but I get an error after signing in that warns:
org.springframework.security.authentication.BadCredentialsException: Could not obtain user details from token...Caused by: org.springframework.security.oauth2.common.exceptions.InvalidTokenException:
I believe this likely has to do with getting a 403 when hitting the okta userinfo endpoint:
Request is to process authentication
Retrieving token from https://dev-{value}.okta.com/oauth2/default/v1/token
Encoding and sending form: {grant_type=[authorization_code], code=[{code}], redirect_uri=[http://localhost:8091/config], client_id=[{id}], client_secret=[{secret}]}
HTTP GET https://dev-{value}.okta.com/oauth2/default/v1/userinfo
Accept=[application/json, application/*+json]
Response 403
I've also tried the okta starter but it seems to break when used with another oauth login to github for another set of subpaths in the application. The spring version I'm using doesn't include the .oauthLogin() and other settings for httpsecurity that I've seen some guides on.
edit: Adding my spring dependency list for more clarification:
org.springframework:spring-beans:5.1.20.RELEASE
org.springframework:spring-context:5.1.20.RELEASE
org.springframework:spring-jdbc:5.1.20.RELEASE
org.springframework:spring-tx:5.1.20.RELEASE
org.springframework:spring-web:5.1.20.RELEASE
org.springframework:spring-webmvc:5.1.20.RELEASE
org.springframework:spring-test:5.1.20.RELEASE
org.springframework.boot:spring-boot-actuator:2.1.18.RELEASE
org.springframework.boot:spring-boot-autoconfigure:2.1.18.RELEASE
org.springframework.boot:spring-boot-configuration-processor:2.1.18.RELEASE
org.springframework.boot:spring-boot-starter:2.1.18.RELEASE
org.springframework.boot:spring-boot-starter-actuator:2.1.18.RELEASE
org.springframework.boot:spring-boot-starter-security:2.1.18.RELEASE
org.springframework.boot:spring-boot-starter-thymeleaf:2.1.18.RELEASE
org.springframework.boot:spring-boot-starter-web:2.1.18.RELEASE
org.springframework.boot:spring-boot-starter-test:2.1.18.RELEASE
org.springframework.retry:spring-retry:1.3.1
org.springframework.security:spring-security-config:5.1.13.RELEASE
org.springframework.security:spring-security-core:5.1.13.RELEASE
org.springframework.security:spring-security-ldap:5.1.13.RELEASE
org.springframework.security:spring-security-web:5.1.13.RELEASE
org.springframework.security.oauth:spring-security-oauth2:2.3.8.RELEASE
org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.1.18.RELEASE
It sounds like you might be using the older Spring Security OAuth project:
spring-security-oauth?
This project has been deprecated. The newer Spring Security OAuth2 modules are great, and they are now first-class citizens, in Spring Security (they live in the official project now). Along with this Spring Boot 1.x is EoL, and is no longer getting patches and security updates.
Most of the guides you are seeing likely reference the newer libraries (e.g. things like .oauthLogin()).
Sorry for the typical StackOverflow answer of "don't do X", but here is what I would recommend:
Update your Spring Boot version
Migrate the newer OAuth libraries
Then add your new logic (this should be much easier after updating)
If you are already on Spring Boot 2 and the newer OAuth lib, let me know, and we can try to figure out why you don't have the newer HttpSecurity methods.

Swagger-UI Does not display with SpringBoot and path parameter on root endpoint

I am trying to setup swagger for an existing Spring Boot API project. I have discovered that I have two endpoints that cause the http://url/swagger-ui.html file to not render. If I comment out these two endpoints then it does render correctly.
When the two endpoints exist, the http://url/v2/api-docs json file does render successfully. I can take the json from api-docs and paste it into https://editor.swagger.io/ and the html page renders correctly on that site.
The two endpoints that are causing the issue are on root path, and have only a path parameter in the url. They are each in a controller that has #RequestMapping("/") and they are annotated;
#PutMapping(value = "{vaultTitleId}", produces = MediaType.APPLICATION_JSON_VALUE)
#DeleteMapping(value = "{vaultTitleId}")
These two endpoints work correctly, they just are causing some issue with Swagger rendering the HTML. If I remove them, the HTML displays. I have tried moving them into a controller by themselves and seeing if I could prevent swagger from accessing them in the Swagger configuration. But, it seems they only have to exist somewhere where spring boot sees them to prevent the html from displaying.
Any advice is appreciated. I would like to use Swagger, but I am giving up on it for now, and looking at alternative tools.
Gradle
compile("io.springfox:springfox-swagger2:2.9.2")
compile("io.springfox:springfox-swagger-ui:2.9.2")
Swagger Config
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors
.basePackage("com.nextgearcapital.mt.controller"))
.paths(PathSelectors.any())
.build();
}
}
I discovered a work around. This was suggested in another forum.
https://github.com/springfox/springfox/issues/631
The problem is you're endpoints are consuming the endpoint mappings,
you can create a regular expression that resolves it?
#DeleteMapping(value = "{vaultTitleId:^((?!swagger-ui.html).)*$}")
Seems al lil clunky but not sure what the right answer is.
Using a request mapping with a regex to define the path parameter did allow the swagger-ui to display. It is not obvious to me why this works. I would call it more of a work around than an actual solution. But, this is what I am going to be using.
#DeleteMapping(value = "{vaultTitleId:^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$}", produces = MediaType.APPLICATION_JSON_VALUE)

Swagger Path Selector Not Working

We are in a process of implementing Swagger for our REST APIs in a Spring Boot Application. Along with adding YAML files, we have also made changes to Spring Boot configurations to include a reg-ex pattern.
#Bean("myApi")
public Docket myApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(myApiPaths())
.build()
.pathMapping("/");
}
private Predicate<String> myApiPaths() {
return PathSelectors.regex("/v1/my/path/.*");
}
Currently all such YAML files are included in one library and are always available for all spring boot components. Because of this swagger-ui shows up all end points defined. This is why we were relying on path selectors so that only those matching patterns will be exposed.
But above code does not seem to be working. Despite trying different regex patterns, RequestHandlers I am still seeing the APIs which are not implemented on given Spring Boot Component.
Any help here will be appreciated.

Springfox swagger JSON?

In a springboot app context, i'm looking for the .json output of swagger.
Seems that in the docs, the /v2/api-docs is available, but there's nothing within this url in my project.
The UI swagger is available under /swagger-ui.html,
where can I find the json output ?
There is no physical json file/resource. It is generated at run-time and served up from memory.
Secondly the swagger-ui.html and all the javascript/css/images resources are served up from the springfox-swagger-ui library which is packaged up as a web-jars.
Try this one. You will have to provide the group name.
http://<host>:<port>/v2/api-docs?group=<group-name>
You don't have json endpoint out of the box. As I know, you have to build Docket for for every endpoint. Here is an example:
Docket endpointDocket = new Docket(DocumentationType.SWAGGER_2)
.groupName("yourGroupName")
.select()
.paths(regex("yourEndpointUrl"))
.build();
You have to register it in app context. Then you will have url (as mentioned by mephis-slayer):
http://<host>:<port>/v2/api-docs?group=yourGroupName

Resources