Skip to content

fix(mpp): reject empty required auth-params when formatting challenges - #120

Closed
memosr wants to merge 1 commit into
tempoxyz:mainfrom
memosr:fix/reject-empty-required-auth-params
Closed

memosr wants to merge 1 commit into
tempoxyz:mainfrom
memosr:fix/reject-empty-required-auth-params

Conversation

@memosr

@memosr memosr commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

formatAuthenticate omits any auth-param whose value is empty. That includes the required id, realm, method and intent fields, so FormatAuthenticateStrict returns no error while emitting a WWW-Authenticate value that this SDK's own ParseChallenge rejects with missing required challenge fields.

The conformance suite already expects this to fail:

// mpp-tools conformance/vectors/www-authenticate.json
"name": "error_empty_id_format",
"object": { "id": "", ... },
"tests": { "format": { "success": false, "error_type": "format_error" } }

and the Go adapter passes that vector only because it carries a manual guard immediately before calling into the SDK:

// mpp-tools conformance/adapters/go/main.go:158
if challenge.ID == "" {
    printJSON(commandResponse{Success: false, Error: "id must not be empty", ErrorType: "format_error"})
    return
}
header, err := challenge.ToAuthenticateStrict(challenge.Realm)

That guard becomes unnecessary once the SDK enforces it.

FormatAuthenticate returns only a string, so its callers cannot observe an error; the lenient path is deliberately unchanged. Optional params (digest, expires, description, opaque) keep being dropped when empty.

One caveat worth naming: protocol.schema.json sets minLength: 1 on id, method and intent but not on realm, so an empty realm is not a schema violation. It is still treated as required here because ParseChallenge rejects a challenge without one. server.New accepts an empty realm today, and such a server previously emitted 402s this SDK could not parse; it now surfaces the misconfiguration as a 400 problem document.

Reverting the check fails the four new TestFormatAuthenticateStrictRejectsEmptyRequiredAuthParams subtests; the "behaviour unchanged" tests pass either way.

formatAuthenticate omitted any auth-param whose value was empty, including the required id, realm, method, intent and request fields. FormatAuthenticateStrict therefore returned no error while emitting a WWW-Authenticate header that this SDK's own ParseChallenge rejects.

The strict path now fails with "mpp: missing required <name> auth-param". The lenient FormatAuthenticate returns only a string, so its callers cannot observe an error; its behaviour is deliberately unchanged.

Copy link
Copy Markdown
Contributor

Thanks for this! We've carried your change forward in #240. It's rebased onto current main, includes the follow-ups from review, and credits this PR. Closing this one in favor of it.

brendanjryan added a commit that referenced this pull request Oct 25, 2026
…s strictly (#240)

Supersedes #120 by @memosr (thanks!), rebased onto current main.

`formatAuthenticate` drops empty values, including the required `id`,
`realm`, `method` and `intent`, so `FormatAuthenticateStrict` returned
no error for a header that `ParseChallenge` rejects with missing
required fields. The conformance vector `error_empty_id_format` expects
a format error. Strict formatting now rejects empty required params; the
lenient `FormatAuthenticate` is unchanged.

- Rebased onto main's opaque handling (`wireOpaque`).

Checks: gofmt -l, go vet ./..., go build ./... ./examples/..., go test
-race ./..., plus the regression tests run against main (fail) and with
the fix (pass).

Co-authored-by: memosr <mehmet.sr35@gmail.com>
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