0

I have a Spring Boot App (2.7.10) and am using the Sprspringdoc-openapi-ui dependency (1.6.15). I have annotated my controller and it seems to be displaying correctly, however when I try and execute one of the endpoints which requires an Authorization Header, Swagger UI is not including it in the Authorization header and I get a 400 Bad Request: org.springframework.web.bind.MissingRequestHeaderException: Required request header 'Authorization' for method parameter type String is not present

Here is my controller class:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeIn;
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType;
import io.swagger.v3.oas.annotations.info.Contact;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityScheme;
import io.swagger.v3.oas.annotations.servers.Server;
import io.swagger.v3.oas.annotations.tags.Tag;

/**
 * This controller will be invoked from the front end to be able to interact
 * with the IAM Service<br>
 * For some reason the swagger UI will not work with the getUserInfo request as its not passing in the Authorization header
 *
 * @author Hanif Rajabali
 */
@OpenAPIDefinition(
    info = @Info(
        title = "${api.info.title}",
        version = "${api.info.version}",
        description = "${api.info.description}",
        termsOfService = "${api.info.termsOfService}",
        contact = @Contact(name = "${api.info.contact.name}", url = "${api.info.contact.url}", email = "${api.info.contact.email}")
    ),
    servers = { @Server(description = "${api.server.description}", url = "${api.server.url}") })

@SecurityScheme(name = "JWT Access Token", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "JWT", in = SecuritySchemeIn.HEADER)
@SecurityRequirement(name = "bearerAuth")
@Tag(name = "${api.tag.name}", description = "${api.tag.description}")
@CrossOrigin
@RestController
@RequestMapping(value = "${api.base-request-mapping}", produces = MediaType.APPLICATION_JSON_VALUE)
public class LoginController {

    final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private LoginService loginService;

   
    @Operation(
        summary = "Retrieves User Attributes From an Authenticated User Within the IAM User Repository",
        description = "The userInfo endpoint is an OpenID Connect (OIDC) userInfo endpoint. It responds with user attributes given an access tokens that the Token endpoint issued. The scopes in the users access token define the user attributes that the userInfo endpoint returns in its response. The openid scope must be one of the access token claims. Currently the authentication service provider is AWS Cognito",
            security = @SecurityRequirement(name = "bearerAuth"),
        parameters = @Parameter(
            in = ParameterIn.HEADER,
            name = "Authorization",
            description = "Access Token",
            required = true,
            schema = @Schema(type = "string", format = "JWT"),
            example = "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
            )
        )
    @ApiResponses(
        value = { @ApiResponse(responseCode = "200", description = "Successful Retrieval of User Attributes"),
            @ApiResponse(
                responseCode = "401",
                description = "Unauthorized or Invalid Token",
                content = { @Content(schema = @Schema(implementation = ApiErrorResponse.class)) }),
            @ApiResponse(
                responseCode = "500",
                description = "Internal Server Error",
                content = { @Content(schema = @Schema(implementation = ApiErrorResponse.class)) }) })
    @GetMapping("/userinfo")
    @ResponseBody
    public ResponseEntity<LoginApiResponse<UserInfo>> getUserInfo(
        @Parameter(in = ParameterIn.HEADER, name = "Authorization", required = true, schema = @Schema(type = "string", format = "Bearer"))
        @RequestHeader(name = "Authorization", required = true) String accessToken) throws Exception {

    UserInfo userInfo = this.loginService.getUserInfo(accessToken);

    LoginApiResponse<?> apiResponse = this.loginService.createApiResponse(userInfo);

    LoginApiResponse<UserInfo> userInfoResponse = (LoginApiResponse<UserInfo>) apiResponse;

    return ResponseEntity.ok(userInfoResponse);

    }

}

Here is the screenshot from my swagger ui: enter image description here

ustad
  • 459
  • 1
  • 6
  • 21

1 Answers1

0

Try adding security = @SecurityRequirement(name = "JWT Access Token") to your @OpenAPIDefinition annotation

Pirate4
  • 560
  • 3
  • 7