Overview:

OAUTH resource service REST end points rely on receiving and validating a “Authorization” header with a string value prefixed with “Bearer ” followed by a BASE64Url-encoded token that could optionally be in Java Web Token (JWT) format. The jwt.io site provides an excellent tutorial and validation tool for JWT, and I often provide this link to GUI developers when I deliver OAUTH-related API releases.

SpringFox is a Java and SpringBoot library project of that encapsulates the Swagger automated documentation generation tool-set. SpringFox works by examining an application and associated REST controller end-points at start-up to infer API semantics based on spring configurations, class structure and various compile time java Annotations. A separate PaulsDevBlog article is dedicated to the configuration and usage of SpringFox Swagger with SpringBoot REST applications.

As of the date this article is written and noted in the References section, there is no clean method within SpringBoot SpringFox Swagger UI to enter and persist an OAUTH “Authorization Bearer” header and execute the end-point via the “Try It Out!” button. As others have, I have used outboard tools, such as Postman, to validate and test Swagger REST API documentation.

However, recently I came up with a simple work around while we wait for the SpringFox team to address this concern.

  • SpringFox provides a method to configure the Swagger “Docket” bean associated with the controller end points to include “global” parameters of either form or header types.
  • This method could be used to create a dumb header field for the purposes of entering the long JWT string, and successfully submit the GET/POST directly from the SpringFox Swagger UI, as shown in the screenshot below.
  • Yes, this is not ideal, but a work-around. It does require an outboard utility to acquire the token from the OAUTH authentication service for copy-pasting into the form each time.
  • However, this work-around method succeeds in providing an accurate Swagger-formatted REST API document contract to the QA Team and external third-party developers.

This article shall detail how to configure the Swagger “Docket” bean to provide this global header parameter field.

Prerequisites:

Procedure:

  1. As defined in the SpringBoot REST API Documentation: Swagger with SpringFox article:
    > Setup SpringFox Dependencies in the POM
    > Setup SpringFox API Information properties in the application.properties file
    > Add your @API Swagger annotations to the appropriate controller REST end-point methods.
    > Create the SwaggerConfig class as detailed …
  2. Make the following additions to the SwaggerConfig:
    IMPORTANT: This is the work-around secret sauce!
  • Create the List<Parameter> listDocketParameters private property to hold all of yoru defined required headers and parameters.
  • Create a default constructor for the SwaggerConfig component configuration bean.
  • Within the constructor, instantiate Parameter objects as required.
    • The “name” is synonymous with the header key name.
    • The “defaultValue” is what is shown by default in the field within the Swagger UI
    • The “modelRef“defines the data type of the parameter; with JWT this is a String
    • The “parameterType” is set to “header
    • Instantiate the listDocketParameters property and add your JWT header parameter.
  • Within the Docket bean method, when instantiating the Docket object, set the globalOperationParameters with your listDocketParameters

Now, each end point method within the scope of the Docket bean configuration will have this header parameter added to the list of method parameters, as shown in the screen shots.

package com.paulsdevblog.springfoxjwtworkaround.config;

import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import org.springframework.stereotype.Component;

import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.Parameters;
import springfox.documentation.builders.RequestHandlerSelectors;

import springfox.documentation.schema.ModelReference;
import springfox.documentation.schema.ModelRef;

import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;

import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import springfox.documentation.swagger2.annotations.EnableSwagger2;


/**
 * Configuration class for Swagger SpringFox and 
 * globalOperaionsParameters docket settings to facilitate 
 * OAuth Authorization Bearer JWT tokens and other required headers
 *
 * @author PaulsDevBlog.com
 */
@Component
@Configuration
@EnableSwagger2
public class SwaggerConfig {
    
    private static final Logger logger = LoggerFactory.getLogger( SwaggerConfig.class );
    
    /** The title for the spring boot service to be displayed on swagger UI.  */  
    @Value("${swagger.title:spring.application.name:app_title}")  
    private String title;  
    
    /** The description of the spring boot service. */  
    @Value("${swagger.description:spring.application.description:app_description}")  
    private String description;  
   
    /** The version of the service. */  
    @Value("${swagger.version:spring.application.version:versionxxx}")  
    private String version;  
   
    /** The terms of service url for the service if applicable. */  
    @Value("${swagger.termsOfServiceUrl:terms_of_service_url:}")  
    private String termsOfServiceUrl;  
   
    /** The contact name for the service. */  
    @Value("${swagger.contact.name:contact_name}")  
    private String contactName;  
   
    /** The contact url for the service. */  
    @Value("${swagger.contact.url:contact_url}")  
    private String contactURL;  
   
    /** The contact email for the service. */  
    @Value("${swagger.contact.email:email_address}")  
    private String contactEmail;  
   
    /** The license for the service if applicable. */  
    @Value("${swagger.license:license_body}")  
    private String license;  
   
    /** The license url for the service if applicable. */  
    @Value("${swagger.licenseUrl:client_licenseUrl}")  
    private String licenseURL;  
    
    private List<Parameter> listDocketParameters;

    
    public SwaggerConfig() {
        
        //Any parameter or header you want to require for all end_points
        Parameter oAuthHeader = new ParameterBuilder()
                                    .name("Authorization")
                                    .description("OAUTH JWT Bearer Token")
                                    .defaultValue("Bearer YourJWTTokenHere")
                                    .modelRef(new ModelRef("string"))
                                    .parameterType("header")
                                    .required(true)
                                    .build();
    
        this.listDocketParameters = new ArrayList<Parameter>();
        this.listDocketParameters.add(oAuthHeader);
    }

    
    /**  
    * This method will return the API info object to swagger which will in turn 
    * display the information on the swagger UI.  
    * 
    * See the active application.properties file for adjusting attributes.
    *  
    * @return the API information object
    */ 
    private ApiInfo apiEndPointsInfo() {
        
        return new ApiInfoBuilder()
                    .title( this.title )
                    .description( this.description )
                    .contact( new Contact(this.contactName, this.contactURL, this.contactEmail ))
                    .license( this.license )
                    .licenseUrl( this.licenseURL )
                    .version( this.version )
                    .build();

    }
    
    /**  
     *  Swagger API Endpoint for Current Time
     * 
     * This method will return the Docket API object to swagger for the 
     * this micro-service application defined end-points, which will in turn 
     * display the information on the swagger UI.  
     *  
     * Refer the URL http://{ip-address or host-name}:{service.port}/{server.contextPath}/swagger-ui.html  
     * 
     * @return the docket object
     */ 
    @Bean
    public Docket docketAPICurrentTime() {
        
        Docket docket = new Docket( DocumentationType.SWAGGER_2 )
            .globalOperationParameters(listDocketParameters) //Your global required parameters and headers
            .groupName( "CurrentTimeAPI" )
            .select()
            .apis( RequestHandlerSelectors.basePackage("com.paulsdevblog.springfoxjwtworkaround.domain.controller") )
            .paths(PathSelectors.ant( "/time/**"))
            .build()
            .apiInfo( apiEndPointsInfo() );
        
        String logging_message = "Configured SWAGGER Group: [" + String.valueOf( docket.getGroupName() ) + "]" ;
        logger.info( logging_message );
        
        return docket;
    }
    
    
}

Hey, Swagger UI “Try it out” Button Works and submits Authorization JWT Token Header!

As shown below, the “Try it out” button sends the GET request with the “Authorization Bearer” token header as required. The curl example is also provided.

BitBucket Repo and Project Code

Yes it would be nice to have a OAUTH authentication form that persisted the header to the “Try it now” button, but this workaround will get the job done. Like and Link, thanks!  paulsDevBlog.End();

References: