Skip to content

fix(oauth2): log database token failures - #42644

Open
aminghadersohi wants to merge 9 commits into
apache:masterfrom
aminghadersohi:aminghadersohi/log-oauth2-db-auth-failures
Open

fix(oauth2): log database token failures#42644
aminghadersohi wants to merge 9 commits into
apache:masterfrom
aminghadersohi:aminghadersohi/log-oauth2-db-auth-failures

Conversation

@aminghadersohi

@aminghadersohi aminghadersohi commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

SUMMARY

Why

OAuth2 database token exchange and refresh failures lacked queryable context, and the callback emitted an outcome-neutral event metric that did not represent failures. Provider exception details and callback request metadata also needed an end-to-end redaction boundary.

What

  • Log token exchange and refresh failures with database_id, canonical engine, and exception type while excluding OAuth codes, tokens, exception text, and provider payloads.
  • Convert provider-facing exchange and refresh exceptions to sanitized OAuth2 domain exceptions before they reach Flask's generic traceback logging.
  • Exclude OAuth callback query, form, JSON, and referrer data from event logs while retaining safe request metadata.
  • Use the standard REST API StatsD decorator so exactly one of DatabaseRestApi.oauth2.success, .warning, or .error is emitted after transaction completion.
  • Run event logging outside the token transaction so an event-log rollback cannot discard a successful token write.
  • Document the metric migration and add focused regression coverage for logging, redaction, transaction ordering, event-log failures, and callback metrics.
  • Stabilize an inherited MCP sub-day time-range test by freezing its clock; during the first UTC hour, the test's raw Last hour premise is otherwise false.

Blast radius

Limited to OAuth2 database token exchange/refresh error handling and callback observability. Success-path token persistence remains unchanged. Provider exceptions crossing the OAuth2 boundary are intentionally replaced with sanitized OAuth2 domain exceptions; OAuth-specific refresh failures still trigger token cleanup and re-authentication.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Not applicable; this is backend observability and error-handling work.

TESTING INSTRUCTIONS

pytest -q tests/unit_tests/commands/databases/oauth2_test.py tests/unit_tests/utils/oauth2_tests.py tests/unit_tests/databases/oauth2_api_test.py tests/unit_tests/databases/api_test.py -k oauth2 --disable-warnings
pytest -q tests/unit_tests/db_engine_specs/test_base.py -k oauth2_fresh_token --disable-warnings
pytest -q tests/unit_tests/mcp_service/common/test_time_range_validation.py --disable-warnings
pre-commit run

Results:

  • OAuth2 selection: 42 passed, 110 deselected
  • Base engine OAuth2 token tests: 5 passed, 63 deselected
  • MCP time-range validator tests: 75 passed
  • All staged-file pre-commit hooks passed, including MyPy, Ruff, Ruff format, and Pylint.

pre-commit run --all-files was also attempted. Backend checks passed, but this worktree's frontend custom-rule hook cannot load the uninstalled glob package; the repository-wide formatter and Ruff hooks also report unrelated files outside this PR.

RISK & ROLLBACK

Low-to-moderate risk: the success path is unchanged, but failure paths now expose only sanitized OAuth2 domain exceptions, and event logging runs after the token transaction. Revert abe3bcad8f to restore the prior OAuth2 failure-path behavior. Revert a79b4d9c6f independently to remove the inherited time-dependent test stabilization.

REVIEW GUIDANCE

Please focus on:

  • the exception sanitization boundary and absence of provider data from all loggers/API responses;
  • decorator ordering: StatsD → event logging → transaction;
  • event-log failure isolation from token persistence;
  • consistency of structured log dimensions and callback metric classification.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API
    • Replaces the outcome-neutral DatabaseRestApi.oauth2 counter with outcome-qualified counters documented in UPDATING.md.

@github-actions github-actions Bot added the api Related to the REST API label Jul 31, 2026
Comment thread superset/commands/database/oauth2.py Fixed
@bito-code-review

Copy link
Copy Markdown
Contributor

The logging changes in this pull request are designed to avoid logging sensitive information by using structured logging that captures only metadata, such as database_id, engine, and error_type. The code explicitly avoids logging the raw exception object or user-specific data that might contain credentials. These changes are appropriate and follow security best practices for structured logging.

superset/commands/database/oauth2.py

except Exception as ex:
            logger.error(
                "OAuth2 token exchange failed: database_id=%s engine=%s "
                "error_type=%s",
                self._state["database_id"],
                self._database.backend,
                type(ex).__name__,
            )

@codecov

codecov Bot commented Jul 31, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 55.55556% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.56%. Comparing base (1605676) to head (69a0873).

Files with missing lines Patch % Lines
superset/commands/database/oauth2.py 25.00% 6 Missing ⚠️
superset/utils/oauth2.py 20.00% 4 Missing ⚠️
superset/db_engine_specs/base.py 0.00% 1 Missing ⚠️
superset/utils/log.py 90.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #42644      +/-   ##
==========================================
- Coverage   65.79%   65.56%   -0.23%     
==========================================
  Files        2842     2821      -21     
  Lines      162106   160402    -1704     
  Branches    37148    36593     -555     
==========================================
- Hits       106653   105164    -1489     
+ Misses      53388    53172     -216     
- Partials     2065     2066       +1     
Flag Coverage Δ
hive 38.08% <55.55%> (+<0.01%) ⬆️
mysql 57.90% <55.55%> (-0.01%) ⬇️
postgres 57.94% <55.55%> (-0.01%) ⬇️
presto 40.00% <55.55%> (+<0.01%) ⬆️
python 59.32% <55.55%> (-0.01%) ⬇️
sqlite 57.57% <55.55%> (-0.01%) ⬇️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aminghadersohi
aminghadersohi marked this pull request as ready for review August 1, 2026 00:41
@dosubot dosubot Bot added authentication:sso Single Sign On logging Creates a UI or API endpoint that could benefit from logging. labels Aug 1, 2026
Comment thread superset/databases/api.py
return self.response_404()

@expose("/oauth2/", methods=["GET"])
@statsd_metrics

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: The newly added statsd_metrics wrapper emits the failure counter from its exception handler without protecting self.incr_stats(...). If the configured StatsD client fails while recording an OAuth2 error, that secondary exception replaces the original callback failure and can change the response and traceback presented to the client. Make metric emission best-effort so observability failures cannot mask the OAuth2 exception. [error handling]

Severity Level: Minor 🧹
- ❌ OAuth2 failure responses can expose a StatsD error instead.
- ⚠️ Original token-exchange diagnostics can be lost.
- ⚠️ Callback error handling depends on StatsD availability.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/databases/api.py
**Line:** 1457:1457
**Comment:**
	*Error Handling: The newly added `statsd_metrics` wrapper emits the failure counter from its exception handler without protecting `self.incr_stats(...)`. If the configured StatsD client fails while recording an OAuth2 error, that secondary exception replaces the original callback failure and can change the response and traceback presented to the client. Make metric emission best-effort so observability failures cannot mask the OAuth2 exception.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@aminghadersohi
aminghadersohi marked this pull request as draft August 1, 2026 00:52
@aminghadersohi
aminghadersohi marked this pull request as ready for review August 4, 2026 19:31
@dosubot dosubot Bot added change:backend Requires changing the backend data:connect Namespace | Anything related to db connections / integrations labels Aug 4, 2026
@bito-code-review

bito-code-review Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8ea754

Actionable Suggestions - 0
Review Details
  • Files reviewed - 7 · Commit Range: a829277..724e4fc
    • superset/commands/database/oauth2.py
    • superset/databases/api.py
    • superset/utils/log.py
    • superset/utils/oauth2.py
    • tests/unit_tests/commands/databases/oauth2_test.py
    • tests/unit_tests/databases/oauth2_api_test.py
    • tests/unit_tests/utils/oauth2_tests.py
  • Files skipped - 1
    • UPDATING.md - Reason: Filter setting
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@netlify

netlify Bot commented Aug 5, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 69a0873
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a72b9e984031900085deca3
😎 Deploy Preview https://deploy-preview-42644--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@bito-code-review

bito-code-review Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #d5dd55

Actionable Suggestions - 0
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset/databases/api.py - 1
Review Details
  • Files reviewed - 11 · Commit Range: 724e4fc..a79b4d9
    • superset/commands/database/oauth2.py
    • superset/databases/api.py
    • superset/db_engine_specs/base.py
    • superset/exceptions.py
    • superset/utils/log.py
    • superset/utils/oauth2.py
    • tests/unit_tests/commands/databases/oauth2_test.py
    • tests/unit_tests/databases/oauth2_api_test.py
    • tests/unit_tests/db_engine_specs/test_base.py
    • tests/unit_tests/utils/oauth2_tests.py
    • tests/unit_tests/mcp_service/common/test_time_range_validation.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the REST API authentication:sso Single Sign On change:backend Requires changing the backend data:connect Namespace | Anything related to db connections / integrations logging Creates a UI or API endpoint that could benefit from logging. review:draft size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants