The summary.
AUTHENTICATION WITHOUT AUTHORISATION IS THE COMMONEST SERIOUS FAULT
A role says what kind of action is permitted; ownership says on which record. Both are required, checked at the point of access.
Test every endpoint with a user who should not have access.
PARAMETERISE EVERY QUERY, AND NEVER BUILD A COMMAND FROM JOINED STRINGS
Match table and column names against a fixed list, since those cannot be parameterised.
VERIFY TOKEN SIGNATURES, AND NEVER LET A TOKEN SPECIFY ITS OWN VERIFICATION METHOD
Keep lifetimes short, since a stolen token is usable until it expires. Never put anything sensitive inside one — the contents are readable.
REGENERATE THE SESSION IDENTIFIER ON SIGN-IN, AND DESTROY IT SERVER-SIDE ON SIGN-OUT
In-process sessions break behind a load balancer, and the symptom is users signed out apparently at random.
FOR UPLOADS, DISCARD THE SUPPLIED FILENAME AND CHECK TYPE BY CONTENT
Store files outside the served directory, so one can never be executed.
VERIFY WEBHOOK SIGNATURES
An unverified endpoint accepts anything from anyone.
RATE-LIMIT AUTHENTICATION MORE STRICTLY THAN EVERYTHING ELSE
And collect less data — what you do not hold cannot be exposed.