|
3 | 3 | import com.dotcms.filters.interceptor.saml.SamlWebUtils; |
4 | 4 | import com.dotcms.rest.WebResource; |
5 | 5 | import com.dotcms.rest.annotation.NoCache; |
| 6 | +import com.dotcms.rest.annotation.SwaggerCompliant; |
6 | 7 | import com.dotcms.saml.Attributes; |
7 | 8 | import com.dotcms.saml.DotSamlConstants; |
8 | 9 | import com.dotcms.saml.DotSamlException; |
|
21 | 22 | import com.dotmarketing.util.WebKeys; |
22 | 23 | import com.google.common.annotations.VisibleForTesting; |
23 | 24 | import com.liferay.portal.model.User; |
| 25 | +import io.swagger.v3.oas.annotations.Operation; |
| 26 | +import io.swagger.v3.oas.annotations.Parameter; |
| 27 | +import io.swagger.v3.oas.annotations.media.Content; |
| 28 | +import io.swagger.v3.oas.annotations.parameters.RequestBody; |
| 29 | +import io.swagger.v3.oas.annotations.responses.ApiResponse; |
| 30 | +import io.swagger.v3.oas.annotations.responses.ApiResponses; |
24 | 31 | import io.swagger.v3.oas.annotations.tags.Tag; |
25 | 32 | import org.glassfish.jersey.server.JSONP; |
26 | 33 |
|
|
49 | 56 | * - metadata renders the XML metadata. |
50 | 57 | * @author jsanca |
51 | 58 | */ |
| 59 | +@SwaggerCompliant(value = "Core authentication and user management APIs", batch = 1) |
52 | 60 | @Tag(name = "SAML Authentication") |
53 | 61 | @Path("/v1/dotsaml") |
54 | 62 | public class DotSamlResource implements Serializable { |
@@ -98,12 +106,29 @@ protected DotSamlResource(final SamlConfigurationService samlConfigura |
98 | 106 | * @param httpServletResponse {@link HttpServletResponse} |
99 | 107 | * @return Response |
100 | 108 | */ |
| 109 | + @Operation( |
| 110 | + summary = "Initiate SAML login", |
| 111 | + description = "Initiates a SAML authentication request by redirecting the user to the Identity Provider (IDP) login screen. Requires IDP metadata to determine the SSO login endpoint." |
| 112 | + ) |
| 113 | + @ApiResponses(value = { |
| 114 | + @ApiResponse(responseCode = "200", |
| 115 | + description = "SAML authentication request initiated successfully (no body)"), |
| 116 | + @ApiResponse(responseCode = "400", |
| 117 | + description = "Bad request - invalid IDP configuration ID", |
| 118 | + content = @Content(mediaType = "application/json")), |
| 119 | + @ApiResponse(responseCode = "404", |
| 120 | + description = "IDP configuration not found or not enabled", |
| 121 | + content = @Content(mediaType = "application/json")), |
| 122 | + @ApiResponse(responseCode = "500", |
| 123 | + description = "Internal server error during SAML authentication initiation", |
| 124 | + content = @Content(mediaType = "application/json")) |
| 125 | + }) |
101 | 126 | @GET |
102 | 127 | @Path( "/login/{idpConfigId}" ) |
103 | 128 | @JSONP |
104 | 129 | @NoCache |
105 | | - @Produces( { MediaType.APPLICATION_JSON, "application/javascript" } ) |
106 | | - public Response doLogin(@PathParam( "idpConfigId" ) final String idpConfigId, |
| 130 | + @Produces( { MediaType.APPLICATION_JSON } ) |
| 131 | + public Response doLogin(@Parameter(description = "Identity Provider configuration ID (typically host ID)", required = true) @PathParam( "idpConfigId" ) final String idpConfigId, |
107 | 132 | @Context final HttpServletRequest httpServletRequest, |
108 | 133 | @Context final HttpServletResponse httpServletResponse) { |
109 | 134 |
|
@@ -148,12 +173,36 @@ public Response doLogin(@PathParam( "idpConfigId" ) final String idpConfigId, |
148 | 173 | * @param httpServletResponse {@link HttpServletResponse} |
149 | 174 | * @throws IOException |
150 | 175 | */ |
| 176 | + @Operation( |
| 177 | + summary = "Process SAML login callback", |
| 178 | + description = "Handles the callback from the Identity Provider after successful authentication. Extracts user information from the SAML assertion and creates/logs in the user to dotCMS.", |
| 179 | + requestBody = @RequestBody(description = "SAML assertion data from Identity Provider", required = true, |
| 180 | + content = {@Content(mediaType = "application/xml"), |
| 181 | + @Content(mediaType = "application/x-www-form-urlencoded")}) |
| 182 | + ) |
| 183 | + @ApiResponses(value = { |
| 184 | + @ApiResponse(responseCode = "200", |
| 185 | + description = "SAML login processed successfully - user logged in", |
| 186 | + content = @Content(mediaType = "text/html")), |
| 187 | + @ApiResponse(responseCode = "400", |
| 188 | + description = "Bad request - invalid SAML assertion or missing data", |
| 189 | + content = @Content(mediaType = "text/html")), |
| 190 | + @ApiResponse(responseCode = "401", |
| 191 | + description = "Unauthorized - SAML assertion validation failed", |
| 192 | + content = @Content(mediaType = "text/html")), |
| 193 | + @ApiResponse(responseCode = "404", |
| 194 | + description = "IDP configuration not found or not enabled", |
| 195 | + content = @Content(mediaType = "text/html")), |
| 196 | + @ApiResponse(responseCode = "500", |
| 197 | + description = "Internal server error during SAML login processing", |
| 198 | + content = @Content(mediaType = "text/html")) |
| 199 | + }) |
151 | 200 | @POST |
152 | 201 | @Path("/login/{idpConfigId}") |
153 | 202 | @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_FORM_URLENCODED}) |
154 | 203 | @Produces( { MediaType.APPLICATION_XML, "text/html" } ) |
155 | 204 | @NoCache |
156 | | - public void processLogin(@PathParam("idpConfigId") final String idpConfigId, |
| 205 | + public void processLogin(@Parameter(description = "Identity Provider configuration ID (typically host ID)", required = true) @PathParam("idpConfigId") final String idpConfigId, |
157 | 206 | @Context final HttpServletRequest httpServletRequest, |
158 | 207 | @Context final HttpServletResponse httpServletResponse) throws IOException { |
159 | 208 |
|
@@ -272,12 +321,33 @@ public void processLogin(@PathParam("idpConfigId") final String idpConfigId, |
272 | 321 | * @param httpServletResponse {@link HttpServletResponse} |
273 | 322 | * @throws IOException |
274 | 323 | */ |
| 324 | + @Operation( |
| 325 | + summary = "Get SAML metadata", |
| 326 | + description = "Renders the XML metadata for the SAML Service Provider configuration. This endpoint is only accessible by administrators and provides the metadata required for IDP configuration." |
| 327 | + ) |
| 328 | + @ApiResponses(value = { |
| 329 | + @ApiResponse(responseCode = "200", |
| 330 | + description = "SAML metadata rendered successfully", |
| 331 | + content = @Content(mediaType = "application/xml")), |
| 332 | + @ApiResponse(responseCode = "401", |
| 333 | + description = "Unauthorized - admin access required", |
| 334 | + content = @Content(mediaType = "application/xml")), |
| 335 | + @ApiResponse(responseCode = "403", |
| 336 | + description = "Forbidden - user is not an administrator", |
| 337 | + content = @Content(mediaType = "application/xml")), |
| 338 | + @ApiResponse(responseCode = "404", |
| 339 | + description = "IDP configuration not found or not enabled", |
| 340 | + content = @Content(mediaType = "application/xml")), |
| 341 | + @ApiResponse(responseCode = "500", |
| 342 | + description = "Internal server error rendering metadata", |
| 343 | + content = @Content(mediaType = "application/xml")) |
| 344 | + }) |
275 | 345 | @GET |
276 | 346 | @Path( "/metadata/{idpConfigId}" ) |
277 | 347 | @JSONP |
278 | 348 | @NoCache |
279 | 349 | @Produces( { MediaType.APPLICATION_XML, "application/xml" } ) |
280 | | - public void metadata( @PathParam( "idpConfigId" ) final String idpConfigId, |
| 350 | + public void metadata( @Parameter(description = "Identity Provider configuration ID (typically host ID)", required = true) @PathParam( "idpConfigId" ) final String idpConfigId, |
281 | 351 | @Context final HttpServletRequest httpServletRequest, |
282 | 352 | @Context final HttpServletResponse httpServletResponse ) throws IOException { |
283 | 353 |
|
@@ -313,12 +383,27 @@ public void metadata( @PathParam( "idpConfigId" ) final String idpConfigId, |
313 | 383 | throw new DoesNotExistException(message); |
314 | 384 | } |
315 | 385 |
|
| 386 | + @Operation( |
| 387 | + summary = "Process SAML logout (POST)", |
| 388 | + description = "Processes a SAML logout request via POST method. Handles logout callbacks from the Identity Provider and redirects to the configured logout endpoint." |
| 389 | + ) |
| 390 | + @ApiResponses(value = { |
| 391 | + @ApiResponse(responseCode = "200", |
| 392 | + description = "SAML logout processed successfully", |
| 393 | + content = @Content(mediaType = "text/html")), |
| 394 | + @ApiResponse(responseCode = "404", |
| 395 | + description = "IDP configuration not found or not enabled", |
| 396 | + content = @Content(mediaType = "text/html")), |
| 397 | + @ApiResponse(responseCode = "500", |
| 398 | + description = "Internal server error during logout processing", |
| 399 | + content = @Content(mediaType = "text/html")) |
| 400 | + }) |
316 | 401 | @POST |
317 | 402 | @Path("/logout/{idpConfigId}") |
318 | 403 | @NoCache |
319 | 404 | @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML}) |
320 | 405 | // Login configuration by id |
321 | | - public void logoutPost(@PathParam("idpConfigId") final String idpConfigId, |
| 406 | + public void logoutPost(@Parameter(description = "Identity Provider configuration ID (typically host ID)", required = true) @PathParam("idpConfigId") final String idpConfigId, |
322 | 407 | @Context final HttpServletRequest httpServletRequest, |
323 | 408 | @Context final HttpServletResponse httpServletResponse) throws IOException, URISyntaxException { |
324 | 409 |
|
@@ -350,12 +435,27 @@ public void logoutPost(@PathParam("idpConfigId") final String idpConfigId, |
350 | 435 | throw new DoesNotExistException(message); |
351 | 436 | } |
352 | 437 |
|
| 438 | + @Operation( |
| 439 | + summary = "Process SAML logout (GET)", |
| 440 | + description = "Processes a SAML logout request via GET method. Initiates logout flow and redirects to the configured logout endpoint or builds a logout URL based on the request." |
| 441 | + ) |
| 442 | + @ApiResponses(value = { |
| 443 | + @ApiResponse(responseCode = "200", |
| 444 | + description = "SAML logout processed successfully", |
| 445 | + content = @Content(mediaType = "text/html")), |
| 446 | + @ApiResponse(responseCode = "404", |
| 447 | + description = "IDP configuration not found or not enabled", |
| 448 | + content = @Content(mediaType = "text/html")), |
| 449 | + @ApiResponse(responseCode = "500", |
| 450 | + description = "Internal server error during logout processing", |
| 451 | + content = @Content(mediaType = "text/html")) |
| 452 | + }) |
353 | 453 | @GET |
354 | 454 | @Path("/logout/{idpConfigId}") |
355 | 455 | @NoCache |
356 | 456 | @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_XHTML_XML}) |
357 | 457 | // Login configuration by id |
358 | | - public void logoutGet(@PathParam("idpConfigId") final String idpConfigId, |
| 458 | + public void logoutGet(@Parameter(description = "Identity Provider configuration ID (typically host ID)", required = true) @PathParam("idpConfigId") final String idpConfigId, |
359 | 459 | @Context final HttpServletRequest httpServletRequest, |
360 | 460 | @Context final HttpServletResponse httpServletResponse) throws IOException, URISyntaxException { |
361 | 461 |
|
|
0 commit comments