Class ClientRedirectValidation.ClientRedirectValidationAspect

java.lang.Object
com.broadleafcommerce.auth.server.service.ClientRedirectValidation.ClientRedirectValidationAspect
Enclosing class:
ClientRedirectValidation

public static class ClientRedirectValidation.ClientRedirectValidationAspect extends Object
Aspect for validating and sanitizing redirection targets across the authentication system.

This provides a centralized and surgical way to enforce our comprehensive security policy for redirects without modifying core framework components.

  • Constructor Summary

    Constructors
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    aroundCommence(org.aspectj.lang.ProceedingJoinPoint joinPoint)
    Intercepts the authentication entry point to close an "Early Exit" vulnerability during silent authentication.
    void
    aroundSendRedirect(org.aspectj.lang.ProceedingJoinPoint joinPoint)
    Intercepts the system's final redirect strategy to enforce the security policy before any redirect is sent to the browser.
    void
    aroundValidate(org.aspectj.lang.ProceedingJoinPoint joinPoint)
    Intercepts the authorization code request validator to prevent "Error Leakage" and enforce Broadleaf-specific whitelists.
    protected String
    findClientId(org.aspectj.lang.JoinPoint joinPoint)
    Attempts to find a client ID within the arguments of the intercepted join point.
    protected Optional<org.springframework.ui.Model>
    findModel(Object[] args)
    Finds a Model argument within the provided list of arguments.
    protected String
    getClientId(jakarta.servlet.http.HttpServletRequest request, OAuth2ClientIdForwardRedirectStrategy strategy)
    Resolves the client ID from the request or the redirect strategy's context.
    protected boolean
    Heuristic check to determine if a string value is likely a client ID.
    protected void
    sanitizeModel(Map<String,Object> model, String clientId)
    Sanitizes the provided model map by validating any specified redirection target.
    protected void
    simulateSuperCommence(org.aspectj.lang.JoinPoint joinPoint, jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, org.springframework.security.core.AuthenticationException authException)
    Simulates the superclass behavior of the authentication entry point by redirecting to the login page.
    void
    validateControllerRedirects(org.aspectj.lang.JoinPoint joinPoint, Object result)
    Intercepts authentication controllers to sanitize the returnTo model attribute.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

  • Method Details

    • aroundCommence

      public void aroundCommence(org.aspectj.lang.ProceedingJoinPoint joinPoint) throws Throwable
      Intercepts the authentication entry point to close an "Early Exit" vulnerability during silent authentication.

      Why this is special: When a user is not authenticated and hits the authorize endpoint with prompt=none, the framework's commence method extracts the redirect_uri and immediately performs a 302 redirect back to it with a login_required error. This redirection happens before any protocol-level OAuth2 validation or handshake occurs. Without this aspect, an attacker can use this "early exit" path to trigger an Open Redirect to an arbitrary domain simply by failing to be logged in.

      This advice ensures that even these pre-protocol redirects are strictly whitelisted. If validation fails, it forces a safe fallback to the login page instead of the malicious target.

      Parameters:
      joinPoint - The proceeding join point for the commence method.
      Throws:
      Throwable - If an error occurs during interception or execution.
    • aroundValidate

      public void aroundValidate(org.aspectj.lang.ProceedingJoinPoint joinPoint) throws Throwable
      Intercepts the authorization code request validator to prevent "Error Leakage" and enforce Broadleaf-specific whitelists.

      Why this is special: While Spring Security has a built-in validator, it only knows about standard OAuth2 callback URIs. Our implementation expands this protection in three ways:

      1. Broadleaf Whitelists: We validate against "Post Authentication Success" and "Post Logout" lists, which often contain targets that are trusted within Broadleaf but absent from the standard protocol callback list.
      2. Preventing Error Redirection: If an authorization request is invalid (e.g. multiple parameter errors), the framework might attempt to redirect the error response to the redirect_uri. By intercepting early and throwing an exception with a null redirect URI, we force a safe 400 Bad Request (no redirect possible) before the framework can commit to a target.
      3. Security Auditing: This is a critical point for emitting [SECURITY EVENT] logs, which are not provided by the default handshake.

      Parameters:
      joinPoint - The proceeding join point for the accept method.
      Throws:
      Throwable - If validation fails or an error occurs.
    • validateControllerRedirects

      public void validateControllerRedirects(org.aspectj.lang.JoinPoint joinPoint, Object result)
      Intercepts authentication controllers to sanitize the returnTo model attribute.

      This ensures that any redirection target specified in the model is validated against the client's security policy before being rendered into the view.

      Parameters:
      joinPoint - The join point of the controller method.
      result - The result returned by the controller method.
    • aroundSendRedirect

      public void aroundSendRedirect(org.aspectj.lang.ProceedingJoinPoint joinPoint) throws Throwable
      Intercepts the system's final redirect strategy to enforce the security policy before any redirect is sent to the browser.

      This provides the final line of defense against Open Redirect attacks by validating the target URL immediately before the redirection response is committed.

      Parameters:
      joinPoint - The proceeding join point for the sendRedirect method.
      Throws:
      Throwable - If an error occurs during interception or execution.
    • simulateSuperCommence

      protected void simulateSuperCommence(org.aspectj.lang.JoinPoint joinPoint, jakarta.servlet.http.HttpServletRequest request, jakarta.servlet.http.HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws Exception
      Simulates the superclass behavior of the authentication entry point by redirecting to the login page.

      This uses reflection to access protected framework methods and fields to ensure the redirection is performed correctly and consistently with the framework's baseline behavior.

      Parameters:
      joinPoint - The join point of the intercepted method.
      request - The current HTTP request.
      response - The current HTTP response.
      authException - The authentication exception that triggered the entry point.
      Throws:
      Exception - If an error occurs during reflection or redirection.
    • getClientId

      protected String getClientId(jakarta.servlet.http.HttpServletRequest request, OAuth2ClientIdForwardRedirectStrategy strategy)
      Resolves the client ID from the request or the redirect strategy's context.
      Parameters:
      request - The current HTTP request.
      strategy - The redirect strategy instance.
      Returns:
      The resolved client ID, or null if it cannot be determined.
    • sanitizeModel

      protected void sanitizeModel(Map<String,Object> model, String clientId)
      Sanitizes the provided model map by validating any specified redirection target.
      Parameters:
      model - The model map to sanitize.
      clientId - The ID of the client to validate against.
    • findClientId

      protected String findClientId(org.aspectj.lang.JoinPoint joinPoint)
      Attempts to find a client ID within the arguments of the intercepted join point.
      Parameters:
      joinPoint - The join point to inspect.
      Returns:
      The resolved client ID, or null if not found.
    • isLikelyClientId

      protected boolean isLikelyClientId(String val)
      Heuristic check to determine if a string value is likely a client ID.
      Parameters:
      val - The string value to check.
      Returns:
      true if likely a client ID, false otherwise.
    • findModel

      protected Optional<org.springframework.ui.Model> findModel(Object[] args)
      Finds a Model argument within the provided list of arguments.
      Parameters:
      args - The arguments to search.
      Returns:
      An Optional containing the found model, or empty if not found.