Skip to content

Add public mock auth runtime#19

Merged
bingran-you merged 1 commit into
mainfrom
bry/public-mock-auth-runtime
Jul 4, 2026
Merged

Add public mock auth runtime#19
bingran-you merged 1 commit into
mainfrom
bry/public-mock-auth-runtime

Conversation

@bingran-you

Copy link
Copy Markdown
Contributor

Summary

  • add the public mock-auth environment package plus the shared auth-client middleware package
  • wire mock-auth into config, the env-0 manifest, generated base image installs, DevHub/control seeding, CI, and Docker smoke coverage
  • enable optional OAuth enforcement in mock-gmail and add auth-least-privilege-summary to both example_tasks/ and tasks/

Validation

  • uv run --extra dev pytest tests -q in packages/environments/mock-auth -> 228 passed, 5 skipped
  • uv run --extra dev pytest tests -q in packages/environments/mock-gmail -> 155 passed
  • uv run --extra dev pytest tests -q in packages/auth-client -> 108 passed
  • python3 -m unittest tests/test_env0_control.py -> 21 passed
  • structural task package check for example_tasks/ and tasks/ -> all-public-task-packages-valid
  • python3 docker/generate_dockerfile.py --check
  • git diff --check
  • docker/build-base.sh && PULL_BASE=0 scripts/smoke_docker_examples.sh
  • BENCHFLOW_REWARD_LENIENT=1 bench eval run --tasks-dir example_tasks --include auth-least-privilege-summary --agent oracle --sandbox docker --jobs-dir .local/bf-jobs-public-auth-example-oracle --context-root . --concurrency 1 --build-concurrency 1 -> 1/1, reward 1.0
  • BENCHFLOW_REWARD_LENIENT=1 bench eval run --tasks-dir example_tasks --agent oracle --sandbox docker --jobs-dir .local/bf-jobs-public-examples-oracle --context-root . --concurrency 1 --build-concurrency 1 -> 6/6, 100.0%

Notes

  • The checked-in auth signing key is an explicitly documented fake deterministic localhost test key for mock JWTs only.
  • Remaining private-only mock families after this PR are discord and stripe.

@bingran-you bingran-you merged commit 2ffbb50 into main Jul 4, 2026
9 checks passed
@bingran-you bingran-you deleted the bry/public-mock-auth-runtime branch July 4, 2026 20:38

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f09e5c4aba

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

):
client = _load_client(db, request, client_id)
redirect_uri = _check_redirect_uri(client, redirect_uri)
scopes = parse_scope(scope)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Revalidate callback scopes before issuing codes

For an authenticated web session, posting directly to this callback with a forged scope value bypasses the allowlist enforced only in GET /o/oauth2/v2/auth. The callback then stores that consent and issues an authorization code, and /oauth2/token exchanges the code without rechecking client.allowed_scope_list, so restricted clients can obtain scopes they are not registered for. Re-run the same allowed-scope validation before consent/code issuance.

Useful? React with 👍 / 👎.

Comment thread scripts/env0_control.py
HEALTH_PATH = "/health"
DEV_PATHS = ("/dev/dashboard", "/dev/db-viewer", "/dev/api-explorer")
TASK_DATA_SERVICES = {"mock-gmail", "mock-gcal", "mock-gdrive", "mock-gdoc", "mock-slack"}
TASK_SCENARIO_SERVICES = {"mock-auth"}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Enable auth for local auth task services

When scripts/dev.sh task auth-least-privilege-summary selects mock-auth plus mock-gmail, the launcher environment only contains the service URLs; it never sets AUTH_ENABLED, while Gmail installs the auth middleware only behind that flag. In local task/devhub sessions the Gmail API therefore stays unauthenticated, so agents can create drafts without bearer tokens and resource-side auth events are not produced. Set AUTH_ENABLED=1 when a task includes mock-auth with auth-enabled resource services.

Useful? React with 👍 / 👎.


def get_issuer() -> str:
"""Issuer string for JWTs and OIDC discovery (overridable via AUTH_ISSUER)."""
return os.environ.get("AUTH_ISSUER", f"http://localhost:{DEFAULT_PORT}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Derive the default issuer from AUTH_URL

In the repo launcher path, env_for_services() exports AUTH_URL=http://127.0.0.1:9000 to resource servers, and auth-client defaults its trusted issuer to that URL. Tokens issued here default iss to http://localhost:9000, so once AUTH_ENABLED is set for local auth tasks every bearer request to Gmail fails issuer validation even though both services are healthy. Default the issuer to AUTH_URL or have the launcher set AUTH_ISSUER consistently.

Useful? React with 👍 / 👎.

f"Expected iss={get_issuer()!r}.")

row = db.query(AccessToken).filter(AccessToken.token_hash == sha256_hex(token)).first()
if row is not None and row.revoked:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor server-side token expiry in bearer checks

When /_admin/expire_token moves AccessToken.expires_at into the past while the JWT exp is still in the future, /oauth2/v2/userinfo and /v1/myaccount/* still accept the token because this check only rejects revoked rows. The admin endpoint documents that server-side expiry is reflected by userinfo, and introspection already checks is_expired(row.expires_at), so bearer validation should reject expired rows too.

Useful? React with 👍 / 👎.

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.

1 participant