openapi-generatoropenapi-generator-maven-plugin

How to forward tokens using the openapi java client generator


I would like to know the best practice to use the client generated by the openapi-generator-maven-plugin in the context of a Spring Boot application, where the application will communicate with an external API using the client, forwarding the user's token.

I don't see how it is possible to use the existing @Autowired functionality, which seems to assume that the bearer token is only configured once, e.g. by a client credentials flow.

This post suggests that adding a security scheme to the endpoint will add another request parameter to the client. However that did not change the client.

There is an article that suggests modifying the RestTemplate to add the bearer token however this doesn't appear ideal, as it affects the global RestTemplate.

Do I just have to drop the @Autowired functionality, and construct the client on a per-user request basis, in order to forward their tokens to the external API?

My openapi-generator-maven-plugin configuration:

          <plugin>
           <groupId>org.openapitools</groupId>
                <artifactId>openapi-generator-maven-plugin</artifactId>
                <version>${openapi-generator.version}</version>
                <executions>
                    <execution>
                        <id>Generate server</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                            <inputSpec>${project.basedir}/src/main/resources/petclinic.yml</inputSpec>
                            <generatorName>spring</generatorName>
                            <apiPackage>com.example.petclinic.api</apiPackage>
                            <modelPackage>com.example.petclinic.model</modelPackage>
                            <supportingFilesToGenerate>ApiUtil.java</supportingFilesToGenerate>
                            <configOptions>
                                <delegatePattern>true</delegatePattern>
                                <useSpringBoot3>true</useSpringBoot3>
                            </configOptions>
                            <configHelp>false</configHelp>
                        </configuration>
                    </execution>
                    <execution>
                        <id>Generate client</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                        <configuration>
                          <inputSpec>${project.basedir}/src/main/resources/petclinic.yml</inputSpec>
                            <generatorName>java</generatorName>
                            <apiPackage>com.example.petclinic.client</apiPackage>
                            <modelPackage>com.example.petclinic.model</modelPackage>
                            <generateApiTests>false</generateApiTests>
                            <generateModelTests>false</generateModelTests>
                            <library>resttemplate</library>
                            <configOptions>
                                <useJakartaEe>true</useJakartaEe>
                                <generateClientAsBean>false</generateClientAsBean>
                            </configOptions>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Solution

  • Adding

        post:
          summary: Create a pet
          security:
            - bearerAuth: []
    
    components:
      securitySchemes:
        bearerAuth:
          type: http
          scheme: bearer
          bearerFormat: JWT
    

    And setting

    <generateClientAsBean>false</generateClientAsBean>
    

    In the latest version 7.0.1 of the openapi-generator

    And creating an ApiClient @RequestScope bean seemed to work:

        @Bean
        @RequestScope
        public ApiClient apiClient() {
            Jwt principal = (Jwt) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            ApiClient apiClient = new ApiClient();
            apiClient.setBearerToken(principal.getTokenValue());
            return apiClient;
        }
    
        @Bean
        public PetsApi petsApi(ApiClient apiClient) {
            PetsApi petsApi = new PetsApi(apiClient);
            return petsApi;
        }