Skip to content

[Bug Fix] Fix inverted validation guards and wire-format mismatches in OAuthTypes#3

Draft
systemblueio wants to merge 4 commits into
ATProtoKit:mainfrom
systemblueio:fix/oauth-types-validation
Draft

[Bug Fix] Fix inverted validation guards and wire-format mismatches in OAuthTypes#3
systemblueio wants to merge 4 commits into
ATProtoKit:mainfrom
systemblueio:fix/oauth-types-validation

Conversation

@systemblueio

@systemblueio systemblueio commented Jun 16, 2026

Copy link
Copy Markdown

Why

OAuthTypes had several validators with inverted guard logic (rejecting valid production input or accepting invalid input) and a few Codable types that did not match the @atproto/oauth-types wire format. This corrects them against the TypeScript reference and adds an OAuthTypes test suite.

This is the validator-fix work from #1 (which was closed unmerged). It lands first, as the base for the OAuthTypes completion tracked in #2. The four commits group the changes (typos, validators, wire formats, tests), with per-item detail in each commit body.

The renamed error cases and the expiresIn/tokenTypeHint changes are source-breaking. Happy to add deprecated aliases instead if you would rather not break at 0.0.x.

References

  • Tracking issue: Implementing the ATOAuthKit client #2
  • Reference: @atproto/oauth-types@0.7.x (uri.ts, oauth-client-id-discoverable.ts, oauth-issuer-identifier.ts, oauth-redirect-uri.ts, and the response and metadata schemas)

Verification

swift build clean and swift test green: 56 tests across 9 suites (Swift Testing), each fix pinned by a test that fails on the previous code. Behavior was matched module by module against @atproto/oauth-types.

systemblueio and others added 4 commits June 4, 2026 21:41
Renames OAuthClientRredentials.swift to OAuthClientCredentials.swift,
corrects the Constants.swift file header, and fixes doc-comment
spelling in OAuthScope.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Several validators had inverted guard logic or checked the full URI
string where the parsed hostname was required, so valid production
input was rejected and invalid input accepted:

- validateHTTPSURI required a loopback host (the spec rejects loopback
  for https) and never parsed the hostname before checking it.
- ClientIDDiscoverable rejected URLs without embedded credentials and
  accepted URLs with them; bare hosts, trailing-slash paths, and
  uncanonical paths (/a/../) also validated.
- ConventionalOAuthClientID rejected IDs without a port or query and
  accepted IDs with them; it now also runs the discoverable validation
  first, matching the schema intersection in the reference.
- IssuerIdentifier rejected clean canonical issuers and accepted
  query/fragment, credentialed, mixed-case-host, and explicit
  default-port URLs; the port also rendered as Optional(...) in the
  canonical comparison.
- LoopbackRedirectURI and OAuthLoopbackRedirectURI checked the full
  URI string for loopback, so valid loopback URIs always threw, and
  OAuthLoopbackRedirectURI accepted any non-localhost string.
- Bracketed IPv6 hostnames ([::1]) are now recognized as IP addresses.

Also renames the misspelled error cases invalidURL,
issuerURLEndsWithSlash, and lessThanTwoSegmentsInURI.

All behavior is matched against the @atproto/oauth-types TypeScript
schemas.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Aligns the JSON encoding of several types with the wire format the
@atproto/oauth-types schemas define:

- TokenResponse.expiresIn decoded expires_in (a lifetime in seconds)
  as a Date; it is now an Int.
- AuthorizationDetail.dataTypes now maps to the wire key datatypes.
- OpenIDConnectClaimsParameter.timeZone raw value corrected from
  zoneInfo to the standard zoneinfo claim.
- TokenIdentification.tokenTypeHint is now optional and maps to
  token_type_hint, matching the schema.
- AuthorizationServerMetadata defaults
  token_endpoint_auth_methods_supported to ["client_secret_basic"]
  only when the key is absent; an explicit null fails to decode and
  the previous [""] sentinel is gone.
- ProtectedResourceMetadata validated the resource for query and
  fragment characters only in release builds; the checks now always
  run.
- OAuthPARResponse rejects a non-positive expires_in instead of
  coercing it with abs(), and decodes the request_uri and expires_in
  keys it previously missed.
- OAuthTokenType decodes case-insensitively (DPoP, dpop, Bearer,
  bearer) and encodes the canonical casing, matching the
  case-insensitive schema regex.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds URIValidationTests, ClientIdentifierTests, and WireFormatTests
(56 tests across 9 suites, Swift Testing) covering each validator and
Codable fix with vectors derived from the @atproto/oauth-types
schemas, and wires OAuthTypes into the test target.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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.

1 participant