Authenticate to the Certora cloud without a browser - #166
Draft
shellygr wants to merge 2 commits into
Draft
Conversation
A headless run that needed to refresh its cloud session spent five minutes
waiting for a login nobody could complete:
AuthenticationError: PKCE login deadline of 300.0s expired before a
callback completed.
`certora_login.login` completes a missing or stale session with the PKCE browser
flow. In a container that cannot succeed: the link is never opened and the
callback server waits out its deadline. `CERTORA_LOGIN_NO_BROWSER`, which the
compose file already set, only suppresses the `webbrowser.open` call -- the wait
is unaffected.
`login` takes `no_pkce`, which removes only the fallback: credentials are still
read and refreshed, and an unusable session raises instead of waiting. New
`composer/prover/auth.py` sets it and turns the failure into a message naming the
command a human has to run, since no amount of retrying fixes an expired token.
It is applied as an environment default rather than an argument because
`ProverOutputAPI` logs in on its own -- its constructor authenticates, and it
authenticates again after a 401 -- and neither call is ours to pass arguments to.
`setdefault` leaves an operator who exports `CERTORA_LOGIN_NO_PKCE=0` in charge,
so a host run can still use the browser. The compose service sets it too, for
subprocesses that never import composer.
Both construction sites now go through the factory, and the cloud path refreshes
before submitting a job rather than after it has run, so a dead session costs no
prover time.
Verified in the container against real credentials: refresh succeeds in 2.2s;
with no credentials present it fails in 0.3s with the hint.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ProverOutputUtility deliberately does not log in under CI. `get_auth_cookies`
returns an empty jar (`if os.getenv("CI"): return cookies`) and `ProverOutputAPI`
authenticates to Lambda with SigV4 instead of cookies. The nightly integration
job matches that shape exactly: AWS OIDC credentials and CERTORAKEY, no
CERTORA_USER/TOKEN/REFRESH_TOKEN and no ~/.certora/credentials.json.
So the eager login added in the previous commit would have failed that job at the
gate -- `get_credentials()` finds nothing, NO_PKCE removes the fallback, and
`login` raises -- before a prover job was ever submitted, in a run that
previously fetched its results through AWS and never touched certora_login.
`test_autoprove_integration.py` runs with cloud=True, so the nightly would have
broken while the fast suite stayed green.
Mirror the precondition instead: no-op under CI. Where AWS credentials are
absent, the run fails later on empty cookies exactly as it did before.
The test fixture now clears CI too. GitHub Actions sets it for the fast suite as
well, and without that every login assertion in this file would quietly become a
no-op that passes while testing nothing.
Found by adversarial review of the previous commit; it was the one finding of
seventeen that survived refutation.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #155 → #148. Retarget to
masteras those merge.Problem
A headless run that needed to refresh its cloud session spent five minutes waiting for a login nobody could complete, then failed:
certora_login.logincompletes a missing or stale session with the PKCE browser flow. In a container that can never succeed — the link is never opened and the callback server waits out its deadline.CERTORA_LOGIN_NO_BROWSER, which the compose file already set, only suppresses thewebbrowser.opencall; the wait is unaffected.Fix
logintakesno_pkce, which removes only the fallback — the refresh path is untouched:New
composer/prover/auth.pyexposesensure_prover_login()and aprover_output_api()factory — the same shape PreAudit uses (prover_api_factory.py) — and turns a failure into a message naming the command a human has to run, since retrying never fixes an expired token.It is applied as an environment default rather than an argument because
ProverOutputAPIlogs in on its own: its constructor authenticates, and it authenticates again after a 401. Neither call is ours to pass arguments to, and both read the same variable.setdefaultleaves an operator who exportsCERTORA_LOGIN_NO_PKCE=0in charge, so a host run can still use the browser.Both construction sites go through the factory —
composer/prover/cloud.pyandcomposer/spec/source/report_prover.py, the latter of which would have hung independently — and the cloud path inrun_proverrefreshes before submitting, so a dead session costs no prover minutes. The compose service sets the variable too, for subprocesses that never import composer.CI is deliberately exempt. ProverOutputUtility does not log in there —
get_auth_cookiesreturns an empty jar underCIand the API uses AWS SigV4 instead — and the nightly integration job has AWS OIDC credentials with no credentials file.ensure_prover_loginmirrors that precondition rather than insisting on a login that would never have happened.Verification
In the container, against real credentials:
run 'certora-cloud login' on the hosttests/test_prover_auth.py— 6 tests: refresh-only, operator override, CI no-op, once-per-process, message content, login-before-construct. Green both normally and withCI=true(the fixture clearsCI, or every assertion here would silently pass under GitHub Actions while testing nothing).The second commit fixes a regression the first one introduced; it was the one finding of seventeen that survived adversarial review.