Skip to content

Hotfix: send a User-Agent on Zenodo token requests - #271

Merged
jodeleeuw merged 1 commit into
mainfrom
fix/zenodo-user-agent
Sep 21, 2026
Merged

jodeleeuw merged 1 commit into
mainfrom
fix/zenodo-user-agent

Conversation

@jodeleeuw

Copy link
Copy Markdown
Member

Connecting Zenodo fails on pipe.jspsych.org for every user. The researcher lands back on /oauth2/connect with "Could not connect your storage provider."

Cause

zenodo.org's firewall rejects the bare node User-Agent that Node's built-in fetch sends. It returns an HTML 403 ("Access to this resource has been restricted due to unusual traffic from your network") before the request reaches the OAuth endpoint. The prod dashboardapi logs show every /api/connectprovider call failing this way. sandbox.zenodo.org doesn't block that User-Agent, so the test site never showed the problem.

Reproduced locally: curl -A node https://zenodo.org/api/deposit/depositions gets the firewall page, while -A undici, -A node-fetch, or any DataPipe string gets Zenodo's normal JSON response.

Fix

The two Zenodo calls that use the built-in fetch now send User-Agent: DataPipe (+https://pipe.jspsych.org), defined in the new functions/src/user-agent.ts:

  • the authorization-code exchange in connect-provider.ts (broken now)
  • the refresh-token exchange in zenodo-oauth.ts (would break once 60-day tokens start expiring)

The upload path in zenodo.ts uses node-fetch, whose default User-Agent isn't blocked, so it's unchanged.

Testing

  • The exact header value reaches zenodo.org's token endpoint without hitting the firewall.
  • providers-zenodo, providers-zenodo-oauth, oauth-connect-emulator, and zenodo-emulator pass under emulators:exec (103 tests).

Goes straight to main as a hotfix; merge main back into test afterward.

🤖 Generated with Claude Code

zenodo.org's firewall rejects the bare "node" User-Agent that Node's
built-in fetch sends, returning an HTML 403 ("unusual traffic from your
network") before the request reaches the API. sandbox.zenodo.org does not,
so connecting Zenodo worked on the test site and fails in production.

The code exchange in connect-provider and the refresh in zenodo-oauth both
use the built-in fetch; set an explicit User-Agent on each. The upload path
in zenodo.ts uses node-fetch, whose default User-Agent is not blocked.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jodeleeuw
jodeleeuw merged commit 7b36858 into main Sep 21, 2026
1 check passed
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