Skip to content

Mint frontend_token with explicit expiry - #21

Open
Gutts-n wants to merge 1 commit into
mainfrom
feature/frontend-token-expiry
Open

Mint frontend_token with explicit expiry#21
Gutts-n wants to merge 1 commit into
mainfrom
feature/frontend-token-expiry

Conversation

@Gutts-n

@Gutts-n Gutts-n commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What

Mint the CKAN frontend_token in _generate_token with an explicit expires_in/unit (default 1h, env-overridable via CKANEXT__SSE__FRONTEND_TOKEN_EXPIRES_IN / _UNIT) instead of relying on the plugin default.

Why

Threat Model Remediation issue #324, Row 8 — "Enable CKAN token expiry". The expire_api_token plugin exists but was disabled. Enabling it makes expires_in/unit required at mint time; this sets them explicitly so the lifetime is a deliberate policy value rather than the implicit 3600s default.

Coordinated changes

  • Frontend re-mints this token before expiry (ssen-portal PR).
  • Plugin enabled + datapusher token given a long lifetime (dx-helm-sse-prod / dx-helm-sse-dev PRs).

Merge order: this + helm PRs together, frontend before/with rollout.

Summary by CodeRabbit

  • Bug Fixes
    • Frontend API tokens now use a configurable expiration duration.
    • Added default token lifetime settings to ensure predictable expiration behavior.
    • Existing frontend tokens continue to be revoked before a new token is issued.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The frontend token generation flow now reads expiration settings from environment variables and passes them explicitly when minting the API token, with defaults of 1 and 3600.

Changes

Frontend token lifetime

Layer / File(s) Summary
Configure frontend token expiration
ckanext/sse/action.py
_generate_token reads CKANEXT__SSE__FRONTEND_TOKEN_EXPIRES_IN and CKANEXT__SSE__FRONTEND_TOKEN_UNIT, then supplies the resulting values to api_token_create.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: minting frontend_token with an explicit expiry instead of relying on defaults.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 feature/frontend-token-expiry

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@anuveyatsu

Copy link
Copy Markdown
Member

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@ckanext/sse/action.py`:
- Around line 526-527: Implement and ship the frontend_token renewal consumer
alongside the token lifetime change: update the frontend session flow referenced
by the comment so it detects impending frontend_token expiry and re-mints the
token before expiration, then uses the renewed token for subsequent API calls.
Ensure this behavior is enabled for newly created sessions and preserves the
existing long-lived NextAuth session.
- Around line 528-533: Update the frontend token rotation flow around
frontend_token_expires_in and frontend_token_unit to parse and validate both
configuration values before revoking the existing frontend_token. Reject empty,
malformed, or non-positive values with a clear configuration error, and only
proceed to token revocation and replacement after validation succeeds.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3e41ea24-1fb1-4841-a58b-361de993721c

📥 Commits

Reviewing files that changed from the base of the PR and between e192075 and 6b578b0.

📒 Files selected for processing (1)
  • ckanext/sse/action.py

Comment thread ckanext/sse/action.py
Comment on lines +526 to +527
# The frontend (ssen-portal) re-mints this token on expiry, so a short
# lifetime here does not break the long-lived NextAuth session.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files containing sse/action.py:"
git ls-files | grep -F 'ckanext/sse/action.py' || true

echo
echo "Line count:"
wc -l ckanext/sse/action.py

echo
echo "Relevant generate_token section:"
sed -n '480,570p' ckanext/sse/action.py

echo
echo "Search frontend token env vars/usages:"
rg -n 'FRONTEND_TOKEN|frontend_token|NextAuth|CKANEXT__SSE|DEFAULT|expires_in' ckanext .github docker-compose* compose* -S || true

Repository: datopian/ckanext-sse

Length of output: 6172


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Diff stat:"
git diff --stat

echo
echo "Context around changed token action maybe:"
git diff ckanext/sse/action.py | sed -n '1,220p' || true

echo
echo "Search exact env var definitions/documentation:"
rg -n 'CKANEXT__SSE__FRONTEND_TOKEN_(UNIT|EXPIRES_IN_UNIT)|FRONTEND_TOKEN_UNIT|FRONTEND_TOKEN_EXPIRES_IN_UNIT' . -S || true

Repository: datopian/ckanext-sse

Length of output: 360


Ship frontend_token renewal with this change.

The default payload is expires_in=1, unit=3600, so new frontend sessions get 3,600-second tokens. If the NextAuth/backend deployment goes live without a frontend renewal consumer that re-mints frontend_token before expiry, API calls will stop while the user session is still valid.

🤖 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 `@ckanext/sse/action.py` around lines 526 - 527, Implement and ship the
frontend_token renewal consumer alongside the token lifetime change: update the
frontend session flow referenced by the comment so it detects impending
frontend_token expiry and re-mints the token before expiration, then uses the
renewed token for subsequent API calls. Ensure this behavior is enabled for
newly created sessions and preserves the existing long-lived NextAuth session.

Comment thread ckanext/sse/action.py
Comment on lines +528 to +533
frontend_token_expires_in = int(
os.environ.get("CKANEXT__SSE__FRONTEND_TOKEN_EXPIRES_IN", 1)
)
frontend_token_unit = int(
os.environ.get("CKANEXT__SSE__FRONTEND_TOKEN_UNIT", 3600)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file excerpt =="
sed -n '480,555p' ckanext/sse/action.py

echo
echo "== related error handling/search =="
rg -n "frontend_token|revoc|token_expires|CKANEXT__SSE__FRONTEND|ValueError|expires" ckanext/sse/action.py ckanext/sse -S || true

echo
echo "== git diff stat/name status if available =="
git diff --stat || true
git diff -- ckanext/sse/action.py | sed -n '1,220p' || true

Repository: datopian/ckanext-sse

Length of output: 5204


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== call graph / action callers =="
rg -n "_generate_token|_login_frontend_token|frontend_token|_check_auth|api_token_create|api_token_revoke" ckanext/sse/action.py ckanext/sse -S || true

echo
echo "== validators excerpt =="
sed -n '150,205p' ckanext/sse/validators.py

echo
echo "== behavior probe: int parsing order/exception behavior =="
python3 - <<'PY'
class RevokeOnce:
    def __init__(self):
        self.revoked = False
    def revoke(self):
        self.revoked = True
        return object()

class BadInt:
    def __str__(self):
        return "bad"
    def __int__(self):
        raise ValueError("bad lifetime")
    def __bool__(self):
        return False

r = RevokeOnce()
old_token = r.revoke()
tokens = [{"name": "frontend_token", "id": "old"}]
front = tokens[0]["name"] == "frontend_token"
if front:
    r.revoke()  # existing token revoked
try:
    frontend_token_expires_in = int(BadInt())
except Exception as e:
    exc = e
print("revoked_before_parse=", r.revoked, type(exc).__name__, str(exc) if exc else None)
PY

Repository: datopian/ckanext-sse

Length of output: 4387


Validate lifetime configuration before revoking the old token.

Empty or malformed CKANEXT__SSE__FRONTEND_TOKEN_EXPIRES_IN / CKANEXT__SSE__FRONTEND_TOKEN_UNIT values raise during int() parsing after any existing frontend_token has already been revoked. Since the except Exception branch leaves user["frontend_token"] as None, a bad deployment value can remove the working token without creating a replacement. Parse and validate these values before revocation, reject non-positive values, and return a clear configuration error.

🤖 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 `@ckanext/sse/action.py` around lines 528 - 533, Update the frontend token
rotation flow around frontend_token_expires_in and frontend_token_unit to parse
and validate both configuration values before revoking the existing
frontend_token. Reject empty, malformed, or non-positive values with a clear
configuration error, and only proceed to token revocation and replacement after
validation succeeds.

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