CSRF Protection


As of Mango 2.7.x CSRF protection has been added. This requires that a special header with a unique token be passed into Mango on all REST API POST, PUT, and DELETE operations.


Getting the Token


You must access a GET endpoint to collect the XSRF-TOKEN cookie prior to making any POST,PUT,DELETE calls to Mango. Generally this is done via the GET login endpoint. The token will be returned in the Set-Cookie header. This token is only valid for one session and is discarded if the session times out or the user logs out.


Using the Token


The token should be submitted as an X-XSRF-TOKEN header for all reqeusts that can modify data in Mango, and the Cookie from the login should be submitted in the Cookie header.


Example Login Logic


Logic to login the admin/admin user.


  1. GET /login/admin with the header password=admin
  2. In the response extract the cookie XSRF-TOKEN and store the value
  3. All future requests should contain the token value assigned to the X-XSRF-TOKEN header.
  4. All future requests should contain the cookie value assigned to the Cookie header.

 JQuery Example Code  

/* Setup Global XHR  */
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') {
            if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
                // Only send the token to relative URLs i.e. locally.
                xhr.setRequestHeader("X-XSRF-TOKEN", getCookie('XSRF-TOKEN'));
                xhr.setRequestHeader("Cookie", document.cookie);
            }
        }
    }
});
/**
 * @function getCookie 
 *
 * @param {string} name - Name of Cookie to retrieve
 * @returns {string} - Value of Cookie
 */
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

   

Swagger Java Client Example Code


Login Logic:

 

ResponseEntityUserModel user = api.login(node.getAttribute("username").getString(), password, false);

if (client.getCookie().equals("")) {
    String cookie = user.getHeaders().getCookie().split(";")[0].replaceAll("\\[", "");
    client.setCookie(cookie);
    LOGGER.info("Setting Cookie: " + cookie);
}
            
for(String cookie : client.getResponseHeaders().get("Set-Cookie")){
    LOGGER.info("Got cookie: " + cookie);
    if(cookie.contains("XSRF-TOKEN")){
        String xsrfCookie = cookie.split(";")[0].replaceAll("\\[", "");
        String token = xsrfCookie.split("=")[1];
        LOGGER.info("Setting XSRF Token: " + token);
        client.addDefaultHeader("X-XSRF-TOKEN", token);
    }
}
LOGGER.info("{} logged in", node.getAttribute("username"));

 

Login Method:

 

/**
     * login
     * login
     * @param username username
     * @param password password
     * @param logout logout
     * @return ResponseEntityUserModel
     */
    public ResponseEntityUserModel login (String username, String password, Boolean logout) 
throws ApiException {
        Object postBody = null;
        byte[] postBinaryBody = null;
         // verify the required parameter 'username' is set
         if (username == null) {
              throw new ApiException(400,
 "Missing the required parameter 'username' when calling login");
         }
        // create path and map variables
        String path = API_VERSION + "/login/{username}".replaceAll("\\{" + "username" + "\\}", 
apiClient.escapeString(username.toString()));
        // query params
        List<Pair> queryParams = new ArrayList<Pair>();
        Map<String, String> headerParams = new HashMap<String, String>();
        Map<String, Object> formParams = new HashMap<String, Object>();
        if (password != null)
            headerParams.put("password", apiClient.parameterToString(password));
        if (logout != null)
            headerParams.put("logout", apiClient.parameterToString(logout));
        final String[] accepts = { "application/json" };
        final String accept = apiClient.selectHeaderAccept(accepts);
        final String[] contentTypes = { "application/json" };
        final String contentType = apiClient.selectHeaderContentType(contentTypes);
        String[] authNames = new String[] { };
        TypeRef returnType = new TypeRef<ResponseEntityUserModel>() { };
        return apiClient.invokeAPI(path, "GET", queryParams, postBody, postBinaryBody,
 	headerParams, formParams, accept, contentType, authNames, returnType);
    }