Class DSpaceCsrfTokenRepository

  • All Implemented Interfaces:
    org.springframework.security.web.csrf.CsrfTokenRepository

    public class DSpaceCsrfTokenRepository
    extends Object
    implements org.springframework.security.web.csrf.CsrfTokenRepository
    This is a custom Spring Security CsrfTokenRepository which supports *cross-domain* CSRF protection (allowing the client and backend to be on different domains). It's inspired by https://stackoverflow.com/a/33175322

    This also borrows heavily from Spring Security's CookieCsrfTokenRepository: https://github.com/spring-projects/spring-security/blob/5.2.x/web/src/main/java/org/springframework/security/web/csrf/CookieCsrfTokenRepository.java How it works: 1. Backend generates XSRF token & stores in a *server-side* cookie named DSPACE-XSRF-COOKIE. By default, this cookie is not readable to JS clients (HttpOnly=true). But, it is returned (by user's browser) on every subsequent request to backend. See "saveToken()" method below. 2. At the same time, backend also sends the generated XSRF token in a header named DSPACE-XSRF-TOKEN to client. See "saveToken()" method below. 3. Client MUST look for DSPACE-XSRF-TOKEN header in a response from backend. If found, the client MUST store/save this token for later request(s). For Angular UI, this task is performed by the XsrfInterceptor. 4. Whenever the client is making a mutating request (e.g. POST, PUT, DELETE, etc), the XSRF token is REQUIRED to be sent back in the X-XSRF-TOKEN header. * NOTE: non-mutating requests (e.g. GET, HEAD) do not check for an XSRF token. This is default behavior in Spring Security 5. On backend, the X-XSRF-TOKEN header is received & compared to the current value of the *server-side* cookie named DSPACE-XSRF-COOKIE. If tokens match, the request is accepted. If tokens don't match a 403 is returned. This is done automatically by Spring Security. In summary, the XSRF token is ALWAYS sent to/from the client & backend via *headers*. This is what allows the client and backend to be on different domains. The server-side cookie named DSPACE-XSRF-COOKIE is (usually) not accessible to the client. It only exists to allow the server-side to remember the currently active XSRF token, so that it can validate the token sent (by the client) in the X-XSRF-TOKEN header.

    • Constructor Detail

      • DSpaceCsrfTokenRepository

        public DSpaceCsrfTokenRepository()
    • Method Detail

      • generateToken

        public org.springframework.security.web.csrf.CsrfToken generateToken​(javax.servlet.http.HttpServletRequest request)
        Specified by:
        generateToken in interface org.springframework.security.web.csrf.CsrfTokenRepository
      • saveToken

        public void saveToken​(org.springframework.security.web.csrf.CsrfToken token,
                              javax.servlet.http.HttpServletRequest request,
                              javax.servlet.http.HttpServletResponse response)
        This method has been modified for DSpace.

        It now uses ResponseCookie to build the cookie, so that the "SameSite" attribute can be applied.

        It also sends the token (if not empty) in both the cookie and the custom "DSPACE-XSRF-TOKEN" header

        Specified by:
        saveToken in interface org.springframework.security.web.csrf.CsrfTokenRepository
        Parameters:
        token - current token
        request - current request
        response - current response
      • loadToken

        public org.springframework.security.web.csrf.CsrfToken loadToken​(javax.servlet.http.HttpServletRequest request)
        Specified by:
        loadToken in interface org.springframework.security.web.csrf.CsrfTokenRepository
      • setParameterName

        public void setParameterName​(String parameterName)
        Sets the name of the HTTP request parameter that should be used to provide a token.
        Parameters:
        parameterName - the name of the HTTP request parameter that should be used to provide a token
      • setHeaderName

        public void setHeaderName​(String headerName)
        Sets the name of the HTTP header that should be used to provide the token.
        Parameters:
        headerName - the name of the HTTP header that should be used to provide the token
      • setCookieName

        public void setCookieName​(String cookieName)
        Sets the name of the cookie that the expected CSRF token is saved to and read from.
        Parameters:
        cookieName - the name of the cookie that the expected CSRF token is saved to and read from
      • setCookieHttpOnly

        public void setCookieHttpOnly​(boolean cookieHttpOnly)
        Sets the HttpOnly attribute on the cookie containing the CSRF token. Defaults to true.
        Parameters:
        cookieHttpOnly - true sets the HttpOnly attribute, false does not set it
      • setCookiePath

        public void setCookiePath​(String path)
        Set the path that the Cookie will be created with. This will override the default functionality which uses the request context as the path.
        Parameters:
        path - the path to use
      • getCookiePath

        public String getCookiePath()
        Get the path that the CSRF cookie will be set to.
        Returns:
        the path to be used.
      • setCookieDomain

        public void setCookieDomain​(String cookieDomain)
        Sets the domain of the cookie that the expected CSRF token is saved to and read from.
        Parameters:
        cookieDomain - the domain of the cookie that the expected CSRF token is saved to and read from
        Since:
        5.2