Skip to content

Auth routes#7

Merged
sreejita-saha merged 8 commits into
mainfrom
auth-routes
May 21, 2026
Merged

Auth routes#7
sreejita-saha merged 8 commits into
mainfrom
auth-routes

Conversation

@sarahmc253
Copy link
Copy Markdown
Owner

@sarahmc253 sarahmc253 commented May 20, 2026

Summary by CodeRabbit

  • New Features

    • Added full registration and login flows that issue short-lived access tokens.
  • Security

    • Upgraded password handling with modern hashing and automatic refresh on login.
    • Reduced username-enumeration risk via dummy verification and constant-time checks.
    • Tightened request validation and graceful handling of malformed JSON.
  • Chores

    • Switched dependency pins to minimum-version constraints and added server/auth packages.
  • Documentation

    • Expanded session transcript with setup and validation details.
  • Style

    • Updated ignore rules to exclude local tool caches.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 98bde9ef-3af7-4312-b81c-d0e9319959cd

📥 Commits

Reviewing files that changed from the base of the PR and between 12ca87d and 07338ed.

📒 Files selected for processing (1)
  • server/app/auth/routes.py

📝 Walkthrough

Walkthrough

Adds full /register and /login endpoints with Argon2id password hashing (with rehash-on-login), JWT access tokens (15-minute expiry), dummy-hash timing mitigation, stricter JSON-field validation, dependency minimum-version updates, and an updated transcript documenting decisions.

Changes

User Authentication with JWT and Password Hashing

Layer / File(s) Summary
Dependencies and JWT Configuration
requirements.txt, server/app/__init__.py, .gitignore
Rewrote dependency pins to >= constraints and added flask-jwt-extended, argon2-cffi, web3, gunicorn; configured JWT_SECRET_KEY and JWT_ACCESS_TOKEN_EXPIRES=15m and initialized JWTManager; .gitignore now ignores .claude/ and __pycache__/.
Auth module: Argon2, validators, and constants
server/app/auth/routes.py
Adds module-level PasswordHasher configured for Argon2id, precomputed _DUMMY_HASH, REQUIRED_FIELDS, and shared JSON/field validation helper; blueprint registration.
Registration endpoint implementation
server/app/auth/routes.py
POST /register validates JSON is an object and required non-blank fields, hashes password with Argon2id (extracts salt), generates UUID/timestamp, inserts user row with commit/rollback and returns 409 on duplicate keys.
Login handler, verification, rehash, and JWT issuance
server/app/auth/routes.py
POST /login validates input, fetches user by username, uses dummy Argon2 verify when user absent, verifies credentials, conditionally rehashes and updates stored hash/salt, and returns a JWT access token plus selected user fields.
Design transcript and docs
docs/transcript_sarah.md
Transcript updated with register/login decisions, validation tightening, request.get_json(silent=True) adoption, dependency pinning approach, and final "update transcript" prompt.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant AuthRoutes as server.app.auth.routes
  participant DB as users_db
  participant Argon2 as PasswordHasher
  participant JWT as JWTManager

  Client->>AuthRoutes: POST /login (username,password)
  AuthRoutes->>DB: SELECT user BY username
  DB-->>AuthRoutes: user row or empty
  AuthRoutes->>Argon2: verify(password, stored_hash) or verify(_DUMMY_HASH)
  Argon2-->>AuthRoutes: verification result
  AuthRoutes->>DB: UPDATE argon2id_server_hash/salt (if rehash needed)
  AuthRoutes->>JWT: create_access_token(identity=user_id)
  AuthRoutes-->>Client: 200 {access_token, user_fields}
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • sarahmc253/WhatSaS#6: Builds on the earlier auth blueprint and app-factory foundations used by these auth endpoint implementations.

Suggested reviewers

  • sreejita-saha
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Auth routes' is vague and generic, lacking specificity about the main implementation details (registration, login, JWT, password hashing, etc.). Provide a more specific title that describes the key changes, such as 'Implement user registration and login with JWT authentication' or 'Add auth routes with Argon2 password hashing and JWT tokens'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch auth-routes

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
server/app/auth/routes.py (1)

108-111: ⚡ Quick win

Narrow exception handling in dummy-verify path to specific Argon2 exceptions.

Catching broad Exception can hide real failures. The dummy-verify code should only catch expected Argon2 verification exceptions:

-from argon2.exceptions import VerifyMismatchError
+from argon2.exceptions import VerifyMismatchError, VerificationError
@@
-        try:
-            ph.verify(_DUMMY_HASH, data['password'])
-        except Exception:
-            pass
+        try:
+            ph.verify(_DUMMY_HASH, data['password'])
+        except (VerifyMismatchError, VerificationError):
+            pass

This catches password mismatches and other verification failures while allowing unexpected errors to propagate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/app/auth/routes.py` around lines 108 - 111, The dummy verification
currently swallows all exceptions in the ph.verify(_DUMMY_HASH,
data['password']) call; narrow this by importing the specific Argon2 exceptions
(e.g., VerifyMismatchError, VerificationError, InvalidHash from
argon2.exceptions) and replace the broad "except Exception" with a targeted
"except (VerifyMismatchError, VerificationError, InvalidHash):" so only expected
verification failures are ignored and other unexpected errors still propagate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@requirements.txt`:
- Around line 1-7: The requirements.txt lists unpinned packages (flask,
flask-jwt-extended, argon2-cffi, mysql-connector-python, web3, python-dotenv,
gunicorn) which makes builds unreproducible and exposes you to transitive vuln
regressions; replace this by generating and committing a fully pinned lock file
(e.g., requirements.lock from pip freeze or pip-tools) and update CI to validate
it, then update the repo to (1) add the lockfile (requirements.lock) with exact
versions for all direct and transitive deps, (2) modify or keep requirements.txt
to reference only top-level packages if needed, and (3) add a CI step using
pip-audit (or equivalent) to fail the build on vulnerable packages (with special
attention to flask-jwt-extended/PyJWT versions), ensuring future installs use
the lockfile to reproduce builds.

In `@server/app/auth/routes.py`:
- Around line 34-36: The current required-field check uses truthiness so
non-string values slip through; update the validation that builds missing to
require each field in REQUIRED_FIELDS be an instance of str and non-empty after
.strip() (e.g., replace the list comprehension that uses data.get(f) with an
isinstance(data.get(f), str) and data.get(f).strip() check) and return the same
400 JSON error if any fail; apply the identical type+non-empty validation logic
for the second occurrence referenced (lines 85-87) so auth inputs are validated
as strings at the boundary.

---

Nitpick comments:
In `@server/app/auth/routes.py`:
- Around line 108-111: The dummy verification currently swallows all exceptions
in the ph.verify(_DUMMY_HASH, data['password']) call; narrow this by importing
the specific Argon2 exceptions (e.g., VerifyMismatchError, VerificationError,
InvalidHash from argon2.exceptions) and replace the broad "except Exception"
with a targeted "except (VerifyMismatchError, VerificationError, InvalidHash):"
so only expected verification failures are ignored and other unexpected errors
still propagate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: be8a7a00-e3f0-4aea-b593-89408a2dcbc8

📥 Commits

Reviewing files that changed from the base of the PR and between f23c333 and 77e12be.

📒 Files selected for processing (5)
  • .gitignore
  • docs/transcript_sarah.md
  • requirements.txt
  • server/app/__init__.py
  • server/app/auth/routes.py

Comment thread requirements.txt Outdated
Comment thread server/app/auth/routes.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/app/auth/routes.py`:
- Around line 27-32: The helper _invalid_fields currently assumes data is a dict
and will raise if given a non-object JSON; update _invalid_fields to first check
if data is a mapping (e.g., isinstance(data, dict)) and if not return the full
list of fields as "invalid" so callers can respond with a 400, and/or explicitly
validate request.get_json() in the /register and /login handlers before calling
_invalid_fields (if the body is not a dict return a 400 with a clear message).
Ensure you reference _invalid_fields when making the change so non-object JSON
payloads no longer cause a 500.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 749e2dc2-6ef6-476d-807f-d2f0b04947ff

📥 Commits

Reviewing files that changed from the base of the PR and between 77e12be and 398afa6.

📒 Files selected for processing (3)
  • docs/transcript_sarah.md
  • requirements.txt
  • server/app/auth/routes.py
✅ Files skipped from review due to trivial changes (1)
  • docs/transcript_sarah.md

Comment thread server/app/auth/routes.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@server/app/auth/routes.py`:
- Around line 36-39: The register() and login() routes call request.get_json()
which raises BadRequest on malformed JSON before the dict check; update both
handlers to call request.get_json(silent=True) (or wrap the get_json call in a
try/except for BadRequest) so malformed JSON returns your normalized JSON 400
response; ensure you keep the existing isinstance(data, dict) guard and return
jsonify({'error': 'Request body must be a JSON object'}), 400 when data is None
or not a dict.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e914227-ee26-43fa-919e-7d9a778b21dd

📥 Commits

Reviewing files that changed from the base of the PR and between 398afa6 and c637de0.

📒 Files selected for processing (2)
  • docs/transcript_sarah.md
  • server/app/auth/routes.py
✅ Files skipped from review due to trivial changes (1)
  • docs/transcript_sarah.md

Comment thread server/app/auth/routes.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
server/app/auth/routes.py (1)

140-142: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Rehash failure should not block successful login.

If the password was already verified but the rehash DB update fails, the exception is re-raised, returning a 500 to an otherwise-authenticated user. Since rehashing is a background optimization, consider logging the error and continuing to issue the token.

💡 Suggested fix
         try:
             cursor.execute(
                 """
                 UPDATE users
                 SET argon2id_server_hash = %s, argon2id_server_salt = %s
                 WHERE id = %s
                 """,
                 (new_hash, new_salt, user['id']),
             )
             db.commit()
         except Exception:
             db.rollback()
-            raise
+            # Log but don't fail login — rehash is opportunistic
+            # TODO: Add proper logging here
         finally:
             cursor.close()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/app/auth/routes.py` around lines 140 - 142, The current except block
around the password rehash update (the except Exception that calls db.rollback()
and re-raises) will turn a rehash failure into a 500 for an
otherwise-authenticated user; change this so the rehash failure is logged and
swallowed while allowing token issuance to continue. Locate the rehash DB update
in server/app/auth/routes.py (the try/except surrounding db.rollback()) and
replace the re-raise with a logged error (use the existing
logger/current_app.logger) and ensure any necessary rollback/cleanup still runs,
but do not raise the exception so the route can proceed to issue the
authentication token.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@server/app/auth/routes.py`:
- Around line 140-142: The current except block around the password rehash
update (the except Exception that calls db.rollback() and re-raises) will turn a
rehash failure into a 500 for an otherwise-authenticated user; change this so
the rehash failure is logged and swallowed while allowing token issuance to
continue. Locate the rehash DB update in server/app/auth/routes.py (the
try/except surrounding db.rollback()) and replace the re-raise with a logged
error (use the existing logger/current_app.logger) and ensure any necessary
rollback/cleanup still runs, but do not raise the exception so the route can
proceed to issue the authentication token.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ecebfeba-c0a6-4665-bf0e-e3f438b51922

📥 Commits

Reviewing files that changed from the base of the PR and between c637de0 and 12ca87d.

📒 Files selected for processing (2)
  • docs/transcript_sarah.md
  • server/app/auth/routes.py
✅ Files skipped from review due to trivial changes (1)
  • docs/transcript_sarah.md

@sreejita-saha sreejita-saha merged commit ddae0be into main May 21, 2026
1 check passed
@sreejita-saha sreejita-saha deleted the auth-routes branch May 21, 2026 13:08
This was referenced May 21, 2026
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants