RepoPilotOpen in app →

NoamB/sorcery

Magical authentication for Rails 3 & 4

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 27+ active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Stale — last commit 9y ago

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/noamb/sorcery)](https://repopilot.app/r/noamb/sorcery)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/noamb/sorcery on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: NoamB/sorcery

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/NoamB/sorcery shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 27+ active contributors
  • Distributed ownership (top contributor 42% of recent commits)
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 9y ago

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live NoamB/sorcery repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/NoamB/sorcery.

What it runs against: a local clone of NoamB/sorcery — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in NoamB/sorcery | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 3448 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>NoamB/sorcery</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of NoamB/sorcery. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/NoamB/sorcery.git
#   cd sorcery
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of NoamB/sorcery and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "NoamB/sorcery(\\.git)?\\b" \\
  && ok "origin remote is NoamB/sorcery" \\
  || miss "origin remote is not NoamB/sorcery (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lib/sorcery.rb" \\
  && ok "lib/sorcery.rb" \\
  || miss "missing critical file: lib/sorcery.rb"
test -f "lib/sorcery/model.rb" \\
  && ok "lib/sorcery/model.rb" \\
  || miss "missing critical file: lib/sorcery/model.rb"
test -f "lib/sorcery/controller.rb" \\
  && ok "lib/sorcery/controller.rb" \\
  || miss "missing critical file: lib/sorcery/controller.rb"
test -f "lib/sorcery/adapters/active_record_adapter.rb" \\
  && ok "lib/sorcery/adapters/active_record_adapter.rb" \\
  || miss "missing critical file: lib/sorcery/adapters/active_record_adapter.rb"
test -f "lib/generators/sorcery/install_generator.rb" \\
  && ok "lib/generators/sorcery/install_generator.rb" \\
  || miss "missing critical file: lib/generators/sorcery/install_generator.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 3448 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3418d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/NoamB/sorcery"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Sorcery is a Ruby gem that provides drop-in magical authentication for Rails 3 & 4 applications, handling user login, password reset, remember-me tokens, session management, and external OAuth integration via a modular plugin architecture. It abstracts authentication logic into reusable submodules (activity_logging, brute_force_protection, remember_me, session_timeout, http_basic_auth, external OAuth) that hook into both model and controller layers without requiring boilerplate. Modular plugin architecture split into two halves: lib/sorcery/model/ (User model mixins: authentication, external OAuth, password reset, user activation) and lib/sorcery/controller/ (controller concerns: session management, HTTP auth, activity logging). lib/sorcery/adapters/ abstracts ORM (Active Record), lib/sorcery/crypto_providers/ plugs in different hash algorithms. lib/generators/ handles Rails install scaffolding.

👥Who it's for

Rails developers (specifically Rails 3 & 4 era) who need to quickly implement secure authentication without rolling their own—particularly those building multi-tenant SaaS apps that need activity logging, brute force protection, or federated login via external providers.

🌱Maturity & risk

This repo appears mature but legacy: it supports Rails 3–4 with CI via Travis, multiple crypto providers (BCrypt, SHA variants, AES256), and comprehensive migrations. However, the README now redirects to Sorcery/sorcery (a newer fork), indicating this version (NoamB/sorcery) is no longer the canonical upstream—production use should consider migrating to the actively maintained fork.

High risk for new projects: Rails 3–4 reached EOL in 2015–2016, and this specific fork is no longer maintained (README points elsewhere). Dependency surface is moderate (Gemfile lists test deps for multiple Rails versions), but no recent commits visible in provided metadata. Security patches are unlikely; existing apps should migrate to the Sorcery/sorcery fork or modern alternatives like Devise.

Active areas of work

This repo appears dormant. The README explicitly states 'Sorcery has moved!' to Sorcery/sorcery, suggesting development ceased on this fork. No recent commits, PRs, or milestones are visible in the provided metadata.

🚀Get running

Clone and bundle: git clone https://github.com/NoamB/sorcery.git && cd sorcery && bundle install. Run specs: bundle exec rspec. Generate into a Rails 3/4 app: rails generate sorcery:install [options].

Daily commands: This is a gem library, not an app. Test it: bundle exec rspec (requires .rspec config and spec/ dir, not shown). Install into a Rails 3/4 app: rails generate sorcery:install core [oauth] [brute_force_protection] etc.

🗺️Map of the codebase

  • lib/sorcery.rb — Main entry point that loads all Sorcery modules and configures the gem; every contributor must understand the module loading order
  • lib/sorcery/model.rb — Core model-level authentication logic that includes and configures all user model submodules (activation, password reset, OAuth, etc.)
  • lib/sorcery/controller.rb — Core controller-level authentication logic that provides login/logout/session management for Rails controllers
  • lib/sorcery/adapters/active_record_adapter.rb — Adapter layer abstracting ORM differences; essential for understanding how Sorcery integrates with ActiveRecord
  • lib/generators/sorcery/install_generator.rb — Rails generator that scaffolds Sorcery setup including migrations, initializer, and model patches; contributors need to understand installation flow
  • lib/sorcery/model/config.rb — Centralized configuration for all model-level modules; defines which features (reset_password, user_activation, etc.) are enabled
  • lib/sorcery/controller/config.rb — Centralized configuration for all controller-level modules; defines session behavior, remember-me, external auth, etc.

🛠️How to make changes

Add Support for a New External OAuth Provider

  1. Create a new provider class inheriting from lib/sorcery/providers/base.rb and implement required methods (get_user_hash, auth_hash_schema, etc.) (lib/sorcery/providers/yourprovider.rb)
  2. Register the provider in the external submodule by adding it to the list of available providers (lib/sorcery/model/submodules/external.rb)
  3. Add provider-specific configuration options (client_id, client_secret, etc.) to the external submodule config (lib/sorcery/model/config.rb)
  4. Write provider integration tests in spec/active_record/user_oauth_spec.rb and spec/controllers/controller_oauth2_spec.rb

Add a New Model-Level Authentication Feature (Submodule)

  1. Create a new submodule in lib/sorcery/model/submodules/yourfeature.rb with a module that gets included into the User model (lib/sorcery/model/submodules/yourfeature.rb)
  2. Add configuration options for your feature in the model config initializer method (lib/sorcery/model/config.rb)
  3. Create a migration template for any required database columns (lib/generators/sorcery/templates/migration/yourfeature.rb)
  4. Hook your submodule into the main model.rb so it loads when sorcery is required (lib/sorcery/model.rb)
  5. Write model-level tests in spec/active_record/user_yourfeature_spec.rb

Add a New Controller-Level Authentication Feature (Submodule)

  1. Create a new submodule in lib/sorcery/controller/submodules/yourfeature.rb that provides controller helper methods (lib/sorcery/controller/submodules/yourfeature.rb)
  2. Add configuration options for your feature in the controller config initializer method (lib/sorcery/controller/config.rb)
  3. Hook your submodule into the main controller.rb so it's injected into ActionController::Base (lib/sorcery/controller.rb)
  4. Write controller tests in spec/controllers/controller_yourfeature_spec.rb using the Rails app in spec/rails_app/

Add Support for a New ORM (e.g., Mongoid)

  1. Create a new ORM adapter by subclassing lib/sorcery/adapters/base_adapter.rb and implement find_by_email, create, update, etc. (lib/sorc)

🪤Traps & gotchas

Rails version lock: designed for Rails 3–4 only (see gemfiles/ for multi-version testing). Crypto provider must be explicitly set in initializer before User model loads (default is BCrypt, but MD5/SHA1 are insecure). External OAuth requires omniauth gem and provider-specific config (not bundled). Activity logging writes to database on every request—can cause performance issues under high load. Remember-me tokens are httponly cookies by default; ensure Rails session store config matches. Brute force protection relies on database queries; no Redis caching means slow under attack.

💡Concepts to learn

  • Modular authentication submodules — Sorcery's core design allows picking and composing features (remember-me, brute force, activity logging) as mixins; understanding how lib/sorcery/model/submodules/ and lib/sorcery/controller/submodules/ are loaded conditionally is key to customizing it.
  • Pluggable crypto providers — Sorcery abstraction (lib/sorcery/crypto_providers/) allows swapping hash algorithms (BCrypt, SHA256, etc.) without touching model code; critical for understanding password security and legacy system migrations.
  • ORM adapters (Active Record abstraction) — lib/sorcery/adapters/ decouples sorcery from raw SQL, allowing future support for non-ActiveRecord ORMs; teach this pattern for maintainable persistence layers.
  • HTTP-only cookies and CSRF tokens — Sorcery's remember-me and session submodules rely on secure cookie defaults; misunderstanding httponly/secure flags is a common breach vector in Rails auth.
  • Token-based password reset workflows — lib/sorcery/model/submodules/reset_password.rb implements time-bound tokens; understanding token generation, validation, and expiry is essential for any auth system.
  • Brute force rate limiting via database counters — lib/sorcery/controller/submodules/brute_force_protection.rb uses login attempt counters and lockout windows; differs from token-bucket approaches and has scaling limitations.
  • External OAuth delegation (federation) — lib/sorcery/controller/submodules/external.rb integrates omniauth for delegated login; understanding OAuth 2.0 callback flows and user linking is critical for modern apps.
  • plataformatec/devise — Most popular Rails auth gem; feature-parity competitor with more active maintenance and broader Rails version support (5+).
  • Sorcery/sorcery — Official fork/successor to NoamB/sorcery; actively maintained, targets modern Rails, and is the canonical home for new sorcery development.
  • omniauth/omniauth — Dependency for sorcery's external OAuth submodule; provides the provider strategy DSL that sorcery::external wraps.
  • rails/rails — The Rails framework itself; sorcery is tightly coupled to Rails 3/4 conventions (migrations, controller concerns, generators).
  • rails/protected_attributes_plus — Complements sorcery's model layer; needed in Rails 4.2+ to whitelist password/email attrs without strong_parameters boilerplate.

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for crypto_providers modules

The lib/sorcery/crypto_providers/ directory contains 7 different encryption implementations (MD5, SHA1, SHA256, SHA512, BCrypt, AES256, and Common), but there are no visible test files for these critical security components. Each provider should have isolated unit tests covering encryption, decryption, and edge cases. This is especially important since these handle password hashing and sensitive data encryption.

  • [ ] Create spec/lib/sorcery/crypto_providers/ directory structure mirroring lib/sorcery/crypto_providers/
  • [ ] Add unit tests for each crypto provider: md5_spec.rb, sha1_spec.rb, sha256_spec.rb, sha512_spec.rb, bcrypt_spec.rb, aes256_spec.rb
  • [ ] Test encryption/decryption round-trips, edge cases (empty strings, special characters, large payloads)
  • [ ] Test that common.rb functionality works correctly across all providers
  • [ ] Add tests for backward compatibility (e.g., can bcrypt validate hashes from older SHA implementations)

Add integration tests for external OAuth/OAuth2 providers

The lib/sorcery/providers/ directory contains 9 provider implementations (Facebook, GitHub, Google, Heroku, Jira, LinkedIn, LiveID, PayPal, Salesforce) but no visible integration tests. These rely on external APIs and OAuth protocols (lib/sorcery/protocols/oauth.rb and oauth2.rb) that need testing. Current test coverage likely doesn't validate provider-specific token exchange, user info parsing, or error handling.

  • [ ] Create spec/lib/sorcery/providers/ with test files for each provider (facebook_spec.rb, github_spec.rb, etc.)
  • [ ] Add VCR cassettes or WebMock stubs for OAuth/OAuth2 flows in spec/fixtures/vcr_cassettes/
  • [ ] Test provider-specific behavior: authorization URL generation, token exchange, user info parsing
  • [ ] Add tests for error scenarios (invalid tokens, API failures, rate limiting)
  • [ ] Create shared examples for common OAuth2 provider patterns to reduce duplication

Add feature tests for model submodules workflow combinations

The lib/sorcery/model/submodules/ directory has 6 independent feature modules (activity_logging, brute_force_protection, external, remember_me, reset_password, user_activation), but there are likely no tests validating how they interact when multiple are enabled simultaneously. The generator (lib/generators/sorcery/install_generator.rb) allows users to mix and match these features, creating complex interaction scenarios that need validation.

  • [ ] Create spec/integration/model_submodules_integration_spec.rb for multi-feature scenarios
  • [ ] Test common combinations: reset_password + user_activation, brute_force_protection + activity_logging, remember_me + session_timeout
  • [ ] Validate that temporary_token.rb (lib/sorcery/model/temporary_token.rb) works correctly across reset_password and user_activation simultaneously
  • [ ] Test migration generation for all submodule combinations (files in lib/generators/sorcery/templates/migration/)
  • [ ] Verify initializer configuration (lib/generators/sorcery/templates/initializer.rb) correctly loads and doesn't conflict when multiple features are enabled

🌿Good first issues

  • Add test coverage for lib/sorcery/crypto_providers/aes256.rb—no spec file visible in provided structure, leaving encryption/decryption untested.
  • Document the OAuth callback flow (lib/sorcery/controller/submodules/external.rb) with a working example against GitHub OAuth, as README lacks concrete integration guide.
  • Add support for Rails 5+ by updating lib/generators/sorcery/templates/migration/ to use Rails 5+ migration syntax (e.g., create_table with primary_key option) and testing against gemfiles/rails50.gemfile.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 4aaf383 — Merge pull request #803 from athix/patch-1 (arnvald)
  • 58402e5 — Update README to only include move notice (joshbuker)
  • 80affcf — Merge pull request #798 from athix/feature/deprecate-rails-3 (arnvald)
  • b0bc0e9 — Merge branch 'travis-ci' into feature/deprecate-rails-3 (joshbuker)
  • 3254e37 — Fix TravisCI not allowing JRuby to fail (joshbuker)
  • 6874503 — Deprecate Rails 3 (joshbuker)
  • f592190 — Merge pull request #763 into feature/deprecate-rails-3 (joshbuker)
  • 1f0a57d — Merge pull request #786 from rubenmoya/master (arnvald)
  • e76786f — Merge pull request #792 from scriptwork/Fix_deprecation_warning_of_Rails5_ActiveRecord_Migration (arnvald)
  • 6984de4 — Updates CHANGELOG.md (rubenmoya)

🔒Security observations

  • High · Multiple Weak Cryptographic Hash Providers Available — lib/sorcery/crypto_providers/md5.rb, lib/sorcery/crypto_providers/sha1.rb. The codebase includes several deprecated and weak cryptographic providers (MD5, SHA1) that are known to be vulnerable to collision attacks. These are present in lib/sorcery/crypto_providers/ directory including md5.rb and sha1.rb. While stronger alternatives exist (bcrypt, SHA256, SHA512), the availability of weak options could lead to improper algorithm selection. Fix: Deprecate and remove MD5 and SHA1 crypto providers. Force users to use bcrypt or stronger alternatives (SHA256, SHA512, AES256). Add warnings if weak providers are selected during configuration.
  • High · Potential SQL Injection Risk in ORM Adapter — lib/sorcery/adapters/active_record_adapter.rb, lib/sorcery/adapters/base_adapter.rb. The active_record_adapter.rb and base_adapter.rb files handle database queries. Without detailed code inspection, there's a risk of SQL injection if user input is directly concatenated into queries, especially in authentication-related operations like login, password reset, and user activation flows. Fix: Audit all database queries to ensure parameterized queries/prepared statements are used. Use ActiveRecord's built-in query protection mechanisms (never string interpolation). Add input validation and sanitization for all user inputs before database operations.
  • High · OAuth/OAuth2 Implementation Security Concerns — lib/sorcery/protocols/oauth.rb, lib/sorcery/protocols/oauth2.rb, lib/sorcery/providers/. The OAuth and OAuth2 protocol implementations (lib/sorcery/protocols/oauth.rb, oauth2.rb) handle external authentication. Common vulnerabilities in OAuth implementations include CSRF token validation bypass, redirect URI validation issues, and token storage vulnerabilities. The presence of multiple provider integrations (Facebook, Google, GitHub, etc.) increases attack surface. Fix: Conduct thorough security audit of OAuth/OAuth2 flows. Verify CSRF tokens are properly validated. Validate redirect URIs against whitelist. Implement secure token storage. Use HTTPS only for token transmission. Implement PKCE for OAuth2 flows.
  • Medium · Session Timeout Configuration Risks — lib/sorcery/controller/submodules/session_timeout.rb. The session_timeout.rb submodule handles session management. Improper timeout configurations could allow session fixation attacks or excessive session persistence, increasing the window for account compromise. Fix: Implement secure default session timeout values (15-30 minutes recommended). Provide clear documentation on configuration. Implement idle timeout and absolute timeout separately. Add warnings for excessively long timeouts.
  • Medium · Remember Me Implementation Vulnerabilities — lib/sorcery/model/submodules/remember_me.rb, lib/sorcery/controller/submodules/remember_me.rb. The remember_me functionality (lib/sorcery/model/submodules/remember_me.rb, lib/sorcery/controller/submodules/remember_me.rb) stores persistent authentication tokens. These tokens could be vulnerable to theft if not properly secured, stored, or if they lack proper expiration. Fix: Ensure remember_me tokens are cryptographically random, long enough (>32 bytes), and never exposed in URLs. Hash tokens in database. Implement token rotation on each use. Set short expiration times (7-30 days). Use secure, HttpOnly, SameSite cookies for storage.
  • Medium · Brute Force Protection Implementation — lib/sorcery/controller/submodules/brute_force_protection.rb, lib/sorcery/model/submodules/brute_force_protection.rb. The brute_force_protection submodule may have incomplete protection mechanisms. Common bypasses include distributed attacks, account enumeration, or insufficient rate limiting. Fix: Implement progressive delays with exponential backoff. Add account lockout with time-based unlocking. Implement IP-based and account-based rate limiting. Add CAPTCHA challenges after failed attempts. Log and monitor brute force attempts. Implement account enumeration protection.
  • Medium · Password Reset Token Security — undefined. The reset_password submodule (lib/sorcery/model/submodules/reset_password. Fix: undefined

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · NoamB/sorcery — RepoPilot