Springboot swagger ui with Bearer token - spring-boot

I use Bearer token to access my api. so I configure my swagger just like this:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("br.com.lumera.intimacaoapi.controller"))
.paths(PathSelectors.any())
.build()
.securitySchemes(Lists.newArrayList(apiKey()))
.securityContexts(Arrays.asList(securityContext()));
}
private ApiKey apiKey() {
return new ApiKey("Bearer", "Authorization", "header");
}
private SecurityContext securityContext() {
return SecurityContext.builder().securityReferences(defaultAuth())
.forPaths(PathSelectors.any()).build();
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope(
"global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference("Bearer",
authorizationScopes));
}
}
but for every request my user must input Bearer <>. It's possible to I configure the swagger to put automatic the 'Bearer ' before the token that my user insert?
tks

One work around for this issue can be setting "Bearer " as default value as shown below
public ResponseEntity method_name(#ApiParam(defaultValue = "Bearer ") String auth) { }
This code will show "Bearer " as default value in token input field box. You can add the token after the bearer in the input field box.

Related

get the "instance_url" in the oauth2 salesforce response and use it in the webclient baseurl

I use a Bean webclient for my connection with salesforce
I created a configuration class with these 2 methods.
#Configuration
public class salesForceConfig {
#Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService
) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder().password().build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager (clientRegistrationRepository, authorizedClientService );
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
authorizedClientManager.setContextAttributesMapper(oAuth2AuthorizeRequest -> {
if (SALESFORCE.equals(oAuth2AuthorizeRequest.getClientRegistrationId())) {
return Map.of(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, SALESFORCE_USERNAME,OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, SALESFORCE_PASSORD
);
}
return null;
});
return authorizedClientManager;
}
#Bean
public WebClient salesforceWebClient(OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth2Client.setDefaultClientRegistrationId(SALESFORCE);
return WebClient.builder()
.baseUrl(SALESFORCE_BASE_PATH)
.apply(oauth2Client.oauth2Configuration())
.build();
}
}
`
during the authentication, I have a message with the token and other information like instance_url.
`{
"access_token": "xxxxx",
"instance_url": "https://xxxx.salesforce.com",
"id": "https://login.salesforce.com/id/xxxxxx",
"token_type": "Bearer",
"issued_at": "xxxx",
"signature": "xxxx"
}
I want to change the webclient baseurl address based on instance_url.
does anyone have any idea how to do this.

Use Swagger-ui for a keycloak protected App

I'm trying to build a user-service to access keycloak with spring-boot and the keycloak-admin-client.
edit: I should mention that run the service and keycloak in different docker containers, I think that might be the problem.
My AUTH_SERVER is set to keycloak:8080, and I have it to redirect to localhost in my hostfile.
edit2: I managed to get the token through swagger, but the user-creation still ends with a 403 Forbidden, although the exact same code works if run outside of swagger. Seems like a problem with my spring-boot or my swagger.
Stragely enough, I can get a token just fine.
I want to create a user and provide a login endpoint, where another service can login a user with username/password and get a token back.
The code for user creation works if I run it outside of swagger in a main method, and I can get a token via postman. (now also through swagger)
But with swagger-ui, I get a "403 Forbidden" when trying to create a user.
I have tried both the Postrequest via resttemplate and through the admin-cli of keycloak.
Both work when run independently of swagger and both dont work with swagger.
#PostMapping(path = "new")
public ResponseEntity<String> addUser(UserData userData) {
UserRepresentation user = new UserRepresentation();
user.setEnabled(true);
user.setUsername(userData.getUsername());
user.setFirstName(userData.getFirstName());
user.setLastName(userData.getLastName());
RealmResource realmResource = getRealmResource();
UsersResource userResource = realmResource.users();
Response response = userResource.create(user);
log.info("Response: " + response.getStatusInfo());
return new ResponseEntity<>("User created with userId: " + userData.getBusinessEntityId(),
HttpStatus.OK);
}
My securityconfig:
/*
Submits the KeycloakAuthenticationProvider to the AuthenticationManager
*/
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keycloakAuthenticationProvider);
}
#Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
#Bean
#Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/api/v1/user/admin").hasRole("admin")
.antMatchers("/api/v1/user/vendor").hasRole("vendor")
// .antMatchers("/api/v1/user/customer").hasRole("customer")
.anyRequest().permitAll();
}
My Swaggerconfig:
#Bean
public Docket apiDocumentation() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.securitySchemes(Arrays.asList(securityScheme()))
.securityContexts(Arrays.asList(securityContext()));
}
private SecurityScheme securityScheme() {
return new OAuthBuilder()
.name("spring_oauth")
.grantTypes(grantTypes())
.build();
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(Arrays.asList(new SecurityReference("spring_oauth", new AuthorizationScope[]{})))
.forPaths(PathSelectors.any())
.build();
}
private List<GrantType> grantTypes() {
GrantType grantType = new ClientCredentialsGrant(AUTH_SERVER + "/realms/User-Service-Realm/protocol/openid-connect/token");
return Arrays.asList(grantType);
}
#Bean
public SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder()
.realm(REALM)
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.scopeSeparator(" ")
.useBasicAuthenticationWithAccessCodeGrant(true)
.build();
}
My Keycloak settings:
I could manage it to work in a client credential grant.
You may want to try it with the following configuration instead.
private SecurityScheme securityScheme() {
return new OAuthBuilder()
.name("spring_oauth")
.grantTypes(grantTypes())
.build();
}
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(Arrays.asList(new SecurityReference("spring_oauth", new AuthorizationScope[] {})))
.forPaths(PathSelectors.regex("/api.*"))
.build();
}
private List<GrantType> grantTypes() {
GrantType grantType = new ClientCredentialsGrant(authTokenURL);
return Arrays.asList(grantType);
}
I found out the solution:
I annotated the Requests in my RestController as PostRequests since thats whats specified in the keycloak docs and what makes sense.
After changing them to GetRequests, they work now.

Why is swagger ignoring my authentication?

I am trying to secure a swagger interface withj OpenId Connect.
I can login using OIDC and swagger shows me as authorised:
but when I do 'try it out' the authentication is ignored and a login box pops up:
In my class which extends SpringBootServletInitializer I have:
#Bean
#ConditionalOnProperty("security.oauth2.client.clientId")
public SecurityScheme securityScheme(Environment environment, OAuth2ClientProperties clientProperties) {
String authorizationUri = environment.getRequiredProperty("security.oauth2.client.user-authorization-uri");
String accessTokenUri = environment.getRequiredProperty("security.oauth2.client.access-token-uri");
LoginEndpoint loginEndpoint = new LoginEndpoint(authorizationUri);
TokenRequestEndpoint tokenRequestEndpoint =
new TokenRequestEndpoint(authorizationUri, clientProperties.getClientId(), clientProperties.getClientSecret());
TokenEndpoint tokenEndpoint = new TokenEndpoint(accessTokenUri, "auth_code");
GrantType grantType = new AuthorizationCodeGrant(tokenRequestEndpoint, tokenEndpoint);
AuthorizationScope authorizationScope = new AuthorizationScope(authorizationScopeGlobal, authorizationScopeGlobal);
return new OAuthBuilder()
.name(securitySchemaOAuth2)
.grantTypes(Arrays.asList(grantType))
.scopes(Arrays.asList(authorizationScope))
.build();
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope(authorizationScopeGlobal, authorizationScopeGlobalDesc);
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Arrays.asList(new SecurityReference(securitySchemaOAuth2, authorizationScopes));
}
#Bean
SecurityConfiguration security(OAuth2ClientProperties clientProperties) {
return new SecurityConfiguration(
clientProperties.getClientId(),
clientProperties.getClientSecret(),
securitySchemaOAuth2,
"test-app",
"apiKey",
ApiKeyVehicle.HEADER,
"api_key",
" " /*scope separator*/);
}
#Bean
public SecurityContext securityContext() {
return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("/v1/.*")).build();
}
and a class with:
#ApiModel(value = "Template", description = "Template of REST APIs")
#RestController
#RequestMapping("/v1")
public class TemplateServiceImplementation {
...
#ApiOperation(httpMethod = "GET", value = "Call Get method",
notes = "See Get method")
#RequestMapping(method = RequestMethod.GET, value = "/calltemplate/{param}/", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Structure> callGet(#PathVariable("param") String param, HttpServletRequest hreq) {
MultiValueMap<String, String> mapParams = new LinkedMultiValueMap<String, String>();
mapParams.add("param", param);
Structure structure = restTemplate.getForObject(callGetEndpoint, Structure.class, mapParams);
ResponseEntity<Structure> thisresponse = new ResponseEntity<Structure>(structure, HttpStatus.OK);
return thisresponse;
}
Sorry for all the code. So how do I make the GET use my OIDC authentication?
When I cancel the login, curl is:
curl -X GET --header 'Accept: application/json' --header 'Authorization: Bearer eyJraWQiOiJyc2ExIiwiYWxnIjoiUlMy lots more encrypted text' 'http://localhost:8080/v1/calltemplate/%7B%20%20%20%22id%22%3A%20%22string%22%2C%20%20%20%22name%22%3A%20%22string%22%2C%20%20%20%22path%22%3A%20%22string%22%2C%20%20%20%22version%22%3A%20%22string%22%20%7D/'
request url:
http://localhost:8080/v1/calltemplate/%7B%20%20%20%22id%22%3A%20%22string%22%2C%20%20%20%22name%22%3A%20%22string%22%2C%20%20%20%22path%22%3A%20%22string%22%2C%20%20%20%22version%22%3A%20%22string%22%20%7D/
and other response variables:
EDIT Forgot to metion my WebSecurityConfig:
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui",
"/swagger-resources/**", "/configuration/**", "/swagger-ui.html"
, "/webjars/**", "/csrf", "/");
}
UPDATE
Output of network:

From swagger editor able to get the JWT auth token, but from application which enabled swagger-ui using springfox is not working

Tested my auth server from swagger editor and is working fine. I'm able to get the token and authorization is happening without any issues. But, when I tried to integrate it with my web service where swagger UI is enabled using springfox dependencies is not working.
Success form swagger editor
Failed from application
Noticed that in the failed case, swagger UI is sending only a single POST request, but swagger editor had an OPTIONS & POST request to get the token.
Suspected CROS filter initially, so I took my swagger json and tested in swagger editor and it worked.
My auth server and resource server with application is also working fine when tested via curl.
Sample auth server and resource server is this:- https://github.com/ranjithap7576/OAuth2-JWT
And swagger configuration is below
#Configuration
#EnableSwagger2
public class SwaggerConfigNew {
#Value("${security.jwt.resource-ids}")
private String clientId;
#Value("${security.signing-key}")
private String clientSecret;
#Value("${security.oauth2.authserver}")
private String authLink;
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("my.package")).build().groupName("test")
.directModelSubstitute(org.joda.time.LocalDate.class, java.sql.Date.class)
.directModelSubstitute(org.joda.time.DateTime.class, java.util.Date.class)
.securitySchemes(Collections.singletonList(securitySchema()))
.securityContexts(Collections.singletonList(securityContext()));
}
private OAuth securitySchema() {
List<AuthorizationScope> authorizationScopeList = newArrayList();
authorizationScopeList.add(new AuthorizationScope("read", "read all"));
authorizationScopeList.add(new AuthorizationScope("trust", "trust all"));
authorizationScopeList.add(new AuthorizationScope("write", "access all"));
List<GrantType> grantTypes = newArrayList();
GrantType creGrant = new ResourceOwnerPasswordCredentialsGrant(authLink + "/oauth/token");
grantTypes.add(creGrant);
return new OAuth("oauth2schema", authorizationScopeList, grantTypes);
}
#Bean
UiConfiguration uiConfig() {
return new UiConfiguration("validatorUrl", // url
"none", // docExpansion => none | list
"alpha", // apiSorter => alpha
"schema", // defaultModelRendering => schema
UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS, false, // enableJsonEditor => true | false
true, // showRequestHeaders => true | false
60000L); // requestTimeout => in milliseconds, defaults to null (uses jquery xh timeout)
}
#Bean
public SecurityConfiguration securityInfo() {
return new SecurityConfiguration(clientId, clientSecret, "", "", "", ApiKeyVehicle.HEADER, "", " ");
}
private SecurityContext securityContext() {
return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.ant("/user/**"))
.build();
}
private List<SecurityReference> defaultAuth() {
final AuthorizationScope[] authorizationScopes = new AuthorizationScope[3];
authorizationScopes[0] = new AuthorizationScope("read", "read all");
authorizationScopes[1] = new AuthorizationScope("trust", "trust all");
authorizationScopes[2] = new AuthorizationScope("write", "write all");
return Collections.singletonList(new SecurityReference("oauth2schema", authorizationScopes));
}
// #Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
I'm using springfox 2.7.0

How send token to header of Swagger

I have Spring Boot application. And I want to integrate swagger in my project.
I am using springfox 2.7.0 and auth0 for authentication on swagger, but I have problem with send id_token from auth0 to header of swagger.
This is my code for Swagger configuration:
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("name.web"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiInfo())
.securitySchemes(Collections.singletonList(securitySchema()));
}
private OAuth securitySchema() {
List<AuthorizationScope> authorizationScopeList = new ArrayList<>();
authorizationScopeList.add(new AuthorizationScope("openid", "access all"));
List<GrantType> grantTypes = new ArrayList<>();
final TokenRequestEndpoint tokenRequestEndpoint = new TokenRequestEndpoint("https://bovinet.auth0.com/authorize", "clientId", "secretKey");
final TokenEndpoint tokenEndpoint = new TokenEndpoint("http://server.com/oauth/token", "id_token");
AuthorizationCodeGrant authorizationCodeGrant = new
AuthorizationCodeGrant(tokenRequestEndpoint, tokenEndpoint);
grantTypes.add(authorizationCodeGrant);
OAuth oAuth = new OAuth("oauth2", authorizationScopeList, grantTypes);
return oAuth;
}
private ApiInfo apiInfo() {
#SuppressWarnings("deprecation")
ApiInfo apiInfo = new ApiInfo(
"Name", "", "", "", "", "", "");
return apiInfo;
}
#Bean
SecurityConfiguration security() {
return new SecurityConfiguration(
"clientId",
"secretKey",
"test-app-realm",
"https://server.com",
"api_key",
ApiKeyVehicle.HEADER,
"Authorization",
"," /*scope separator*/);
}
When I open console for swagger-ui.htm page I can see id_token in response of /oauth/token request but I don't know how put that token in header of swagger.
Can somebody please help me to resolve this problem?

Resources