Skip to content

v1 manifest: support sending the key as a query parameter (blocks Pushover) #5

Closed

Description

@stahnma

Problem

The v1 auth field can only put the key in a request header:

  • "bearer" sends Authorization: Bearer <key>
  • {"header": name, "prefix"?: text} sends <name>: [<prefix> ]<key>

(v1/schema.json $defs.auth; scripts/probe.mjs authHeader, which mirrors
Sprites.Gateway.Connector.auth_header/2.)

Some APIs accept credentials only as request parameters. Pushover
is one of them. Every endpoint takes the application token as a token
parameter, sent in the form-encoded body for POSTs and in the query string for
GETs. Pushover documents no header-based auth at all. So a Pushover connector
cannot be written in v1, and the only alternative is for the Sprite to hold the
token itself, which defeats the point of a connector.

Proposal

Add a parameter-based auth form alongside the header form, for example:

"auth": {"query": "token"}

The gateway would set token=<key> in the query string of every forwarded
request and of the probe.

Requirements:

  1. Override, don't append. The gateway removes any token parameter the
    Sprite supplied before it adds its own. Otherwise a Sprite could swap in a
    different key, or the API could receive the parameter twice and resolve the
    duplicate unpredictably.
  2. Redaction. The key now appears in the URL. Gateway request logs, error
    reports, and probe.mjs --write-fixture must redact the URL, not only
    headers. probe.mjs currently records the request URL without redaction.
  3. Probe and checker parity. Update authHeader/buildProbeRequest in
    scripts/probe.mjs and its tests to match the gateway's behaviour.

Query injection is enough for Pushover (verified)

Pushover documents token only as a body parameter for
POST /1/messages.json, but it also accepts the token in the query string.
This was tested on 2026-10-14 by calling Pushover directly, without the
gateway:

curl -s -X POST "https://api.pushover.net/1/messages.json?token=$PUSHOVER_TOKEN" \
  --data-urlencode "user=$PUSHOVER_USER" \
  --data-urlencode "message=sprites connector query-param test"
# {"status":1,"request":"e6d80a48-55b7-48d4-9c4f-c42eb069c5bf"}

The message was delivered. Body-parameter injection, which would mean
re-encoding form and JSON bodies and recomputing content-length, is not
needed for this connector. Because the query-string behaviour is undocumented,
the connector should note that it relies on it.

A second fixed parameter (out of scope, noted for completeness)

Pushover's POST /1/messages.json also requires a user key, which is a
second secret identifying the recipient. CONTRIBUTING.md rules out "any secret
beyond the key", so even with parameter auth the Sprite would pass user
itself. That is acceptable for Pushover, because the user key cannot send
messages without an app token. I am not proposing a second injected secret
here.

Pushover connector this would unblock

  • base_url: https://api.pushover.net
  • Probe: GET /1/apps/limits.json. It validates the token, has no side
    effects, and returns {"limit":10000,"remaining":…,"reset":…,"status":1}.
  • Routes: POST /1/messages.json, POST /1/users/validate.json,
    GET /1/apps/limits.json, GET /1/receipts/{receipt}.json. The receipts route works today as pattern
    /1/receipts/:receipt with "path_param": "\\A[A-Za-z0-9]+\\.json\\z"
    (checked against scripts/lib/routes.mjs). It does not match
    /1/receipts/X.json/cancel.json, so canceling receipts stays excluded. Routes for
    groups, teams, subscriptions, licensing, glances, and the Open Client API are
    excluded.
  • Operational notes for users: the message limit is 1,024 characters. Each
    account gets 10,000 messages per month, and Pushover returns 429 when they
    run out. Pushover temporarily blocks IPs that send repeated 4xx requests,
    and all connector traffic comes from the shared gateway IP, so one
    misbehaving Sprite could block every Pushover user of the gateway. That
    shared-IP risk should be weighed when reviewing this connector, separately
    from the schema change.

Activity

  1. changed the title [-]v1 manifest: support sending the key as a query or body parameter (blocks Pushover)[/-] [+]v1 manifest: support sending the key as a query parameter (blocks Pushover)[/+] on Oct 14, 2026
  2. aezell commented on Oct 15, 2026

    @aezell
    Collaborator

    Thanks for this report. We can definitely support auth like this for community connectors. I'm working on it now!

  3. aezell commented on Oct 15, 2026

    @aezell
    Collaborator

    From this repository's side: the manifest format now accepts "auth": {"query": "token"} (#6), pending the gateway release that understands it (superfly/sprites-api#1574). Both requirements hold as specified here: the gateway and scripts/probe.mjs replace every parameter of that name the caller sent rather than appending, and the key, raw and URL-encoded, is redacted from everything the probe runner prints or records, including bodies and headers that echo the request URL. The contributor guide now describes the form, asks query-auth connectors to say in a notice that the key travels in the URL, and asks those whose API echoes request URLs in error bodies to set gateway_error_messages to false. The shared-IP concern for Pushover is a property of that connector rather than of the format; it will be weighed when the Pushover connector PR is reviewed.

  4. added a commit that references this issue on Oct 15, 2026
  5. aezell commented on Oct 15, 2026

    @aezell
    Collaborator

    @stahnma I've added support for query parameter auth. If you could try the Pushover connector PR again and let me know how it goes, I'd appreciate it. Thanks again!

  6. stahnma commented on Oct 16, 2026

    @stahnma
    ContributorAuthor

    Thanks @aezell, query auth works for Pushover. The connector is up in #7.

    • "auth": {"query": "token"} with scripts/probe.mjs: the probe passes with a real application token, and a wrong token is classified as invalid_api_key (fixtures for both are in the PR).
    • Pushover's 400 body doesn't echo the request URL or token, so the connector leaves gateway_error_messages at its default.
    • Sending to POST /1/messages.json with the token in the query string worked with both form-encoded and JSON bodies, tested directly against Pushover.

    I haven't tested through the gateway itself, since that depends on superfly/sprites-api#1574 being released. The shared-IP question from this issue is listed for review in #7.


    Posted by Claude Code on behalf of @stahnma.

  7. added a commit that references this issue on Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions