From 6c24eb632f31b36e04a37de8f99e5885df29efba Mon Sep 17 00:00:00 2001 From: "Badr.NassLahsen" Date: Sun, 16 Jun 2024 22:33:14 +0200 Subject: [PATCH] Spring Authorization Server Metadata Endpoint not compatible. fixes #2606 --- .../SpringDocSecurityOAuth2Customizer.java | 19 +- .../src/test/resources/results/app10.json | 134 +++++---- .../src/test/resources/results/app11.json | 189 +++++++++---- .../src/test/resources/results/app12.json | 266 +++++++++++------- 4 files changed, 400 insertions(+), 208 deletions(-) diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java index b8cfd52f0..d155b9459 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/configuration/SpringDocSecurityOAuth2Customizer.java @@ -4,6 +4,8 @@ import io.swagger.v3.core.util.AnnotationsUtils; import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.PathItem; @@ -18,9 +20,14 @@ import io.swagger.v3.oas.models.media.StringSchema; import io.swagger.v3.oas.models.parameters.HeaderParameter; import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.PathParameter; import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.responses.ApiResponses; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.security.SecurityScheme.In; +import io.swagger.v3.oas.models.security.SecurityScheme.Type; import org.apache.commons.lang3.reflect.FieldUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -182,6 +189,10 @@ private void getOAuth2AuthorizationServerMetadataEndpoint(OpenAPI openAPI, Secur ReflectionUtils.makeAccessible(field); String defaultOauth2MetadataUri = (String) ReflectionUtils.getField(field, null); openAPI.getPaths().addPathItem(defaultOauth2MetadataUri , new PathItem().get(operation)); + operation = buildOperation(apiResponses); + operation.addParametersItem(new PathParameter().name("subpath").schema(new StringSchema())); + operation.summary("Valid when multiple issuers are allowed"); + openAPI.getPaths().addPathItem(defaultOauth2MetadataUri+"/{subpath}" , new PathItem().get(operation)); } } } @@ -252,7 +263,7 @@ private void getOAuth2TokenEndpoint(OpenAPI openAPI, SecurityFilterChain securit String mediaType = org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; RequestBody requestBody = new RequestBody().content(new Content().addMediaType(mediaType, new MediaType().schema(requestSchema))); operation.setRequestBody(requestBody); - operation.addParametersItem(new HeaderParameter().name("Authorization")); + operation.addParametersItem(new HeaderParameter().name("Authorization").schema(new StringSchema())); buildPath(oAuth2EndpointFilter, "tokenEndpointMatcher", openAPI, operation, HttpMethod.POST); } @@ -310,6 +321,10 @@ private void getOidcProviderConfigurationEndpoint(OpenAPI openAPI, SecurityFilte ReflectionUtils.makeAccessible(field); String defaultOidcConfigUri = (String) ReflectionUtils.getField(field, null); openAPI.getPaths().addPathItem(defaultOidcConfigUri , new PathItem().get(operation)); + operation = buildOperation(apiResponses); + operation.addParametersItem(new PathParameter().name("subpath").schema(new StringSchema())); + operation.summary("Valid when multiple issuers are allowed"); + openAPI.getPaths().addPathItem("/{subpath}"+defaultOidcConfigUri , new PathItem().get(operation)); } } } @@ -360,7 +375,7 @@ private void getOidcClientRegistrationEndpoint(OpenAPI openAPI, SecurityFilterCh String mediaType = APPLICATION_JSON_VALUE; RequestBody requestBody = new RequestBody().content(new Content().addMediaType(mediaType, new MediaType().schema(schema))); operation.setRequestBody(requestBody); - operation.addParametersItem(new HeaderParameter().name("Authorization")); + operation.addParametersItem(new HeaderParameter().name("Authorization").schema(new StringSchema())); buildPath(oAuth2EndpointFilter, "clientRegistrationEndpointMatcher", openAPI, operation, HttpMethod.POST); } diff --git a/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app10.json b/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app10.json index c53212833..9ca244228 100644 --- a/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app10.json +++ b/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app10.json @@ -56,6 +56,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -65,6 +68,25 @@ } } } + } + } + } + }, + "/.well-known/oauth-authorization-server": { + "get": { + "tags": [ + "authorization-server-endpoints" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OAuth2AuthorizationServerMetadata" + } + } + } }, "500": { "description": "Internal Server Error" @@ -72,11 +94,22 @@ } } }, - "/.well-known/oauth-authorization-server": { + "/.well-known/oauth-authorization-server/{subpath}": { "get": { "tags": [ "authorization-server-endpoints" ], + "summary": "Valid when multiple issuers are allowed", + "parameters": [ + { + "name": "subpath", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK", @@ -101,8 +134,11 @@ ], "parameters": [ { + "name": "Authorization", "in": "header", - "name": "Authorization" + "schema": { + "type": "string" + } } ], "requestBody": { @@ -165,6 +201,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -184,9 +223,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -215,15 +251,8 @@ "text/html": {} } }, - "302": { - "description": "Moved Temporarily", - "headers": { - "Location": { - "schema": { - "type": "string" - } - } - } + "500": { + "description": "Internal Server Error" }, "400": { "description": "Bad Request", @@ -235,8 +264,15 @@ } } }, - "500": { - "description": "Internal Server Error" + "302": { + "description": "Moved Temporarily", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } } } } @@ -280,6 +316,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -289,9 +328,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -322,6 +358,9 @@ "200": { "description": "OK" }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -331,9 +370,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -358,9 +394,6 @@ "OAuth2AuthorizationServerMetadata": { "type": "object", "properties": { - "issuer": { - "type": "string" - }, "token_endpoint_auth_methods_supported": { "type": "array", "items": { @@ -397,16 +430,19 @@ "type": "string" } }, + "introspection_endpoint": { + "type": "string" + }, + "revocation_endpoint": { + "type": "string" + }, "grant_types_supported": { "type": "array", "items": { "type": "string" } }, - "revocation_endpoint": { - "type": "string" - }, - "introspection_endpoint": { + "issuer": { "type": "string" }, "jwks_uri": { @@ -424,13 +460,13 @@ "type": "integer", "format": "int64" }, - "access_token": { + "token_type": { "type": "string" }, - "refresh_token": { + "access_token": { "type": "string" }, - "token_type": { + "refresh_token": { "type": "string" } } @@ -438,26 +474,21 @@ "OAuth2TokenIntrospection": { "type": "object", "properties": { - "nbf": { - "type": "integer", - "format": "int64" - }, "scope": { "type": "string" }, "jti": { "type": "string" }, - "client_id": { - "type": "string" - }, - "username": { - "type": "string" + "exp": { + "type": "integer", + "format": "int64" }, - "active": { - "type": "boolean" + "nbf": { + "type": "integer", + "format": "int64" }, - "iss": { + "token_type": { "type": "string" }, "aud": { @@ -466,19 +497,24 @@ "type": "string" } }, - "token_type": { + "client_id": { "type": "string" }, - "exp": { - "type": "integer", - "format": "int64" + "username": { + "type": "string" }, - "sub": { + "iss": { "type": "string" }, + "active": { + "type": "boolean" + }, "iat": { "type": "integer", "format": "int64" + }, + "sub": { + "type": "string" } } } diff --git a/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app11.json b/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app11.json index 1f8119986..8d7a90106 100644 --- a/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app11.json +++ b/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app11.json @@ -56,6 +56,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -65,6 +68,25 @@ } } } + } + } + } + }, + "/.well-known/oauth-authorization-server": { + "get": { + "tags": [ + "authorization-server-endpoints" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OAuth2AuthorizationServerMetadata" + } + } + } }, "500": { "description": "Internal Server Error" @@ -72,11 +94,22 @@ } } }, - "/.well-known/oauth-authorization-server": { + "/.well-known/oauth-authorization-server/{subpath}": { "get": { "tags": [ "authorization-server-endpoints" ], + "summary": "Valid when multiple issuers are allowed", + "parameters": [ + { + "name": "subpath", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK", @@ -101,8 +134,11 @@ ], "parameters": [ { + "name": "Authorization", "in": "header", - "name": "Authorization" + "schema": { + "type": "string" + } } ], "requestBody": { @@ -165,6 +201,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -184,9 +223,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -215,15 +251,8 @@ "text/html": {} } }, - "302": { - "description": "Moved Temporarily", - "headers": { - "Location": { - "schema": { - "type": "string" - } - } - } + "500": { + "description": "Internal Server Error" }, "400": { "description": "Bad Request", @@ -235,8 +264,15 @@ } } }, - "500": { - "description": "Internal Server Error" + "302": { + "description": "Moved Temporarily", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } } } } @@ -280,6 +316,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -289,9 +328,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -322,6 +358,9 @@ "200": { "description": "OK" }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -331,6 +370,25 @@ } } } + } + } + } + }, + "/.well-known/openid-configuration": { + "get": { + "tags": [ + "authorization-server-endpoints" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OidcProviderConfiguration" + } + } + } }, "500": { "description": "Internal Server Error" @@ -338,11 +396,22 @@ } } }, - "/.well-known/openid-configuration": { + "/{subpath}/.well-known/openid-configuration": { "get": { "tags": [ "authorization-server-endpoints" ], + "summary": "Valid when multiple issuers are allowed", + "parameters": [ + { + "name": "subpath", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK", @@ -405,9 +474,6 @@ "OAuth2AuthorizationServerMetadata": { "type": "object", "properties": { - "issuer": { - "type": "string" - }, "token_endpoint_auth_methods_supported": { "type": "array", "items": { @@ -444,16 +510,19 @@ "type": "string" } }, + "introspection_endpoint": { + "type": "string" + }, + "revocation_endpoint": { + "type": "string" + }, "grant_types_supported": { "type": "array", "items": { "type": "string" } }, - "revocation_endpoint": { - "type": "string" - }, - "introspection_endpoint": { + "issuer": { "type": "string" }, "jwks_uri": { @@ -471,13 +540,13 @@ "type": "integer", "format": "int64" }, - "access_token": { + "token_type": { "type": "string" }, - "refresh_token": { + "access_token": { "type": "string" }, - "token_type": { + "refresh_token": { "type": "string" } } @@ -485,26 +554,21 @@ "OAuth2TokenIntrospection": { "type": "object", "properties": { - "nbf": { - "type": "integer", - "format": "int64" - }, "scope": { "type": "string" }, "jti": { "type": "string" }, - "client_id": { - "type": "string" - }, - "username": { - "type": "string" + "exp": { + "type": "integer", + "format": "int64" }, - "active": { - "type": "boolean" + "nbf": { + "type": "integer", + "format": "int64" }, - "iss": { + "token_type": { "type": "string" }, "aud": { @@ -513,25 +577,33 @@ "type": "string" } }, - "token_type": { + "client_id": { "type": "string" }, - "exp": { - "type": "integer", - "format": "int64" + "username": { + "type": "string" }, - "sub": { + "iss": { "type": "string" }, + "active": { + "type": "boolean" + }, "iat": { "type": "integer", "format": "int64" + }, + "sub": { + "type": "string" } } }, "OidcProviderConfiguration": { "type": "object", "properties": { + "id_token_signing_alg_values_supported": { + "type": "string" + }, "token_endpoint_auth_methods_supported": { "type": "array", "items": { @@ -556,22 +628,19 @@ "type": "string" } }, - "id_token_signing_alg_values_supported": { - "type": "string" - }, - "authorization_endpoint": { + "subject_types_supported": { "type": "string" }, - "token_endpoint": { + "scopes_supported": { "type": "string" }, "userinfo_endpoint": { "type": "string" }, - "subject_types_supported": { + "authorization_endpoint": { "type": "string" }, - "scopes_supported": { + "token_endpoint": { "type": "string" }, "response_types_supported": { @@ -580,18 +649,18 @@ "type": "string" } }, + "introspection_endpoint": { + "type": "string" + }, + "revocation_endpoint": { + "type": "string" + }, "grant_types_supported": { "type": "array", "items": { "type": "string" } }, - "revocation_endpoint": { - "type": "string" - }, - "introspection_endpoint": { - "type": "string" - }, "issuer": { "type": "string" }, diff --git a/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app12.json b/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app12.json index 8925e7038..a45d84f60 100644 --- a/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app12.json +++ b/springdoc-openapi-tests/springdoc-openapi-security-tests/src/test/resources/results/app12.json @@ -56,6 +56,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -65,6 +68,25 @@ } } } + } + } + } + }, + "/.well-known/oauth-authorization-server": { + "get": { + "tags": [ + "authorization-server-endpoints" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OAuth2AuthorizationServerMetadata" + } + } + } }, "500": { "description": "Internal Server Error" @@ -72,11 +94,22 @@ } } }, - "/.well-known/oauth-authorization-server": { + "/.well-known/oauth-authorization-server/{subpath}": { "get": { "tags": [ "authorization-server-endpoints" ], + "summary": "Valid when multiple issuers are allowed", + "parameters": [ + { + "name": "subpath", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK", @@ -101,8 +134,11 @@ ], "parameters": [ { + "name": "Authorization", "in": "header", - "name": "Authorization" + "schema": { + "type": "string" + } } ], "requestBody": { @@ -165,6 +201,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -184,9 +223,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -215,15 +251,8 @@ "text/html": {} } }, - "302": { - "description": "Moved Temporarily", - "headers": { - "Location": { - "schema": { - "type": "string" - } - } - } + "500": { + "description": "Internal Server Error" }, "400": { "description": "Bad Request", @@ -235,8 +264,15 @@ } } }, - "500": { - "description": "Internal Server Error" + "302": { + "description": "Moved Temporarily", + "headers": { + "Location": { + "schema": { + "type": "string" + } + } + } } } } @@ -280,6 +316,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -289,9 +328,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -322,6 +358,9 @@ "200": { "description": "OK" }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -331,6 +370,25 @@ } } } + } + } + } + }, + "/.well-known/openid-configuration": { + "get": { + "tags": [ + "authorization-server-endpoints" + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OidcProviderConfiguration" + } + } + } }, "500": { "description": "Internal Server Error" @@ -338,11 +396,22 @@ } } }, - "/.well-known/openid-configuration": { + "/{subpath}/.well-known/openid-configuration": { "get": { "tags": [ "authorization-server-endpoints" ], + "summary": "Valid when multiple issuers are allowed", + "parameters": [ + { + "name": "subpath", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK", @@ -393,7 +462,10 @@ "parameters": [ { "name": "Authorization", - "in": "header" + "in": "header", + "schema": { + "type": "string" + } } ], "requestBody": { @@ -416,6 +488,9 @@ } } }, + "500": { + "description": "Internal Server Error" + }, "400": { "description": "Bad Request", "content": { @@ -445,9 +520,6 @@ } } } - }, - "500": { - "description": "Internal Server Error" } } } @@ -472,9 +544,6 @@ "OAuth2AuthorizationServerMetadata": { "type": "object", "properties": { - "issuer": { - "type": "string" - }, "token_endpoint_auth_methods_supported": { "type": "array", "items": { @@ -511,16 +580,19 @@ "type": "string" } }, + "introspection_endpoint": { + "type": "string" + }, + "revocation_endpoint": { + "type": "string" + }, "grant_types_supported": { "type": "array", "items": { "type": "string" } }, - "revocation_endpoint": { - "type": "string" - }, - "introspection_endpoint": { + "issuer": { "type": "string" }, "jwks_uri": { @@ -538,13 +610,13 @@ "type": "integer", "format": "int64" }, - "access_token": { + "token_type": { "type": "string" }, - "refresh_token": { + "access_token": { "type": "string" }, - "token_type": { + "refresh_token": { "type": "string" } } @@ -552,26 +624,21 @@ "OAuth2TokenIntrospection": { "type": "object", "properties": { - "nbf": { - "type": "integer", - "format": "int64" - }, "scope": { "type": "string" }, "jti": { "type": "string" }, - "client_id": { - "type": "string" - }, - "username": { - "type": "string" + "exp": { + "type": "integer", + "format": "int64" }, - "active": { - "type": "boolean" + "nbf": { + "type": "integer", + "format": "int64" }, - "iss": { + "token_type": { "type": "string" }, "aud": { @@ -580,25 +647,33 @@ "type": "string" } }, - "token_type": { + "client_id": { "type": "string" }, - "exp": { - "type": "integer", - "format": "int64" + "username": { + "type": "string" }, - "sub": { + "iss": { "type": "string" }, + "active": { + "type": "boolean" + }, "iat": { "type": "integer", "format": "int64" + }, + "sub": { + "type": "string" } } }, "OidcProviderConfiguration": { "type": "object", "properties": { + "id_token_signing_alg_values_supported": { + "type": "string" + }, "token_endpoint_auth_methods_supported": { "type": "array", "items": { @@ -623,22 +698,19 @@ "type": "string" } }, - "id_token_signing_alg_values_supported": { - "type": "string" - }, - "authorization_endpoint": { + "subject_types_supported": { "type": "string" }, - "token_endpoint": { + "scopes_supported": { "type": "string" }, "userinfo_endpoint": { "type": "string" }, - "subject_types_supported": { + "authorization_endpoint": { "type": "string" }, - "scopes_supported": { + "token_endpoint": { "type": "string" }, "response_types_supported": { @@ -647,18 +719,18 @@ "type": "string" } }, + "introspection_endpoint": { + "type": "string" + }, + "revocation_endpoint": { + "type": "string" + }, "grant_types_supported": { "type": "array", "items": { "type": "string" } }, - "revocation_endpoint": { - "type": "string" - }, - "introspection_endpoint": { - "type": "string" - }, "issuer": { "type": "string" }, @@ -676,22 +748,13 @@ "id_token_signed_response_alg": { "type": "string" }, - "response_types": { - "type": "array", - "items": { - "type": "string" - } - }, - "client_secret": { + "registration_access_token": { "type": "string" }, "client_secret_expires_at": { "type": "integer", "format": "int64" }, - "registration_access_token": { - "type": "string" - }, "registration_client_uri": { "type": "string" }, @@ -705,12 +768,27 @@ "type": "string" } }, - "scope": { + "client_secret": { "type": "string" }, + "response_types": { + "type": "array", + "items": { + "type": "string" + } + }, "client_id": { "type": "string" }, + "client_name": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, "token_endpoint_auth_signing_alg": { "type": "string" }, @@ -719,12 +797,6 @@ "items": { "type": "string" } - }, - "jwks_uri": { - "type": "string" - }, - "client_name": { - "type": "string" } } }, @@ -737,15 +809,6 @@ "id_token_signed_response_alg": { "type": "string" }, - "response_types": { - "type": "array", - "items": { - "type": "string" - } - }, - "client_secret": { - "type": "string" - }, "client_secret_expires_at": { "type": "string", "format": "date-time" @@ -760,12 +823,27 @@ "type": "string" } }, - "scope": { + "client_secret": { "type": "string" }, + "response_types": { + "type": "array", + "items": { + "type": "string" + } + }, "client_id": { "type": "string" }, + "client_name": { + "type": "string" + }, + "jwks_uri": { + "type": "string" + }, + "scope": { + "type": "string" + }, "token_endpoint_auth_signing_alg": { "type": "string" }, @@ -774,12 +852,6 @@ "items": { "type": "string" } - }, - "jwks_uri": { - "type": "string" - }, - "client_name": { - "type": "string" } } }