|
26 | 26 | import org.springdoc.core.configuration.oauth2.SpringDocOAuth2AuthorizationServerMetadata;
|
27 | 27 | import org.springdoc.core.configuration.oauth2.SpringDocOAuth2Token;
|
28 | 28 | import org.springdoc.core.configuration.oauth2.SpringDocOAuth2TokenIntrospection;
|
| 29 | +import org.springdoc.core.configuration.oauth2.SpringDocOidcClientRegistrationRequest; |
| 30 | +import org.springdoc.core.configuration.oauth2.SpringDocOidcClientRegistrationResponse; |
| 31 | +import org.springdoc.core.configuration.oauth2.SpringDocOidcProviderConfiguration; |
29 | 32 | import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
|
30 |
| -import org.springdoc.core.utils.SpringDocAnnotationsUtils; |
31 | 33 |
|
32 | 34 | import org.springframework.beans.BeansException;
|
33 | 35 | import org.springframework.context.ApplicationContext;
|
|
37 | 39 | import org.springframework.security.oauth2.core.AuthorizationGrantType;
|
38 | 40 | import org.springframework.security.oauth2.core.OAuth2Error;
|
39 | 41 | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
|
| 42 | +import org.springframework.security.oauth2.server.authorization.oidc.web.OidcClientRegistrationEndpointFilter; |
| 43 | +import org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter; |
| 44 | +import org.springframework.security.oauth2.server.authorization.oidc.web.OidcUserInfoEndpointFilter; |
40 | 45 | import org.springframework.security.oauth2.server.authorization.web.NimbusJwkSetEndpointFilter;
|
41 | 46 | import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter;
|
42 | 47 | import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationServerMetadataEndpointFilter;
|
@@ -85,6 +90,9 @@ public void customise(OpenAPI openAPI) {
|
85 | 90 | getOAuth2AuthorizationEndpoint(openAPI, filterChain);
|
86 | 91 | getOAuth2TokenIntrospectionEndpointFilter(openAPI, filterChain);
|
87 | 92 | getOAuth2TokenRevocationEndpointFilter(openAPI, filterChain);
|
| 93 | + getOidcProviderConfigurationEndpoint(openAPI, filterChain); |
| 94 | + getOidcUserInfoEndpoint(openAPI, filterChain); |
| 95 | + getOidcClientRegistrationEndpoint(openAPI, filterChain); |
88 | 96 | }
|
89 | 97 | }
|
90 | 98 |
|
@@ -259,6 +267,76 @@ private void getOAuth2AuthorizationEndpoint(OpenAPI openAPI, SecurityFilterChain
|
259 | 267 | }
|
260 | 268 | }
|
261 | 269 |
|
| 270 | + /** |
| 271 | + * Gets OpenID Provider endpoint filter |
| 272 | + * |
| 273 | + * @param openAPI the open api |
| 274 | + * @param securityFilterChain the security filter chain |
| 275 | + */ |
| 276 | + private void getOidcProviderConfigurationEndpoint(OpenAPI openAPI, SecurityFilterChain securityFilterChain) { |
| 277 | + Object oAuth2EndpointFilter = |
| 278 | + new SpringDocSecurityOAuth2EndpointUtils(OidcProviderConfigurationEndpointFilter.class).findEndpoint(securityFilterChain); |
| 279 | + |
| 280 | + if (oAuth2EndpointFilter != null) { |
| 281 | + ApiResponses apiResponses = new ApiResponses(); |
| 282 | + buildApiResponsesOnSuccess(apiResponses, AnnotationsUtils.resolveSchemaFromType(SpringDocOidcProviderConfiguration.class, openAPI.getComponents(), null)); |
| 283 | + buildApiResponsesOnInternalServerError(apiResponses); |
| 284 | + Operation operation = buildOperation(apiResponses); |
| 285 | + buildPath(oAuth2EndpointFilter, "requestMatcher", openAPI, operation, HttpMethod.GET); |
| 286 | + } |
| 287 | + } |
| 288 | + |
| 289 | + /** |
| 290 | + * Gets OpenID UserInfo endpoint filter |
| 291 | + * |
| 292 | + * @param openAPI the open api |
| 293 | + * @param securityFilterChain the security filter chain |
| 294 | + */ |
| 295 | + private void getOidcUserInfoEndpoint(OpenAPI openAPI, SecurityFilterChain securityFilterChain) { |
| 296 | + Object oAuth2EndpointFilter = |
| 297 | + new SpringDocSecurityOAuth2EndpointUtils(OidcUserInfoEndpointFilter.class).findEndpoint(securityFilterChain); |
| 298 | + |
| 299 | + if (oAuth2EndpointFilter != null) { |
| 300 | + ApiResponses apiResponses = new ApiResponses(); |
| 301 | + Schema<?> schema = new ObjectSchema().additionalProperties(new StringSchema()); |
| 302 | + buildApiResponsesOnSuccess(apiResponses, schema); |
| 303 | + buildApiResponsesOnInternalServerError(apiResponses); |
| 304 | + Operation operation = buildOperation(apiResponses); |
| 305 | + buildPath(oAuth2EndpointFilter, "userInfoEndpointMatcher", openAPI, operation, HttpMethod.GET); |
| 306 | + } |
| 307 | + } |
| 308 | + |
| 309 | + /** |
| 310 | + * Gets OpenID Client Registration endpoint filter |
| 311 | + * |
| 312 | + * @param openAPI the open api |
| 313 | + * @param securityFilterChain the security filter chain |
| 314 | + */ |
| 315 | + private void getOidcClientRegistrationEndpoint(OpenAPI openAPI, SecurityFilterChain securityFilterChain) { |
| 316 | + Object oAuth2EndpointFilter = |
| 317 | + new SpringDocSecurityOAuth2EndpointUtils(OidcClientRegistrationEndpointFilter.class).findEndpoint(securityFilterChain); |
| 318 | + |
| 319 | + if (oAuth2EndpointFilter != null) { |
| 320 | + ApiResponses apiResponses = new ApiResponses(); |
| 321 | + buildApiResponsesOnCreated(apiResponses, AnnotationsUtils.resolveSchemaFromType(SpringDocOidcClientRegistrationResponse.class, openAPI.getComponents(), null)); |
| 322 | + buildApiResponsesOnInternalServerError(apiResponses); |
| 323 | + buildApiResponsesOnBadRequest(apiResponses, openAPI); |
| 324 | + buildOAuth2Error(openAPI, apiResponses, HttpStatus.UNAUTHORIZED); |
| 325 | + buildOAuth2Error(openAPI, apiResponses, HttpStatus.FORBIDDEN); |
| 326 | + Operation operation = buildOperation(apiResponses); |
| 327 | + |
| 328 | + // OidcClientRegistration |
| 329 | + Schema schema = AnnotationsUtils.resolveSchemaFromType(SpringDocOidcClientRegistrationRequest.class, openAPI.getComponents(), null); |
| 330 | + |
| 331 | + String mediaType = APPLICATION_JSON_VALUE; |
| 332 | + RequestBody requestBody = new RequestBody().content(new Content().addMediaType(mediaType, new MediaType().schema(schema))); |
| 333 | + operation.setRequestBody(requestBody); |
| 334 | + operation.addParametersItem(new HeaderParameter().name("Authorization")); |
| 335 | + |
| 336 | + buildPath(oAuth2EndpointFilter, "clientRegistrationEndpointMatcher", openAPI, operation, HttpMethod.POST); |
| 337 | + } |
| 338 | + } |
| 339 | + |
262 | 340 | /**
|
263 | 341 | * Build operation operation.
|
264 | 342 | *
|
@@ -287,6 +365,21 @@ private ApiResponses buildApiResponsesOnSuccess(ApiResponses apiResponses, Schem
|
287 | 365 | return apiResponses;
|
288 | 366 | }
|
289 | 367 |
|
| 368 | + /** |
| 369 | + * Build api responses api responses on created. |
| 370 | + * |
| 371 | + * @param apiResponses the api responses |
| 372 | + * @param schema the schema |
| 373 | + * @return the api responses |
| 374 | + */ |
| 375 | + private ApiResponses buildApiResponsesOnCreated(ApiResponses apiResponses, Schema schema) { |
| 376 | + ApiResponse response = new ApiResponse().description(HttpStatus.CREATED.getReasonPhrase()).content(new Content().addMediaType( |
| 377 | + APPLICATION_JSON_VALUE, |
| 378 | + new MediaType().schema(schema))); |
| 379 | + apiResponses.addApiResponse(String.valueOf(HttpStatus.CREATED.value()), response); |
| 380 | + return apiResponses; |
| 381 | + } |
| 382 | + |
290 | 383 | /**
|
291 | 384 | * Build api responses api responses on internal server error.
|
292 | 385 | *
|
@@ -338,22 +431,23 @@ private void buildPath(Object oAuth2EndpointFilter, String authorizationEndpoint
|
338 | 431 | Field tokenEndpointMatcherField = FieldUtils.getDeclaredField(oAuth2EndpointFilter.getClass(), authorizationEndpointMatcher, true);
|
339 | 432 | RequestMatcher endpointMatcher = (RequestMatcher) tokenEndpointMatcherField.get(oAuth2EndpointFilter);
|
340 | 433 | String path = null;
|
341 |
| - if (endpointMatcher instanceof AntPathRequestMatcher) |
342 |
| - path = ((AntPathRequestMatcher) endpointMatcher).getPattern(); |
343 |
| - else if (endpointMatcher instanceof OrRequestMatcher) { |
344 |
| - OrRequestMatcher endpointMatchers = (OrRequestMatcher) endpointMatcher; |
| 434 | + if (endpointMatcher instanceof AntPathRequestMatcher antPathRequestMatcher) |
| 435 | + path = antPathRequestMatcher.getPattern(); |
| 436 | + else if (endpointMatcher instanceof OrRequestMatcher endpointMatchers) { |
345 | 437 | Field requestMatchersField = FieldUtils.getDeclaredField(OrRequestMatcher.class, "requestMatchers", true);
|
346 | 438 | Iterable<RequestMatcher> requestMatchers = (Iterable<RequestMatcher>) requestMatchersField.get(endpointMatchers);
|
347 | 439 | for (RequestMatcher requestMatcher : requestMatchers) {
|
348 |
| - if (requestMatcher instanceof OrRequestMatcher) { |
349 |
| - OrRequestMatcher orRequestMatcher = (OrRequestMatcher) requestMatcher; |
| 440 | + if (requestMatcher instanceof OrRequestMatcher orRequestMatcher) { |
350 | 441 | requestMatchersField = FieldUtils.getDeclaredField(OrRequestMatcher.class, "requestMatchers", true);
|
351 | 442 | requestMatchers = (Iterable<RequestMatcher>) requestMatchersField.get(orRequestMatcher);
|
352 | 443 | for (RequestMatcher matcher : requestMatchers) {
|
353 |
| - if (matcher instanceof AntPathRequestMatcher) |
354 |
| - path = ((AntPathRequestMatcher) matcher).getPattern(); |
| 444 | + if (matcher instanceof AntPathRequestMatcher antPathRequestMatcher) |
| 445 | + path = antPathRequestMatcher.getPattern(); |
355 | 446 | }
|
356 | 447 | }
|
| 448 | + else if (requestMatcher instanceof AntPathRequestMatcher antPathRequestMatcher) { |
| 449 | + path = antPathRequestMatcher.getPattern(); |
| 450 | + } |
357 | 451 | }
|
358 | 452 | }
|
359 | 453 |
|
|
0 commit comments