I want to add token endpoint oauth/token into my API documentation so I configured Docket like this:
public Docket api(UserProperties userProperties) {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(Predicates.not(PathSelectors.regex("/error")))
.paths(Predicates.not(PathSelectors.regex("/oauth/authorize")))
.paths(Predicates.not(PathSelectors.regex("/oauth/check_token")))
.paths(Predicates.not(PathSelectors.regex("/oauth/token_key")))
.paths(Predicates.not(PathSelectors.regex("/oauth/confirm_access")))
.paths(Predicates.not(PathSelectors.regex("/oauth/error")))
.build().apiInfo(apiInfo());
}
swagger-ui display page correctly, however 3rd party validator claims that:
Swagger schema validation failed.
Data does not match any schemas from 'oneOf' at #/paths//oauth/token/post/parameters/1
Data does not match any schemas from 'oneOf' at #/paths//oauth/token/post/parameters/1
Missing required property: schema at #/
Missing required property: type at #/
Missing required property: $ref at #/paths//oauth/token/post/parameters/1
JSON_OBJECT_VALIDATION_FAILED
The swagger.json taken from /api/v2/api-docs:
"/oauth/token": {
"get": {
...
},
"post": {
"tags": [
"token-endpoint"
],
"summary": "postAccessToken",
"operationId": "postAccessTokenUsingPOST",
"consumes": [
"application/json"
],
"produces": [
"*/*"
],
"parameters": [
{
"name": "name",
"in": "query",
"required": false,
"type": "string"
},
{
"name": "parameters",
"in": "query",
"description": "parameters",
"required": true,
"items": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
],
"responses": {
...
},
"deprecated": false
}
},
Why springfox generates invalid schema?
Related
I am integrating a Spring Boot application with OIDC. The customer has an OIDC manifest file, at https://example.biz/.well-known/openid-configuration, which is redacted as displayed later.
Problem
When I attempt to authenticate via Swagger, the authorization endpoint complains that a parameter is missing. I could see that Swagger does not send the client_id parameter in (it's actually empty).
Please note, I expect that 99% of the configuration is handled by Springdoc after the OIDC configuration URL.
Question
Why doesn't Springdoc/Swagger OIDC setup work according to the existing setup and OIDC manifest?
Set up
OIDC manifest I can retrieve from authorization endpoint
{
"client_id": "the-clientid",
"issuer": "https://...",
"authorization_endpoint": "https://...",
"token_endpoint": "https://...",
"userinfo_endpoint": "https://...",
"jwks_uri": "https://...",
"end_session_endpoint": "https://...",
"registration_endpoint": null,
"scopes_supported": [
"openid"
],
"response_types_supported": [
"token",
"id_token",
"id_token token"
],
"response_modes_supported": [
"form_post",
"fragment"
],
"grant_types_supported": [
""
],
"subject_types_supported": [
"pairwise"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic"
],
"claims_supported": [
"sub",
"iss",
"aud",
"exp",
"iat",
"auth_time",
"nonce"
]
}
I import this scheme using Springdoc's #SecurityScheme annotation
#ConditionalOnProperty(...) // I can switch between basic (dev) and oidc authentication (test, uat, prod)
#SecurityScheme(
name = "secured",
type = OPENIDCONNECT,
openIdConnectUrl = "${oidc-url}/.well-known/openid-configuration" //Parameterized URL works here
)
public class OidcConfiguration {
}
Swagger displays me the Authorize button on top of the page.
However, when I see the generated Swagger OpenAPI v3 schema, it looks like the following
{
"openapi": "3.0.1",
"info": {
"title": "API",
"version": "v1"
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Generated server url"
}
],
"paths": {
"/api/v1/.....": {
"patch": {
"tags": [
"...."
],
"operationId": "...",
"responses": {
"200": {
"description": "OK"
}
},
"security": [
{
"secured": []
}
]
}
},
"/health.check": {
"get": {
"tags": [
"probe-controller"
],
"operationId": "healthCheckProbe",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"type": "boolean"
}
}
}
}
},
"security": [
{
"open": []
}
]
}
}
},
"components": {
"securitySchemes": {
"secured": {
"type": "openldConnect",
"openldConnectUrl": "https://...."
}
}
}
}
As you can see, the JSON file points to the remote OIDC configuration, and Swagger retrieves it.
But when I click on the Authentication button, I can see in the popup
secured (OAuth2, )
OpenId Connect URL: https://.....
Flow:
Scopes (select all, select none)
[ ] openid
According to this, I am not prompted with any client id. Clicking on Authorize opens a new window where I can't debug the original URL, as I am immediately redirected and DevTools is not open yet.
But after login request, I could see that the next URL displays ?client_id=&.....
If I manually navigate the URL with the client ID set, I can be redirected.
I also tried to set springdoc.swagger-ui.oauth.clientId=some client id according to linked issue, but it didn't display the input box.
I'm using Krakend as API-Gateway, and my configuration looks like this :
{
"plugin": {
"folder": "/etc/krakend/plugins/authenticator/",
"pattern":".so"
},
"port": 8080,
"extra_config": {
"github_com/devopsfaith/krakend/transport/http/server/handler": {
"name": "authenticator"
}
},
"endpoints": [
{
"output_encoding": "no-op",
"backend": [
{
"encoding": "no-op",
"host": [
"127.0.0.1:8080"
],
"url_pattern": "/api/v1/address/{id}",
"method": "GET"
}
],
"endpoint": "/api/v1/addresses/{id}",
"method": "GET"
}
],
"name": "gateway",
"timeout": "30s",
"version": 2
}
I want to pass some metadata per end point and access it in my predefined plugin .
In this case authenticator plugin.
What you are trying to achieve is perfectly possible, and is the way all components work in KrakenD. Your plugin can access the KrakenD configuration using the namespace you define. For instance, you could set your metadata like this (I am assuming you have in your Go code a pluginName = "slifer2015-authenticator" ):
{
"endpoints": [
{
"output_encoding": "no-op",
"backend": [
{
"encoding": "no-op",
"host": [
"127.0.0.1:8080"
],
"url_pattern": "/api/v1/address/{id}"
}
],
"endpoint": "/api/v1/addresses/{id}",
"extra_config": {
"github_com/devopsfaith/krakend/transport/http/server/handler": {
"name": [
"slifer2015-authenticator",
"some-other-plugin-here"
],
"slifer2015-authenticator": {
"Metadata1": "value1",
"Metadata2": {
"Some": 10,
"Thing": 100,
"Here": "60s"
}
}
}
}
}
]
}
Then your metada is available in the extra parameter when the registerer kicks in, inside the key you have chosen.
func (r registerer) registerHandlers(ctx context.Context, extra map[string]interface{}, h http.Handler) (http.Handler, error) {
``
So far I'm able to do swagger validation if the parameters are from "in": "body" or if the input expected is in a json format.
However, I can't find how to validate a simple string entered as formData.
Below is my swagger script (in json format)
v1swag = {
"cancels_post": {
"tags": ["/api/v1"],
"parameters": [
{
"name": "token",
"in": "formData",
"type": "string",
"required": True,
"description": "Cancels the provided token.",
}
],
"responses": {
"200": {
"description": "Success!",
}
}
}
}
I removed the schema as it seems to only work for "in": "body"
I've been searching the net but can't seem to find the light.
Though I will still be searching... Any hints would be greatly appreciated.
Thank you very much in advance.
A different source media type has to be consumed here. Specify "consumes" member to include media type of application/x-www-form-urlencoded.
v1swag = {
"cancels_post": {
"tags": ["/api/v1"],
"consumes": [
"application/x-www-form-urlencoded"
],
"parameters": [
{
"name": "token",
"in": "formData",
"type": "string",
"required": True,
"description": "Cancels the provided token.",
}
],
"responses": {
"200": {
"description": "Success!",
}
}
}
}
I've created a Spring Boot application with RestController. I enabled Swagger UI and it works fine as I can login to the UI and execute any GET methods. But for POST methods accepting objects in the body, when I fire off the request using Swagger UI, it always returns 400 status code. I can see the request never reached the particular POST method. May I know if any special config I need for Swagger UI?
The particular method in my Spring Boot RestController
#ApiOperation(value = "Query requests by search criteria")
#RequestMapping(value = "/api/query", method = POST)
public PageResult<MyPOJO> find(#RequestBody SearchRequest request) {
//implementation omitted.
}
and I'm using
"io.springfox:springfox-swagger2:2.1.2",
"io.springfox:springfox-swagger-ui:2.1.2"
This one (generated by Swagger UI) for the corresponding api gives me 400 bad request:
{
"listEntrySearchCriteria": {
"summary": {
"createdBy": "string",
"createdOn": "2016-03-21T10:33:05.048Z",
"effectiveEnd": "2016-03-21T10:33:05.048Z",
"effectiveStart": "2016-03-21T10:33:05.048Z",
"id": 0,
"region": "string",
"type": "ETB",
"updatedBy": "string",
"updatedOn": "2016-03-21T10:33:05.048Z",
"version": 0
}
},
"listSummarySearchCriteria": {
"effectiveEnd": "2016-03-21T10:33:05.048Z",
"effectiveStart": "2016-03-21T10:33:05.048Z",
"statuses": [
"string"
],
"types": [
"string"
]
},
"pageRequest": {
"orders": [
{
"direction": "ASC",
"ignoreCase": true,
"nullHandling": "NATIVE",
"property": "string"
}
],
"page": 0,
"size": 0
}
}
But if I supply a random request for the same method, it at least reaches my method:
{
"orders": [
{
"direction": "ASC",
"ignoreCase": true,
"nullHandling": "NATIVE",
"property": "id"
}
],
"page": 0,
"size": 0
}
i am trying to display the enum of a model in the model description.
The schema of my model is defined under definitions and uses an enum for the action property, because only this three types are allowed. (see code below)
I am using swagger version 2.0. In version 1.2 this seems to work: http://petstore.swagger.wordnik.com/ you can find the example under store/order.
they also use an enum and this is displayed behind the property in the model view.
How can i achieve the same result with the new version?
Thanks for help!
"paths": {
"/event": {
"post": {
"tags": [
"event"
],
"summary": "Add an new Event.",
"description": "TEST",
"operationId": "addEvent",
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"parameters": [
{
"in": "body",
"name": "data",
"description": "",
"required": true,
"schema": {
"$ref": "#/definitions/Event"
}
}
],
"responses": {
"405": {
"description": "Invalid input"
}
}
}
}
}
"definitions": {
"Event": {
"id": "eventModel",
"required": [
"action"
],
"properties": {
"action": {
"type": "string",
"default": "START",
"enum": [
"START",
"UPDATE",
"END"
],
"description": "blabla"
}
}
}
}
PS: another mistake i recognized right now, is that the shown model description of arrays misses the closing bracket ].
Your definition is fine, there's a known bug in swagger-ui - https://github.com/swagger-api/swagger-ui/issues/672. Feel free to subscribe the issue and follow the progress there.
As a side note, there's no "id" property in models in Swagger 2.0.