Skip to content

fix(auth): unwrap configmanager Items in require_auth_token#1136

Merged
amalcaraz merged 1 commit into
mainfrom
fix/auth-token-item-wrapper
May 14, 2026
Merged

fix(auth): unwrap configmanager Items in require_auth_token#1136
amalcaraz merged 1 commit into
mainfrom
fix/auth-token-item-wrapper

Conversation

@amalcaraz
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #884.

require_auth_token was passing configmanager.Item wrappers straight into verify_auth_token, which then forwarded them to bytes.fromhex(public_key_hex) and the current_time - timestamp > max_age_seconds comparison. Both raise TypeError on non-primitive arguments:

public_key = auth_config.public_key      # → <Item public_key '02…389'>, NOT str
max_age    = auth_config.max_token_age   # → <Item max_token_age 300>, NOT int

Those errors were swallowed by the except Exception: return False inside verify_auth_token, so every token validation silently returned False — the endpoint /api/v0/price/{hash}/recalculate (and any future @require_auth_token-decorated route) was effectively dead even after #884 fixed the PublicKey.from_hex AttributeError.

Fix

Call .value on the two Item accessors in require_auth_token before handing them to verify_auth_token:

         config = get_config()
         auth_config = config.aleph.auth
-        public_key = auth_config.public_key
-        max_age = auth_config.max_token_age
+        public_key = auth_config.public_key.value
+        max_age = auth_config.max_token_age.value

Tests

The existing tests in tests/toolkit/test_ecdsa.py exercised verify_signature / verify_auth_token with raw strings — that's why this bug slipped through. Added two regression tests that drive the require_auth_token decorator with a real configmanager.Config (so Item wrappers are present, matching the production case):

  • test_require_auth_token_unwraps_configmanager_items — valid token → 200
  • test_require_auth_token_rejects_invalid_token_with_item_wrappers — token signed by a different key → 401

Test plan

  • hatch run linting:all — passes
  • hatch run testing:test tests/toolkit/test_ecdsa.py -v — 13/13 passed
  • Manual verification against a patched CCN: POST /api/v0/price/{hash}/recalculate with a valid token returns 200 and updates cost_credit from 0 to a non-zero value.

Out of scope

  • Reworking verify_auth_token / verify_signature to coerce inputs (kept strict — the contract is "primitives in, bool out").
  • Replacing the catch-all except Exception: return False (would have surfaced this as a 500 instead of 401, but is a bigger discussion).
  • Auditing .value defensively elsewhere — only require_auth_token was in scope here.

`require_auth_token` was passing `configmanager.Item` wrappers straight
into `verify_auth_token`, where `bytes.fromhex(public_key)` and the
`int > Item` comparison both raised `TypeError`. Those errors were
swallowed by the `except Exception: return False` in
`verify_auth_token`, so every token validation silently returned False
and `/api/v0/price/{hash}/recalculate` (and any other
`@require_auth_token` route) returned 401 for valid tokens.

Call `.value` on the two `Item` accessors before handing them to
`verify_auth_token`, and add a regression test that exercises the
decorator with a real `Config` so future similar mistakes are caught.

Follow-up to #884.
@amalcaraz amalcaraz self-assigned this May 14, 2026
@amalcaraz amalcaraz requested review from aliel and odesenfans May 14, 2026 20:53
Copy link
Copy Markdown

@foxpatch-aleph foxpatch-aleph left a comment

Choose a reason for hiding this comment

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

This is a focused, correct fix for a real bug where configmanager.Item wrappers were passed to functions expecting primitive types, causing silent authentication failures. The two-line change correctly unwraps the items with .value, and the two regression tests exercise the actual decorator path with real configmanager.Config instances to prevent regression. Clean, minimal, well-documented.

tests/toolkit/test_ecdsa.py (line 262): Trivial nit: the second _ for _other_public_key = generate_key_pair()[1] would be slightly more readable than a bare _ in a different scope — but this is cosmetic and fine as-is.

@amalcaraz amalcaraz merged commit 1275157 into main May 14, 2026
4 checks passed
@amalcaraz amalcaraz deleted the fix/auth-token-item-wrapper branch May 14, 2026 21:15
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