mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-16 19:33:11 +02:00
Fix: Access to Swagger UI when login enabled (#5194)
Fixes for /swagger-ui/index.html & /v1/api-docs endpoints not being accessible when login was enabled. - `UserAuthenticationFilter.isPublicAuthEndpoint()` had gaps in its check, missing `/v1/api-docs` - Refactored `UserAuthenticationFilter` to use `RequestUriUtils.isPublicAuthEndpoint()` instead of its own incorrect method Closes #5125 & #5028 --- ### Testing (if applicable) - [x] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
@@ -162,10 +162,9 @@ public class RequestUriUtils {
|
|||||||
// enableLogin)
|
// enableLogin)
|
||||||
|| trimmedUri.startsWith(
|
|| trimmedUri.startsWith(
|
||||||
"/api/v1/ui-data/footer-info") // Public footer configuration
|
"/api/v1/ui-data/footer-info") // Public footer configuration
|
||||||
|| trimmedUri.startsWith("/v1/api-docs")
|
|
||||||
|| trimmedUri.startsWith("/api/v1/invite/validate")
|
|| trimmedUri.startsWith("/api/v1/invite/validate")
|
||||||
|| trimmedUri.startsWith("/api/v1/invite/accept")
|
|| trimmedUri.startsWith("/api/v1/invite/accept")
|
||||||
|| trimmedUri.contains("/v1/api-docs");
|
|| trimmedUri.startsWith("/v1/api-docs");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String stripContextPath(String contextPath, String requestURI) {
|
private static String stripContextPath(String contextPath, String requestURI) {
|
||||||
|
|||||||
@@ -62,10 +62,14 @@ public class OpenApiConfig {
|
|||||||
|
|
||||||
// Add server configuration from environment variable
|
// Add server configuration from environment variable
|
||||||
String swaggerServerUrl = System.getenv("SWAGGER_SERVER_URL");
|
String swaggerServerUrl = System.getenv("SWAGGER_SERVER_URL");
|
||||||
|
Server server;
|
||||||
if (swaggerServerUrl != null && !swaggerServerUrl.trim().isEmpty()) {
|
if (swaggerServerUrl != null && !swaggerServerUrl.trim().isEmpty()) {
|
||||||
Server server = new Server().url(swaggerServerUrl).description("API Server");
|
server = new Server().url(swaggerServerUrl).description("API Server");
|
||||||
openAPI.addServersItem(server);
|
} else {
|
||||||
|
// Use relative path so Swagger uses the current browser origin to avoid CORS issues when accessing via different ports
|
||||||
|
server = new Server().url("/").description("Current Server");
|
||||||
}
|
}
|
||||||
|
openAPI.addServersItem(server);
|
||||||
|
|
||||||
// Add ErrorResponse schema to components
|
// Add ErrorResponse schema to components
|
||||||
Schema<?> errorResponseSchema =
|
Schema<?> errorResponseSchema =
|
||||||
|
|||||||
+8
-18
@@ -26,6 +26,7 @@ import jakarta.servlet.ServletException;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import stirling.software.common.model.ApplicationProperties;
|
import stirling.software.common.model.ApplicationProperties;
|
||||||
@@ -39,6 +40,7 @@ import stirling.software.proprietary.security.service.JwtServiceInterface;
|
|||||||
import stirling.software.proprietary.security.service.UserService;
|
import stirling.software.proprietary.security.service.UserService;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private final JwtServiceInterface jwtService;
|
private final JwtServiceInterface jwtService;
|
||||||
@@ -47,19 +49,6 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
private final AuthenticationEntryPoint authenticationEntryPoint;
|
private final AuthenticationEntryPoint authenticationEntryPoint;
|
||||||
private final ApplicationProperties.Security securityProperties;
|
private final ApplicationProperties.Security securityProperties;
|
||||||
|
|
||||||
public JwtAuthenticationFilter(
|
|
||||||
JwtServiceInterface jwtService,
|
|
||||||
UserService userService,
|
|
||||||
CustomUserDetailsService userDetailsService,
|
|
||||||
AuthenticationEntryPoint authenticationEntryPoint,
|
|
||||||
ApplicationProperties.Security securityProperties) {
|
|
||||||
this.jwtService = jwtService;
|
|
||||||
this.userService = userService;
|
|
||||||
this.userDetailsService = userDetailsService;
|
|
||||||
this.authenticationEntryPoint = authenticationEntryPoint;
|
|
||||||
this.securityProperties = securityProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doFilterInternal(
|
protected void doFilterInternal(
|
||||||
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||||
@@ -68,7 +57,11 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isStaticResource(request.getContextPath(), request.getRequestURI())) {
|
|
||||||
|
String requestURI = request.getRequestURI();
|
||||||
|
String contextPath = request.getContextPath();
|
||||||
|
|
||||||
|
if (isStaticResource(contextPath, requestURI)) {
|
||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -77,10 +70,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
String jwtToken = jwtService.extractToken(request);
|
String jwtToken = jwtService.extractToken(request);
|
||||||
|
|
||||||
if (jwtToken == null) {
|
if (jwtToken == null) {
|
||||||
// Allow specific auth endpoints to pass through without JWT
|
// Allow auth endpoints to pass through without JWT
|
||||||
String requestURI = request.getRequestURI();
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
|
|
||||||
if (!isPublicAuthEndpoint(requestURI, contextPath)) {
|
if (!isPublicAuthEndpoint(requestURI, contextPath)) {
|
||||||
// For API requests, return 401 JSON
|
// For API requests, return 401 JSON
|
||||||
String acceptHeader = request.getHeader("Accept");
|
String acceptHeader = request.getHeader("Accept");
|
||||||
|
|||||||
-18
@@ -241,24 +241,6 @@ public class UserAuthenticationFilter extends OncePerRequestFilter {
|
|||||||
filterChain.doFilter(request, response);
|
filterChain.doFilter(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isPublicAuthEndpoint(String requestURI, String contextPath) {
|
|
||||||
// Remove context path from URI to normalize path matching
|
|
||||||
String trimmedUri =
|
|
||||||
requestURI.startsWith(contextPath)
|
|
||||||
? requestURI.substring(contextPath.length())
|
|
||||||
: requestURI;
|
|
||||||
|
|
||||||
// Public auth endpoints that don't require authentication
|
|
||||||
return trimmedUri.startsWith("/login")
|
|
||||||
|| trimmedUri.startsWith("/auth/")
|
|
||||||
|| trimmedUri.startsWith("/oauth2")
|
|
||||||
|| trimmedUri.startsWith("/saml2")
|
|
||||||
|| trimmedUri.startsWith("/api/v1/auth/login")
|
|
||||||
|| trimmedUri.startsWith("/api/v1/auth/refresh")
|
|
||||||
|| trimmedUri.startsWith("/api/v1/auth/logout")
|
|
||||||
|| trimmedUri.startsWith("/api/v1/proprietary/ui-data/login");
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum UserLoginType {
|
private enum UserLoginType {
|
||||||
USERDETAILS("UserDetails"),
|
USERDETAILS("UserDetails"),
|
||||||
OAUTH2USER("OAuth2User"),
|
OAUTH2USER("OAuth2User"),
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export const devApiLink = "https://registry.scalar.com/@stirlingpdf/apis/stirling-pdf-processing-api/";
|
export const devApiLink = "/swagger-ui/index.html";
|
||||||
|
|||||||
Reference in New Issue
Block a user