Skip to content

feat!: require explicit AuthorizationResponseIssPolicy - #358

Merged
osanderson merged 2 commits into
mainfrom
feat/authz-response-iss-policy
Sep 19, 2026
Merged

osanderson merged 2 commits into
mainfrom
feat/authz-response-iss-policy

Conversation

@osanderson

Copy link
Copy Markdown
Collaborator

Summary

From a cross-project security rubric review (constructor-time validation, boolean security toggles, extension-point interfaces, fail-open/fail-closed, algorithm agility, type-system enforcement, TLS defaults): FAPIgo's one gap under "boolean security toggles" was client.Config.RequireAuthorizationResponseIss, an optional bool defaulting to false — the weaker RFC 9207 posture. NewFromDiscovery correctly raises it to true when discovery confirms support, but a caller building Config by hand gets the silent-weak default with no signal to look at this field at all — there's no way to distinguish "explicitly chose to tolerate a missing iss" from "never thought about it".

Replaces the bool with a closed AuthorizationResponseIssPolicy enum, zero value deliberately invalid — same shape as PARDPoPBinding, except PARDPoPBinding's zero value is a real, safe default (RFC 9449 itself recommends it) while this field has no universally-safe default: RequireAuthorizationResponseIss breaks every AS that doesn't send iss, TolerateAbsentAuthorizationResponseIss is the weaker posture. New now rejects an unset value the same way it already rejects an invalid Profile or PARDPoPBinding. NewFromDiscovery's own "only ever raises the bar, never lowers what the caller set" semantics are unchanged.

BREAKING CHANGE

client.Config.RequireAuthorizationResponseIss (bool) is renamed to AuthorizationResponseIssPolicy (AuthorizationResponseIssPolicy) and is now required. Existing callers must set it explicitly: RequireAuthorizationResponseIss (matches former true) or TolerateAbsentAuthorizationResponseIss (matches former false/zero value).

Test plan

  • gofmt -l . clean
  • go build ./...
  • go vet ./...
  • go test -race ./... — all packages pass
  • golangci-lint run ./... — 0 issues
  • Extended TestNewRejectsInvalidConfig with both an out-of-range and a zero-value case for the new enum
  • All 3 existing NewFromDiscovery iss-enforcement tests (enable-when-advertised, leave-off-when-not-advertised, never-disable-explicit-enforcement) still pass under the new type

🤖 Generated with Claude Code

https://claude.ai/code/session_01JCpqoxEg7XUkkGg312zXyS

client.Config.RequireAuthorizationResponseIss was an optional bool
defaulting to false — the weaker RFC 9207 posture (tolerate a callback
missing "iss"). NewFromDiscovery correctly raises it to true when
discovery confirms the issuer supports the parameter, but a caller
building Config by hand (never calling NewFromDiscovery) gets the
silent-weak default with no signal they should have looked at this
field at all: there's no way to tell "explicitly chose to tolerate a
missing iss" from "never thought about it".

Replace the bool with a closed AuthorizationResponseIssPolicy enum,
zero value deliberately invalid — the same shape as PARDPoPBinding,
except PARDPoPBinding's zero value is a real, safe default (RFC 9449
itself recommends it) while this field has no universally-safe
default: "require" breaks every AS that doesn't send iss, "tolerate"
is the weaker posture. New now rejects an unset value the same way it
already rejects an invalid Profile or PARDPoPBinding.
NewFromDiscovery's own "only ever raises the bar, never lowers what
the caller set" semantics are unchanged.

BREAKING CHANGE: client.Config.RequireAuthorizationResponseIss (bool)
is renamed to AuthorizationResponseIssPolicy
(AuthorizationResponseIssPolicy) and is now required. Existing callers
must set it explicitly: RequireAuthorizationResponseIss (matches
former true) or TolerateAbsentAuthorizationResponseIss (matches former
false/zero value).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@osanderson
osanderson merged commit a9ab435 into main Sep 19, 2026
7 of 8 checks passed
@osanderson
osanderson deleted the feat/authz-response-iss-policy branch September 19, 2026 06:49
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