Class CsrfPreventionRequestCycleListener

  • All Implemented Interfaces:
    IRequestCycleListener

    public class CsrfPreventionRequestCycleListener
    extends Object
    implements IRequestCycleListener
    Prevents CSRF attacks on Wicket components by checking the Origin and Referer HTTP headers for cross domain requests. By default only checks requests that try to perform an action on a component, such as a form submit, or link click.

    Installation

    You can enable this CSRF prevention filter by adding it to the request cycle listeners in your application's init method:

     @Override
     protected void init()
     {
            // ...
            getRequestCycleListeners().add(new CsrfPreventionRequestCycleListener());
            // ...
     }
     

    Configuration

    When the Origin or Referer HTTP header is present but doesn't match the requested URL this listener will by default throw a HTTP error ( 400 BAD REQUEST) and abort the request. You can configure this specific action.

    A missing Origin and Referer HTTP header is handled as if it were a bad request and rejected. You can configure the specific action to a different value, suppressing or allowing the request when the HTTP headers are missing.

    When the Origin HTTP header is present and has the value null it is considered to be from a "privacy-sensitive" context and will trigger the no origin action. You can customize what happens in those actions by overriding the respective onXXXX methods.

    When you want to accept certain cross domain request from a range of hosts, you can whitelist those domains.

    You can enable or disable this listener by overriding isEnabled().

    You can customize whether a particular page should be checked for CSRF requests. For example you can skip checking pages that have a @NoCsrfCheck annotation, or only those pages that extend your base secure page class. For example:

     @Override
     protected boolean isChecked(IRequestablePage requestedPage)
     {
            return requestedPage instanceof SecurePage;
     }
     

    You can also tweak the request handlers that are checked. The CSRF prevention request cycle listener checks only action handlers, not render handlers. Override isChecked(IRequestHandler) to customize this behavior.

    You can customize the default actions that are performed by overriding the event handlers for them:

    • Constructor Detail

      • CsrfPreventionRequestCycleListener

        public CsrfPreventionRequestCycleListener()
    • Method Detail

      • setErrorCode

        public CsrfPreventionRequestCycleListener setErrorCode​(int errorCode)
        Modifies the HTTP error code in the exception when a conflicting Origin header is detected.
        Parameters:
        errorCode - the alternate HTTP error code, default 400 BAD REQUEST
        Returns:
        this
      • setErrorMessage

        public CsrfPreventionRequestCycleListener setErrorMessage​(String errorMessage)
        Modifies the HTTP message in the exception when a conflicting Origin header is detected.
        Parameters:
        errorMessage - the alternate message
        Returns:
        this
      • addAcceptedOrigin

        public CsrfPreventionRequestCycleListener addAcceptedOrigin​(String acceptedOrigin)
        Adds an origin (host name/domain name) to the white list. An origin is in the form of <domainname>.<TLD>, and can contain a subdomain. Every Origin header that matches a domain from the whitelist is accepted and not checked any further for CSRF issues. E.g. when example.com is in the white list, this allows requests from (i.e. with an Origin: header containing) example.com and blabla.example.com but rejects requests from blablaexample.com and example2.com.
        Parameters:
        acceptedOrigin - the acceptable origin
        Returns:
        this
      • isEnabled

        protected boolean isEnabled()
        Dynamic override for enabling/disabling the CSRF detection. Might be handy for specific tenants in a multi-tenant application. When false, the CSRF detection is not performed for the running request. Default true
        Returns:
        true when the CSRF checks need to be performed.
      • isChecked

        protected boolean isChecked​(IRequestablePage targetedPage)
        Override to limit whether the request to the specific page should be checked for a possible CSRF attack.
        Parameters:
        targetedPage - the page that is the target for the action
        Returns:
        true when the request to the page should be checked for CSRF issues.
      • isChecked

        protected boolean isChecked​(org.apache.wicket.request.IRequestHandler handler)
        Override to change the request handler types that are checked. Currently only action handlers (form submits, link clicks, AJAX events) are checked for a matching Origin HTTP header.
        Parameters:
        handler - the handler that is currently processing
        Returns:
        true when the Origin HTTP header should be checked for this handler
      • unwrap

        protected org.apache.wicket.request.IRequestHandler unwrap​(org.apache.wicket.request.IRequestHandler handler)
        Unwraps the handler if it is a IRequestHandlerDelegate down to the deepest nested handler.
        Parameters:
        handler - The handler to unwrap
        Returns:
        the deepest handler that does not implement IRequestHandlerDelegate
      • getSourceUri

        protected String getSourceUri​(javax.servlet.http.HttpServletRequest containerRequest)
        Resolves the source URI from the request headers (Origin or Referer).
        Parameters:
        containerRequest - the current container request
        Returns:
        the normalized source URI.
      • checkRequest

        protected void checkRequest​(javax.servlet.http.HttpServletRequest request,
                                    String sourceUri,
                                    IRequestablePage page)
        Performs the check of the Origin or Referer header that is targeted at the page.
        Parameters:
        request - the current container request
        sourceUri - the source URI
        page - the page that is the target of the request
      • isWhitelistedHost

        protected boolean isWhitelistedHost​(String sourceUri)
        Checks whether the domain part of the sourceUri (Origin or Referer header) is whitelisted.
        Parameters:
        sourceUri - the contents of the Origin or Referer HTTP header
        Returns:
        true when the source domain was whitelisted
      • isLocalOrigin

        protected boolean isLocalOrigin​(javax.servlet.http.HttpServletRequest containerRequest,
                                        String originHeader)
        Checks whether the Origin HTTP header of the request matches where the request came from.
        Parameters:
        containerRequest - the current container request
        originHeader - the contents of the Origin HTTP header
        Returns:
        true when the origin of the request matches the Origin HTTP header
      • normalizeUri

        protected final String normalizeUri​(String uri)
        Creates a RFC-6454 comparable URI from the uri string.
        Parameters:
        uri - the contents of the Origin or Referer HTTP header
        Returns:
        only the scheme://host[:port] part, or null when the URI string is not compliant
      • getTargetUriFromRequest

        protected final String getTargetUriFromRequest​(javax.servlet.http.HttpServletRequest request)
        Creates a RFC-6454 comparable URI from the request requested resource.
        Parameters:
        request - the incoming request
        Returns:
        only the scheme://host[:port] part, or null when the origin string is not compliant
      • whitelistedHandler

        protected void whitelistedHandler​(javax.servlet.http.HttpServletRequest request,
                                          String origin,
                                          IRequestablePage page)
        Handles the case where an origin is in the whitelist. Default action is to allow the whitelisted origin.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header
        page - the page that is targeted with this request
      • onWhitelisted

        protected void onWhitelisted​(javax.servlet.http.HttpServletRequest request,
                                     String origin,
                                     IRequestablePage page)
        Called when the origin was available in the whitelist. Override this method to implement your own custom action.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header
        page - the page that is targeted with this request
      • matchingOrigin

        protected void matchingOrigin​(javax.servlet.http.HttpServletRequest request,
                                      String origin,
                                      IRequestablePage page)
        Handles the case where an origin was checked and matched the request origin. Default action is to allow the whitelisted origin.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header
        page - the page that is targeted with this request
      • onMatchingOrigin

        protected void onMatchingOrigin​(javax.servlet.http.HttpServletRequest request,
                                        String origin,
                                        IRequestablePage page)
        Called when the origin HTTP header matched the request. Override this method to implement your own custom action.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header
        page - the page that is targeted with this request
      • allowHandler

        protected void allowHandler​(javax.servlet.http.HttpServletRequest request,
                                    String origin,
                                    IRequestablePage page)
        Handles the case where an Origin HTTP header was not present or did not match the request origin, and the corresponding action (noOriginAction or conflictingOriginAction) is set to ALLOW.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header, may be null or empty
        page - the page that is targeted with this request
      • onAllowed

        protected void onAllowed​(javax.servlet.http.HttpServletRequest request,
                                 String origin,
                                 IRequestablePage page)
        Override this method to customize the case where an Origin HTTP header was not present or did not match the request origin, and the corresponding action (noOriginAction or conflictingOriginAction) is set to ALLOW.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header, may be null or empty
        page - the page that is targeted with this request
      • suppressHandler

        protected void suppressHandler​(javax.servlet.http.HttpServletRequest request,
                                       String origin,
                                       IRequestablePage page)
        Handles the case where an Origin HTTP header was not present or did not match the request origin, and the corresponding action (noOriginAction or conflictingOriginAction) is set to SUPPRESS.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header, may be null or empty
        page - the page that is targeted with this request
      • onSuppressed

        protected void onSuppressed​(javax.servlet.http.HttpServletRequest request,
                                    String origin,
                                    IRequestablePage page)
        Override this method to customize the case where an Origin HTTP header was not present or did not match the request origin, and the corresponding action (noOriginAction or conflictingOriginAction) is set to SUPPRESSED.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header, may be null or empty
        page - the page that is targeted with this request
      • abortHandler

        protected void abortHandler​(javax.servlet.http.HttpServletRequest request,
                                    String origin,
                                    IRequestablePage page)
        Handles the case where an Origin HTTP header was not present or did not match the request origin, and the corresponding action (noOriginAction or conflictingOriginAction) is set to ABORT.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header, may be null or empty
        page - the page that is targeted with this request
      • onAborted

        protected void onAborted​(javax.servlet.http.HttpServletRequest request,
                                 String origin,
                                 IRequestablePage page)
        Override this method to customize the case where an Origin HTTP header was not present or did not match the request origin, and the corresponding action (noOriginAction or conflictingOriginAction) is set to ABORTED.
        Parameters:
        request - the request
        origin - the contents of the Origin HTTP header, may be null or empty
        page - the page that is targeted with this request