Keycloak intégration dans Swagger

J'ai un backend protégé par Keycloak auquel j'aimerais accéder via swagger-ui. Keycloak lui-même est fournir le OAuth2 implicite et le flux de code d'accès, mais les deux je n'ai pas obtenu de travail. Actuellement, la documentation de Keycloak fait défaut sur ce point pour lequel l'url devrait être utilisée authorizationUrl et tokenUrl à l'intérieur de swagger.json.

chaque domaine de Keycloak offre une énorme liste d'url de configuration en accédant http://keycloak.local/auth/royaumes/ROYAUME/.bien connu/openid-configuration

<!-De plus, j'ai essayé d'intégrer directement le keycloak js-client dans l'index swagger-ui.html en ajoutant les lignes suivantes:

<script src="keycloak/keycloak.js"></script>
<script>
  var keycloak = Keycloak('keycloak.json');
    keycloak.init({ onLoad: 'login-required' })
      .success(function (authenticated) {
        console.log('Login Successful');
        window.authorizations.add("oauth2", new ApiKeyAuthorization("Authorization", "Bearer " + keycloak.token, "header"));
      }).error(function () {
        console.error('Login Failed');
        window.location.reload();
      }
    );
 </script>

j'ai aussi essayé quelque chose comme ça après 'Login Successful'

swaggerUi.api.clientAuthorizations.add("key", new SwaggerClient.ApiKeyAuthorization("Authorization", "Bearer " + keycloak.token, "header"));

mais ça ne marche pas non plus.

N'importe quelle suggestion comment je peux intégrer l'auteur de keycloak dans swagger?

26
demandé sur Gonzalo Matheu 2017-01-29 11:06:14

1 réponses

Swagger-ui peut s'intégrer avec keycloak en utilisant le implicit mode d'authentification. Vous pouvez configurer oauth2 sur swagger-ui pour qu'il vous demande de vous authentifier au lieu de donner directement le token d'accès à swagger-ui.

1ère chose, votre swagger besoin de faire référence à une définition de la Sécurité de la forme:

"securityDefinitions": {
    "oauth2": {
        "type":"oauth2",
        "authorizationUrl":"http://172.17.0.2:8080/auth/realms/master/protocol/openid-connect/auth",
        "flow":"implicit",
        "scopes": {
            "openid":"openid",
            "profile":"profile"
        }
    }
}

ensuite, vous devez faire référence à un autre paramètre de swagger-ui: avec le JS pur, vous pouvez utiliser le index.html

const ui = SwaggerUIBundle({ ...} );

ui.initOAuth({
    clientId: "test-uid",
    realm: "Master",
    appName: "swagger-ui",
    scopeSeparator: " ",
    additionalQueryStringParams: {"nonce": "132456"}
})

dans le présent code,

  • authorizationUrl est l'autorisation d'extrémité sur votre keycloak domaine
  • Étendues sont quelque chose que vous pouvez définir vos besoins
  • clientId est un client paramétré avec implicit mode keycloak domaine
  • le paramètre supplémentaire nonce devrait être aléatoire, mais swagger-ui ne l'utilise pas encore.

je vais a eu un exemple si vous voulez faire tout cela sur Spring-boot:

sur ce cadre, vous utiliserez principalement swagger et swagger-interface utilisateur web-pot de Springfox. Ceci est fait en ajoutant les dépendances:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.8.0</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.8.0</version>
</dependency>

Swagger est activé en ajoutant l'annotation swagger2 sur votre classe principale:

@SpringBootApplication
@EnableSwagger2
public class TestSpringApplication {
    ...

ensuite, vous pouvez configurer un Configuration classe comme ceci:

@Configuration
public class SwaggerConfigurer {

    @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();
    }

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("com.example.testspring"))
            .paths(PathSelectors.any())
            .build().securitySchemes(buildSecurityScheme()).securityContexts(buildSecurityContext());
    }

    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://172.17.0.2: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 {
                log.warn("Scope '{}' is not valid (format is scope=description)", scopeItem);
            }
        }

        return scopes;
    }
}

il y a beaucoup de choses que vous pouvez mettre à jour dans ce code. C'est essentiellement la même qu'avant:

  • nonce ce qui devrait être une chose aléatoire (swagger-ui ne l'utilise pas encore)
  • clientId que vous devez configurer en fonction du client que vous configurez dans keycloak
  • basePackage: vous devez définir le paquet dans lequel tous vos Controllers sont
  • si vous avez besoin d'une clé api, vous pouvez l'activer et l'ajouter sur la liste security scheme
  • LoginEndpoint: qui doivent être l'autorisation d'extrémité de vous keycloak domaine
  • scopeItems: les étendues que vous voulez pour cette authentification.

Il va générez la même chose qu'avant: mettre à jour le swagger pour ajouter la definition securityDefinition et faire swagger-UI prendre le paramètre clientId, nonce, ...

1
répondu wargre 2018-07-24 16:18:32