[PR #346] [MERGED] Harden GSC OAuth callback state validation #311

Closed
opened 2026-03-02 23:35:05 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/AJaySi/ALwrity/pull/346
Author: @AJaySi
Created: 2/11/2026
Status: Merged
Merged: 2/11/2026
Merged by: @AJaySi

Base: mainHead: codex/harden-gscservice-handle_oauth_callback


📝 Commits (1)

  • 6929ea1 Harden GSC OAuth callback state validation

📊 Changes

2 files changed (+183 additions, -37 deletions)

View changed files

backend/services/gsc_oauth_state_validation_tests.py (+149 -0)
📝 backend/services/gsc_service.py (+34 -37)

📄 Description

Motivation

  • Prevent ambiguous or replayed OAuth callbacks by enforcing exact one-time state consumption and explicit errors for missing/expired/unknown states.
  • Align GSC state handling with the existing Bing OAuth pattern by adding an expiry and making state consumption atomic.

Description

  • Added an expires_at column to the gsc_oauth_states table and ensured the column is created/altered during table initialization, with a default 20-minute TTL. (backend/services/gsc_service.py)
  • Persist expires_at when issuing a new state and update it on conflict so each state has a time-to-live. (backend/services/gsc_service.py)
  • Rewrote handle_oauth_callback to: immediately reject a missing state; atomically consume only an exact, non-expired state using DELETE ... RETURNING user_id; detect and return explicit errors for expired or not-found/reused states; and removed prior fallback branches that returned recent credentials or used the most recent state. (backend/services/gsc_service.py)
  • Added targeted unit tests exercising missing state, unknown state, reused state, expired state, and cross-user mismatch scenarios. (backend/services/gsc_oauth_state_validation_tests.py)

Testing

  • Added backend/services/gsc_oauth_state_validation_tests.py covering the invalid-state, reused-state, expired-state, and cross-user mismatch cases and ran the tests successfully. The test command used was PYTHONPATH=backend pytest -q backend/services/gsc_oauth_state_validation_tests.py. All tests passed.

Codex Task


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/AJaySi/ALwrity/pull/346 **Author:** [@AJaySi](https://github.com/AJaySi) **Created:** 2/11/2026 **Status:** ✅ Merged **Merged:** 2/11/2026 **Merged by:** [@AJaySi](https://github.com/AJaySi) **Base:** `main` ← **Head:** `codex/harden-gscservice-handle_oauth_callback` --- ### 📝 Commits (1) - [`6929ea1`](https://github.com/AJaySi/ALwrity/commit/6929ea1cdafb2f874b1fd9c75285e4a081cb83d5) Harden GSC OAuth callback state validation ### 📊 Changes **2 files changed** (+183 additions, -37 deletions) <details> <summary>View changed files</summary> ➕ `backend/services/gsc_oauth_state_validation_tests.py` (+149 -0) 📝 `backend/services/gsc_service.py` (+34 -37) </details> ### 📄 Description ### Motivation - Prevent ambiguous or replayed OAuth callbacks by enforcing exact one-time state consumption and explicit errors for missing/expired/unknown states. - Align GSC state handling with the existing Bing OAuth pattern by adding an expiry and making state consumption atomic. ### Description - Added an `expires_at` column to the `gsc_oauth_states` table and ensured the column is created/altered during table initialization, with a default 20-minute TTL. (`backend/services/gsc_service.py`) - Persist `expires_at` when issuing a new state and update it on conflict so each state has a time-to-live. (`backend/services/gsc_service.py`) - Rewrote `handle_oauth_callback` to: immediately reject a missing `state`; atomically consume only an exact, non-expired state using `DELETE ... RETURNING user_id`; detect and return explicit errors for expired or not-found/reused states; and removed prior fallback branches that returned recent credentials or used the most recent state. (`backend/services/gsc_service.py`) - Added targeted unit tests exercising missing state, unknown state, reused state, expired state, and cross-user mismatch scenarios. (`backend/services/gsc_oauth_state_validation_tests.py`) ### Testing - Added `backend/services/gsc_oauth_state_validation_tests.py` covering the invalid-state, reused-state, expired-state, and cross-user mismatch cases and ran the tests successfully. The test command used was `PYTHONPATH=backend pytest -q backend/services/gsc_oauth_state_validation_tests.py`. All tests passed. ------ [Codex Task](https://chatgpt.com/codex/tasks/task_e_698c305df3cc8328aa8632d30d6a588a) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
kerem 2026-03-02 23:35:05 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/ALwrity#311
No description provided.