validation.js

ABOUT

This module is concerned with the server-side validation of user input from as many sources as possible. Validation of user-supplied input should be completed at every step including prior to server-side processing as well as post-server processing (such as before storage in a database). This module fulfills the following obligations:

  1. Browser checks
  2. Validate connection source (https?)
  3. Header checks => origin, host, referrer
  4. javascript, html, css sanitization
    • input encoding
    • output encoding
  5. form inputs
  6. sessions (id, cookies)
  7. authentication
  8. authorization
  9. pristine data prior to storage in database

REQUIREMENTS & ASSUMPTIONS

require('../security.json')
let validate = require('validate.js')
let sanitizeHtml = require('sanitize-html')
var whitelists = require('./.whitelists.json')
const tls = require('tls')
  • The ’.whitelists.json’ file is created by _spartan. It is a JSON object which contains all of the “things” you wish to validate. It looks something like this:
{
    "origin": ["'https://localhost:8080'"],
    "host": ["'localhost:8080'"],
    "referers": [ "'http://localhost:3000'", 
                    "'https://localhost:8080/'", 
                    "'https://localhost:8080/login'",
                    "'http://localhost:3000/login'",
                    "'https://localhost:8080/register'",
                    "'http://localhost:3000/register'",
                    "'https://localhost:8080/thanks'",
                    "'http://localhost:3000/thanks'",
                    "'https://localhost:8080/profile'",
                    "'http://localhost:3000/profile'"
                ],
    "csp": "'secJson.securityHeaders.config.csp'"
}

You can add as many keys/properties and values as you wish to validate.

_spartan makes a one-time copy of the whitelist Array from security.json to .whitelist.json origin property. If you choose to make updates to the origin after the policy has been generated, you should add to this file instead of the policy whitelist.

AVAILABLE METHODS

Module Instantiation

method name description params returns
N/A exposes validated, contentValidation and uploadCheck methods N/A Error

USAGE

// in app.js
let validation = security.validation

Validate From Whitelists

method name description params returns
validated validates a param based upon type what to validate (header, authentication, authorization, form input, etc) String validator function or Error

USAGE

let formChecker = validation.validated('form') // returns a function which accepts a form to check
app.post('/route', (request, response, next) => {
  let uData = {}
  uData.email = request.body.email
  uData.firstName = request.body.firstName
  uData.lastName = request.body.lastName
  uData.password = request.body.password
  uData.confirm = request.body.confirm
  if (formChecker(uData) instanceof Error) {
    next(formChecker(uData))
  } else {
    ... // validation check passed, continue on with processing
  }
})

Available validators:

  • forms
  • request headers
  • authentication & authorization (if you’re using basic auth for instance)
  • session tokens
  • connection settings
  • file uploads

Available processors:

  • html encoding & sanitization
  • javascript encoding & sanitization

CSS sanitization is not available as part of the validation module; instead, you should utilize client-side CSS sanitization libraries (especially if you plan to use or reference third-party CSS files in your project)

Content Validation

method name description params returns
contentValidation checks to see if type and content of the provided data makes sense (obj* thing to check, rules* schema to match, callback function) passMessage String or Error

* see usage for examples on how to use these objects

To provide maximum flexibility, _spartan fully exposes the validatejs library which can be used both client-side and server side. Any input available in this library can be passed through _spartan to build both the constraints and the validator

USAGE

app.post('/route', (request, response, next) => {
  let obj = { // (example inputs)
  name : request.body.name,
  email : request.body.email
  password : request.body.password
  startDate : 1 Jan 1982,
  endDate : 5 Feb 1986
}
let rules = { // (example inputs)
  name : {
    required : true,
    minLen : 3,
    maxLen : 24
  }
  email : {
    email : true,
    minLen : 3,
    maxLen : 24
  },
  password: {
    format : // < matches password policy in security.json >,
    minLen : // < matches password policy in security.json >,
    maxLen : // < matches password policy in security.json >
  },
  startDate : {
    dateTime : { dateOnly : true },
  },
  endDate : {
    dateTime : { dateOnly : true },
    greaterThan : startDate _assuming startDate is converted to utc_
  }
} 
validation.contentValidation(obj, rules, (err) => {
  if (err) {
    next (err)
  } else {
    ... // do some stuff
    response.redirect('/thanks')
  }
})
})

ERRORS

  • (‘validation/disabled-by-policy’) => thrown if validation is disabled by policy. To change this, mark contentValidationPolicy.enabled : true in security.json and then run _spartan --force
  • (‘validation/invalid-type’) => thrown if either the supplied data object or the rules object are not objects
  • (‘validation/input-type-error’) => validation failure; thrown if a property in the data object doesn’t match the type specified in the same property of the rules object