roc-lang / roc-lang/basic-webserver

Add session-backed CSRF token generation and verification helpers

Open
#204 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
HTML
Stars
107
Forks
20
Avg merge
1d 17h
Merged PRs (30d)
11

Description

Summary

Add a focused Csrf module implementing the synchronizer-token building blocks needed by HTML forms and browser APIs.

Illustrative API:

token = Csrf.generate!()       # persist in the server-side session
form_value = token.to_str()

match Csrf.verify({
    expected: Csrf.from_stored(session.csrf_token)?,
    presented: submitted_value,
}) {
    Valid => handle_state_change()
    Invalid(reason) => forbidden(reason)
}

Dependencies

  • #198 for OS-backed cryptographic random bytes
  • #203 for the intended server-side session integration
  • #199 for the surrounding session-cookie flow

Why this should not be generic middleware

CSRF enforcement depends on route semantics, authentication, and where the application obtains the submitted token. A form handler may need to parse a bounded URL-encoded or multipart body before verification, while a JSON endpoint normally reads a header.

Automatically consuming request bodies or guessing which methods and routes are safe would conflict with the explicit request-body and routing model. The platform should instead provide a difficult-to-misuse token type and verification function.

OWASP recommends server-generated, secret, unpredictable synchronizer tokens that are compared with session state. It also warns against placing synchronizer tokens in cookies, URLs, or logs.

Required contract

  • Generate tokens from at least 32 bytes returned by Random.bytes!.
  • Use a fixed cookie/form-safe representation with strict parsing.
  • Make the token nominal and redact its normal inspection.
  • Verify token values with a constant-time comparison after validating their fixed length and encoding.
  • Distinguish missing, malformed, and mismatched tokens.
  • Provide a helper for extracting exactly one configured request header without consuming the body.
  • Form handlers parse their own bounded body and pass the presented value explicitly.
  • Document that the application stores the expected token in its server-side session.
  • Rotate the token on session creation, authentication, and session-identifier rotation.
  • Never emit token values in error messages, access logs, or metrics.
  • Provide an end-to-end form example using the SQLite session facility.

Non-goals

  • Automatic protection of all POST requests
  • Guessing safe routes or methods
  • Consuming form or multipart bodies behind the application
  • CORS policy
  • A naive double-submit cookie design
  • Stateless signed tokens or general HMAC APIs
  • Origin/Referer validation based on untrusted forwarded headers

Acceptance criteria

  • Applications can generate, persist, render, and verify synchronizer tokens.
  • Verification uses fixed-format parsing and constant-time comparison.
  • Missing, malformed, and mismatched values are distinguishable without leaking secrets.
  • Header extraction never consumes the request body.
  • A real-listener example demonstrates session cookie plus protected form submission.

References

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the linked dependency issues #198, #203, and #199, then trace the SQLite session facility and its real-listener example. Done means applications can generate, store, render, and verify fixed-format synchronizer tokens, distinguish failure cases without leaks, extract a header without consuming the body, and demonstrate a protected form submission.

Written by the indexing model from the issue text.

Assessment

Tech stack
sqlite
Domain
backend-api-design, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.