Hello, 

I have a secured spring backend and an angular frontend. The backend has a 
swagger-ui which is accessible without authentification. I would like to be 
able to call a backend controller with this swagger-ui, therefore I need an 
authentification config in swagger/spring. 

I have created two clients in keycloak, one with access type 'public' for 
frontend authentification, one with access type 'bearer-only' for the 
backend application. The interface between angular and spring was designed 
with swagger. The Swagger UI is still visible thanks to 
HttpSecurity.authorizeRequests().antMatchers(new 
String[]{"/swagger-ui.html", "/swagger/swagger.yaml", "/swagger-resources", 
"/swagger-resources/**", "/webjars/springfox-swagger-ui/**"}).permitAll()

I would like to get an access token for calls in Swagger UI. Adding the 
java code and swagger yaml configuration from this posting Keycloak 
integration in Swagger 
<https://stackoverflow.com/questions/41918845/keycloak-integration-in-swagger> 
does not work so far. I created a third client in keycloak for the 
swagger-ui with a 'public' access type. 

My swagger.yaml:


...
securityDefinitions:
  OAuth2:
    type: oauth2
    flow: implicit
    authorizationUrl: http://localhost:8080/auth/
    scopes:
      openid: openid
      profile: profile
security:
  - OAuth2: [openid, profile]


This is my swagger config class(note: Swagger builds the ui from the provided 
yaml file and NOT from the controller classes)

@Configuration
@EnableSwagger2
public class SwaggerConfiguration {

private static final Logger LOGGER = 
LoggerFactory.getLogger(SwaggerConfiguration.class);

@Bean
WebMvcConfigurer configurer() {
 return new WebMvcConfigurer() {
 @Override
 public void addResourceHandlers(ResourceHandlerRegistry registry) {
 registry
 .addResourceHandler("/swagger/**")
 .addResourceLocations("classpath:swagger/");

 }
 };
}

@Primary
@Bean
public SwaggerResourcesProvider swaggerResourcesProvider() {
 return () -> {
 SwaggerResource resource = new SwaggerResource();
 resource.setName("QM-API");
 resource.setLocation("/swagger/swagger.yaml");

 SwaggerResource models = new SwaggerResource();
 models.setName("QM-Models");
 models.setLocation("/swagger/qm-common-definitions.yaml");

 List<SwaggerResource> resources = new ArrayList<>();
 resources.add(resource);
 resources.add(models);
 return resources;
 };
}

@Bean
public SecurityConfiguration securityConfiguration() {

 Map<String, Object> additionalQueryStringParams=new HashMap<>();
 additionalQueryStringParams.put("nonce","123456");

 return SecurityConfigurationBuilder.builder()
 .clientId("test-uid").realm("Master").appName("swagger-ui")
 .additionalQueryStringParams(additionalQueryStringParams)
 .build();
}

private List<SecurityContext> buildSecurityContext() {
 List<SecurityReference> securityReferences = new ArrayList<>();

 
securityReferences.add(SecurityReference.builder().reference("oauth2").scopes(scopes().toArray(new
 AuthorizationScope[]{})).build());

 SecurityContext context = 
SecurityContext.builder().forPaths(Predicates.alwaysTrue()).securityReferences(securityReferences).build();

 List<SecurityContext> ret = new ArrayList<>();
 ret.add(context);
 return ret;
}

private List<? extends SecurityScheme> buildSecurityScheme() {
 List<SecurityScheme> lst = new ArrayList<>();
 lst.add(new ApiKey("api_key", "X-API-KEY", "header"));

 LoginEndpoint login = new 
LoginEndpointBuilder().url("http://localhost:8080/auth/realms/master/protocol/openid-connect/auth";).build();

 List<GrantType> gTypes = new ArrayList<>();
 gTypes.add(new ImplicitGrant(login, "acces_token"));

 lst.add(new OAuth("oauth2", scopes(), gTypes));
 return lst;
}

private List<AuthorizationScope> scopes() {
 List<AuthorizationScope> scopes = new ArrayList<>();
 for (String scopeItem : new String[]{"openid=openid", "profile=profile"}) {
 String scope[] = scopeItem.split("=");
 if (scope.length == 2) {
 scopes.add(new 
AuthorizationScopeBuilder().scope(scope[0]).description(scope[1]).build());
 } else {
 LOGGER.warn("Scope '{}' is not valid (format is scope=description)", 
scopeItem);
 }
 }

 return scopes;
}
}

With this configuration I have an 'Authorize' button in my swagger-ui. Pressing 
this button opens a modal form, giving me the opportunity to enter a client_id, 
and displays checkboxes for the scopes. Pressing the 'Authorize' button in this 
form 
opens a new tab in my browser, showing the keycloak welcome page. Keycloak does 
not show any log error message. 


I experimented a bit with the 'flow' in the swagger.yaml. Changing it to 
'password' caused the modal form to give more input like 'user' and 'password' 
and causing the keycloak to log warn messages, but did not get me further. 


What can I do to authenticate the swagger ui against keycloak in order to get 
access to the backend? 

-- 
You received this message because you are subscribed to the Google Groups 
"Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to