agentsclimarketplace

Rails token auth

Skill davidteren/hotwire-codex-skills/skills/rails-token-auth

Build secure DB-backed token session auth in Rails — one mechanism for web, Action Cable, and Hotwire Native, with Current attributes and secure-by-default controller concerns. Use when adding login/sessions to a Rails app, when web and native clients need to share authentication, when you need revocable server-side sessions (logout/kick a device) instead of stateless JWTs, or when auditing existing auth for user-enumeration, plaintext tokens, readable cookies, or opt-in-auth mistakes. Provides templates and a security audit.From its SKILL.md

Install
npx -y skills add davidteren/hotwire-codex-skills --skill rails-token-auth

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 1 command, including `scripts/audit_token_auth.sh path/to/rails-app`.

SKILL.md

3.5 KB, 724 tokens by cl100k_base, as published. Nobody here has run it

Rails token-backed session auth

A revocable, DB-backed session model (AppSession) that authenticates web and native clients with one mechanism — plus Current attributes and secure-by-default controller concerns. Built without a gem (plain has_secure_password + authenticate_by). Full design + rationale: references/token-auth-guide.md.

When to use

  • Adding login/logout to a Rails app and you want it done securely from the start.
  • Web + Hotwire Native (and Action Cable) need to share one auth.
  • You need revocable sessions (real logout, kick a device) — not stateless JWTs.
  • Auditing existing auth for the expensive mistakes.

The shape

FileRole
AppSession (app/models/app_session.rb)one row per login; token stored as a digest (has_secure_password :token)
User::Authentication (app/models/user/authentication.rb)has_secure_password; authenticate_by login; mint/verify sessions
Current (app/models/current.rb)request-scoped user / app_session / organization
Authenticate (app/controllers/concerns/authenticate.rb)secure-by-default before_action; skip_authentication / allow_unauthenticated; log_in/log_out
SessionsControllercreate_app_sessionlog_in; destroylog_out

Copy the templates from templates/ (they're generic, ready to adapt). Add the migration (app_sessions: user ref + token_digest), the routes (login/logout), and include User::Authentication + include Authenticate in ApplicationController.

The non-negotiables (why this design)

  • authenticate_by, not find_by(email:)&.authenticate — timing-safe, no account enumeration.
  • Token hashed at rest (has_secure_password :token) — plaintext token lives only in the encrypted cookie. A DB leak yields no usable sessions.
  • cookies.encrypted for the session payload — confidential + tamper-proof.
  • Secure-by-default: global before_action :authenticate; public actions opt out explicitly. A forgotten controller stays locked.
  • Real logout destroys the AppSession row — server-side revocation.

Audit an app

scripts/audit_token_auth.sh path/to/rails-app

Checks all six properties above and flags: find_by(email:)+authenticate (enumeration), plaintext token storage, token/session in a plain cookie, opt-in auth (no global before_action), cookie-only logout, missing has_secure_password / password length. Heuristic grep scan — it names its ceiling; a clean run is not a formal proof, so still review custom logic. Verified: passes the secure Piazza app, flags a synthetic insecure one on every check.

Testing the concerns

The Authenticate concern is tested in isolation with a TestController + draw_test_routes harness. That harness has a Rails 8 LazyRouteSet flake — use the fixed helper and the detector from the rails-8-upgrade skill.

What ships with it: 7 files

14.8 KB alongside SKILL.md, 1 of them executable

references/

scripts/

Gives 0 of the 12 instructions most security skills give in 724 tokens

Counted across 666 of the 889 authors here whose files we hold, read 2026-09-06

  • Use parameterized queries for database accessin 82 of 666, across 79 files
  • Hash passwords with BCryptin 55 of 666, across 39 files
  • Implement rate limiting for public endpointsin 48 of 666, across 34 files
  • Use environment variables for secretsin 35 of 666
  • Scan dependencies for vulnerabilitiesin 35 of 666, across 24 files
  • Validate and sanitize all user inputin 35 of 666, across 32 files
  • Add security headers to all responsesin 34 of 666, across 20 files
  • Validate all external input at the system boundaryin 26 of 666, across 25 files
  • Use parameterized queries to prevent SQL injectionin 25 of 666, across 13 files
  • Store secrets in Vault or environment variablesin 25 of 666, across 10 files
  • Run containers as a non-root userin 21 of 666, across 18 files
  • Validate all input using Bean Validationin 19 of 666, across 5 files

Said here and by no other author read

  • use authenticate_by for timing-safe authentication
  • store token digests in the database
  • implement global before_action for authentication
  • require explicit opt-out for public controller actions
  • destroy session records on logout
  • copy templates from the provided directory

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.