Security

PIN Security

Storage

Cashier PINs are never stored in plain text. The system uses:

  • SHA-256 hashing with a per-cashier salt

  • 32-byte random salt generated for each cashier (64 hex characters)

  • Timing-safe comparison to prevent timing attacks during verification

Stored: SHA-256(pin + ":" + salt)

Even if the database were compromised, PINs cannot be recovered from the hashes.

PIN Rules

Rule
Detail

Minimum length

8 digits

Allowed characters

Digits only (0-9)

Uniqueness

Each cashier must have a unique PIN

Reset

Only the merchant can reset a PIN

Retrieval

Not possible -- PINs are one-way hashed

Why Unique PINs?

The system identifies cashiers by their PIN during login. When a cashier enters their PIN, the system searches all allowed cashiers for a match. If two cashiers shared the same PIN, the system couldn't tell them apart.

Session Security

Token Generation

  • 32 bytes of cryptographically random data (crypto.getRandomValues())

  • Stored as a 64-character hex string

  • Only the hash of the token is stored in the database

Token Storage

  • Primary: httpOnly secure cookie (cannot be accessed by JavaScript)

  • Backup: localStorage (for session recovery if cookie is lost)

Session Expiration

  • Sessions last 15 minutes from last activity

  • Activity (creating payments, navigating) resets the timer

  • Expired sessions are automatically cleaned up by a background job

Session Termination

Sessions are ended when:

  • The 15-minute inactivity timer expires

  • The cashier manually logs out

  • The merchant resets the cashier's PIN

  • The merchant deactivates the cashier

  • The merchant deactivates the terminal

Terminal Access Control

Public vs Private Information

Information
Accessible By

Terminal name, code

Anyone with the terminal URL (needed for login page)

Terminal settings, allowed cashiers

Merchant only (requires dashboard authentication)

Cashier names (for login display)

Anyone at the terminal URL

Cashier PINs

Nobody (hashed)

Payment history

Merchant only

Terminal URL Security

  • Terminal URLs contain a system-generated ID (term_<random>), not the short code

  • Terminal IDs are not easily guessable

  • Knowing the URL only gives access to the login screen, not to any payment functions

  • A valid PIN is still required to create payments

Payment Security

  • Every payment requires a valid, non-expired session

  • Payments are attributed to the authenticated merchant (terminal owner)

  • Order IDs create an audit trail linking payments to terminals and cashiers

  • Chain, token, and amount are validated server-side before payment creation

Last updated