Course Content
Joi.js Input Validation (Part 1)
Table Of Contents
Scope
- Understand how to approach input validation (useful for any input validation library)
- Learn how to create json validation schemas within Joi.js
What is Joi?
- Javascript input validation library
- Create JSON schemas that validate JSON payloads entering an API (or leaving a browser)
Why Leverage Joi?
- Very granular whitelisting functionality
- Define what you will accept from the user
- Everything else is denied by default
- In general, when user input is sent to the api, what types of input validation should we preform?
- HINT
- Think about the different types of coding errors
- There are two primary types
- 2 primary checks need to occur when untrusted input (user input) comes to the API
- If these checks aren't completed, the server might act in unintended ways
- Types of input validation checks
- "Syntactic" Checks (Checking the form of the input)
- Ex: Is the input a string with length
X
?
- Regular Express Denial Of Service (ReDoS) mitigation
- Usecase for Joi
- "Semantic" Checks (Logic Checks)
- Ex: Does the user have appropriate permissions to do action
X
?
- Not what Joi is intended for
Joi Advantages
- If you aren't leveraging Javascript/Node.js, look for these features in a framework
- Share JSON schema between frontend/backend
- Validated at entrypoint
- Much safer than validating through database library
Joi Advantages (CONT.)
- Celebrate
- A Joi validation middleware for Express.js
Joi Schemas
- Joi leverages schemas to define validations
- Within a schema, you define
types
and constraints
username: Joi.string().alphanum().min(3).max(30).required()
- Type Ex:
Joi.string()
Joi.string()
generates a schema object that matches a string data type
- Inherits from
Joi.any()
- Generates a schema object that matches any data type
- Constraint Ex:
.min(3)
- Each constraint returns a new schema object
- Method chaining is available
Joi Schemas (CONT.)
username: Joi.string().alphanum().min(3).max(30).required()
- Values (or keys in case of objects) are optional by default
Additional Joi Types
- Ex:
username: Joi.string().alphanum().min(3).max(30).required()
- Besides
string()
, what other types can we validate?
- Joi Types
Ex: Joi Bypass (Question)
- While viewing the following schema object (and payload) on the next slide, think about how it could be exploited/bypassed
- Further assumptions
- JSON payload is submitted to the API
- Joi doesn't throw a validation error
- The JSON is directly saved to the database
- Payload key/value pairs are directly mapped to database fields/values
- Try to figure out how the following schema could be exploited
Ex: Joi Schema/Payload
const Joi = require('joi');
const schema = Joi.object()
.keys({
// Requires a given string value
username: Joi.string()
.alphanum()
.min(3)
.max(30)
.required(),
// Define password complexity requirements through regex (consider more complex regex)
password: Joi.string()
.regex(/^[a-zA-Z0-9]{3,30}$/)
.required(),
// Force passwords to match
password_confirmation: Joi.any()
.equal(Joi.ref('password'))
.required(),
// Accept different Joi types. Optional, unconstrained string or number
access_token: [Joi.string(), Joi.number()],
// Required birthyear to be an int between range
birthyear: Joi.number()
.integer()
.min(1900)
.max(2013)
.required(),
// Validate email address from example.com (remember spoofing considerations)
email: Joi.string()
.email()
.regex(/example\.com$/),
marketing_opt_out: Joi.boolean(),
csrf_token: Joi.string()
.guid({
version: 'uuidv4',
})
.required(),
sex: Joi.string()
.equal(['M', 'F', 'MALE', 'FEMALE', 'DECLINE'])
.required(),
time: Joi.date()
.timestamp('javascript'),
roles: Joi.object()
.keys(),
})
// email must be accompanied by marketing_opt_out
.with('email', 'marketing_opt_out');
const result = Joi.validate({
username: 'Ronald',
password: 'McDonald',
password_confirmation: 'McDonald',
birthyear: 2010,
email: '[email protected]',
marketing_opt_out: true,
csrf_token: '6d4d8c14-ef12-45d9-ab3c-5dddf941fb76',
sex: 'F',
time: 1534942475121,
roles: {},
}, schema);
// If result.error === null, payload is valid
console.log(`The validation error is: ${result.error}`);
Ex: Joi Schema/Payload (Result)
The validation error is: null
Complete and Continue
0 comments