Skip to content

Servant oauth extraction#2

Closed
albertov wants to merge 121 commits intomasterfrom
005-servant-oauth-extraction
Closed

Servant oauth extraction#2
albertov wants to merge 121 commits intomasterfrom
005-servant-oauth-extraction

Conversation

@albertov
Copy link

@albertov albertov commented Dec 19, 2025

Refactors Servant.OAuth2.IDP.* modules to have zero imports from MCP.* namespace, preparing them for extraction to a standalone package.

Changes

New modules:

  • Servant.OAuth2.IDP.Config - OAuthEnv record for protocol configuration
  • Servant.OAuth2.IDP.Metadata - RFC 8414/9728 metadata types
  • Servant.OAuth2.IDP.PKCE - PKCE functions (moved from MCP.Server.Auth)
  • Servant.OAuth2.IDP.Errors - Consolidated error types with ADT payloads
  • Servant.OAuth2.IDP.Trace - OAuthTrace ADT for structured tracing

Removed:

  • MCP.Trace.OAuth (moved to Servant)
  • Servant.OAuth2.IDP.LoginFlowError (consolidated into Errors)
  • Servant.OAuth2.IDP.Types.Internal (merged into Types)

Split OAuthConfig into:

  • OAuthEnv (protocol settings) - lives in Servant
  • MCPOAuthConfig (demo/MCP-specific) - stays in MCP

Other fixes:

  • Constant-time PKCE validation
  • Smart constructor exports (no raw constructor leakage)
  • Generator functions return domain types instead of Text

Add comprehensive planning documentation for removing MCP imports
from Servant.OAuth2.IDP modules to prepare for package extraction:

- spec.md: Feature requirements (FR-001 through FR-008)
- plan.md: Implementation phases and file-by-file changes
- research.md: Dependency analysis and extraction strategy
- data-model.md: Type definitions for OAuthEnv and OAuthTrace
- module-dependencies.md: Import graph and breaking changes
- quickstart.md: Developer guide for implementation

Also updates .beads/issues.jsonl with tracking and CLAUDE.md with
technology choices for the feature.
…th phased tasks

Restructure epic mcp-5wk with clearer phase organization:
- Phase A: Create new Servant modules (Trace, Config, Metadata, PKCE)
- Phase B: Update Servant handlers to use new modules
- Phase C: Update MCP integration layer (AppEnv, adapters)
- Phase D: Clean break (remove old code, verify no MCP imports)

Close superseded tasks (mcp-5wk.1-22) and create reorganized
tasks (mcp-5wk.23-48) with explicit dependencies and parallel
execution opportunities where possible.
Change OAuthErrorResponse.oauthErrorCode from Text to OAuthErrorCode
ADT for type-safe error handling. Update authorizationErrorToResponse
to use constructors instead of string literals, enabling exhaustiveness
checking at compile time.

Additional fixes:
- Add RecordWildCards language extension
- Add FromJSON instance for OAuthErrorCode
- Add missing validationErrorToResponse test cases
- Update test assertions to use OAuthErrorCode constructors
Add Servant.OAuth2.IDP.Errors module to library exports
and ErrorsSpec to test suite configuration.
Create Servant.OAuth2.IDP.Metadata module with OAuth discovery types:
- OAuthMetadata: RFC 8414 Authorization Server Metadata
- ProtectedResourceMetadata: RFC 9728 Protected Resource Metadata

Both types use custom JSON instances with snake_case field names
per RFC specifications. Field name prefixing (pr*) used in
ProtectedResourceMetadata to avoid conflicts with OAuthMetadata.

Includes comprehensive test coverage for JSON serialization,
deserialization, and round-trip verification.
Hide OAuthMetadata and ProtectedResourceMetadata type constructors
to prevent bypassing validation. Add field accessor functions for
reading values after construction.

Implement RFC-mandated HTTPS URI validation:
- Reject non-HTTPS URIs (HTTP, relative paths)
- Validate all required and optional URI fields
- Return Nothing from smart constructors on validation failure

Update all tests to use smart constructors with proper error handling.
Add comprehensive validation test coverage for invalid URI inputs.

Fixes smart constructor hygiene violation (Constitution Principle II).
Add 4 missing validation tests for ProtectedResourceMetadata smart
constructor to match coverage level of OAuthMetadata (6 tests).

Tests verify:
- Rejection of non-HTTPS resource URI
- Rejection of relative resource URI
- Rejection of non-HTTPS documentation URI when provided
- Acceptance of valid HTTPS URIs

Increases test count from 452 to 456 examples.
Track completion of Metadata module implementation and add
universal ignore patterns for environment files and IDE configs.
Create Servant.OAuth2.IDP.PKCE module with PKCE functions moved from
MCP.Server.Auth, using domain newtypes from Servant.OAuth2.IDP.Types.

Implements:
- generateCodeVerifier: cryptographically secure verifier generation
- generateCodeChallenge: SHA256-based challenge computation (S256)
- validateCodeVerifier: constant-time challenge validation

All functions use domain newtypes (CodeVerifier, CodeChallenge) for
type safety. Implementation follows RFC 7636 with 256-bit entropy
requirement and base64url encoding.

Includes comprehensive test suite with:
- Code verifier generation validation (charset, length, uniqueness)
- Challenge computation properties (deterministic, unique per verifier)
- Round-trip validation property tests
- RFC 7636 Appendix B test vectors

Tests follow TDD: written first, verified to fail (RED), then
implementation added to pass (GREEN), formatted with fourmolu.

Part of FR-003 (P0 Critical) from spec 005-servant-oauth-extraction.
Fixed code review violations (mcp-5wk.27) by removing raw constructor
exports and updating all usages to smart constructors and accessors.

Changes:
- PKCE.hs: Use mkCodeVerifier/mkCodeChallenge and un* accessors
- MCP/Server/Auth.hs: Use accessors in validateCodeVerifier
- Test files: Use smart constructors instead of raw construction
- Types.hs: Added TODO for full Internal module refactor

All tests passing (466 examples, 0 failures).

Per Constitution Principle II (Constructor Hygiene): Raw constructors
must not be exported. Smart constructors enforce validation at
construction time, making illegal states unrepresentable.
Remove raw constructor exports for CodeVerifier and CodeChallenge
from public API per Constitution Principle II.

Changes:
- Create Servant.OAuth2.IDP.Types.Internal module for raw constructors
- Move PKCE type definitions and FromHttpApiData instances to Internal
- Update Types.hs to import from Internal and export only:
  - Type names (CodeChallenge, CodeVerifier)
  - Smart constructors (mkCodeChallenge, mkCodeVerifier)
  - Accessors (unCodeChallenge, unCodeVerifier)
- Update Boundary.hs to import raw constructors from Internal
- Remove unused raw constructor imports from Token.hs and Auth.hs
- Register Types.Internal in mcp.cabal other-modules

Verification:
- All 466 tests passing
- No raw constructor exports in public API
- cabal build successful
Add comprehensive test coverage for OAuthGrantType enum before moving
it from MCP.Server.Auth to Servant.OAuth2.IDP.Types (FR-002b).

Tests verify:
- JSON serialization/deserialization for both constructors
- Equality semantics between AuthorizationCode and ClientCredentials
- Readable Show output for debugging

This is the RED phase of TDD - tests intentionally fail until the
type is moved in the next commit.
Move OAuthGrantType enum from MCP.Server.Auth to Servant.OAuth2.IDP.Types
module as part of OAuth extraction refactoring (FR-002b).

Changes:
- Add OAuthGrantType with prefixed constructors to avoid name collision
  with existing AuthorizationCode type (domain entity)
- Constructors: OAuthAuthorizationCode, OAuthClientCredentials
- Include full JSON serialization instances (RFC 6749 format)
- Update MCP.Server.Auth to import and re-export for compatibility
- Update test imports and example usage

All 473 tests pass including 7 new OAuthGrantType tests.
Add comprehensive tests for the MCPOAuthConfig type which will hold
MCP-specific demo configuration fields extracted from OAuthConfig.

Tests verify all four required fields:
- autoApproveAuth (demo mode auto-approval flag)
- demoUserIdTemplate (template for generating demo user IDs)
- demoEmailDomain (domain suffix for demo user emails)
- authorizationSuccessTemplate (HTML template for success page)

This is an intentional failing test following TDD red-green-refactor.
The MCPOAuthConfig type does not exist yet and will be implemented
in the next commit.
Add MCPOAuthConfig data type to hold MCP-specific demo configuration
fields that will be extracted from OAuthConfig in later refactoring.

Fields (with mcp prefix to avoid DuplicateRecordFields ambiguity):
- mcpAutoApproveAuth: Demo mode auto-approval flag
- mcpDemoUserIdTemplate: Template for generating demo user IDs
- mcpDemoEmailDomain: Domain suffix for demo user emails
- mcpAuthorizationSuccessTemplate: HTML template for success page

All tests passing (477 examples, 0 failures).
Update imports in 6 files from Servant.OAuth2.IDP.LoginFlowError to
Servant.OAuth2.IDP.Errors following consolidation in FR-004b.

Files updated:
- src/Servant/OAuth2/IDP/Boundary.hs
- src/Servant/OAuth2/IDP/Server.hs
- src/Servant/OAuth2/IDP/Handlers/Login.hs
- src/MCP/Server/HTTP.hs
- src/MCP/Server/HTTP/AppEnv.hs
- test/Servant/OAuth2/IDP/LucidRenderingSpec.hs

Library builds successfully. Pre-existing test failures from mcp-5wk.43
are unrelated to this import refactoring.
Update bead status after completing work:
- mcp-5wk.28: OAuthGrantType migration completed
- mcp-5wk.49: Spec clarification resolved
- mcp-5wk.51: LoginFlowError imports updated
- mcp-5wk.45: Reset to open (imports done, deletion pending)
Resolve field name collision between MCPOAuthConfig and OAuthConfig by
removing OAuthConfig entirely:

- OAuthConfig → REMOVED (split into OAuthEnv + MCPOAuthConfig)
- Protocol fields → OAuthEnv (Servant.OAuth2.IDP.Config)
- Demo/MCP fields → MCPOAuthConfig (unprefixed field names)
- Add oauthRequireHTTPS to OAuthEnv
- Add DemoOAuthBundle for test migration convenience

Closes mcp-5wk.50, unblocks mcp-5wk.43
12 new tasks under mcp-5wk epic:
- E.1 (mcp-5wk.52): Update MCPOAuthConfig fields
- E.2 (mcp-5wk.53): Remove OAuthConfig type
- E.3 (mcp-5wk.54): Update HTTPServerConfig
- E.4 (mcp-5wk.55): Create DemoOAuthBundle
- E.5.1-4 (mcp-5wk.56-59): Update tests
- E.6.1-3 (mcp-5wk.60-62): Update examples/docs
- E.7 (mcp-5wk.63): Verification

Closes mcp-5wk.43 (superseded by mcp-5wk.52)
Update description to reflect resolved blocker (mcp-5wk.49).
Task now ready for implementation of LoginAction and TokenValidity types.
Add domain types for type precision improvements:

- LoginAction ADT (ActionApprove | ActionDeny) with HttpApiData instances
- TokenValidity newtype with ToJSON outputting integer seconds
- Update LoginForm.formAction to use LoginAction
- Update TokenResponse.expires_in to use Maybe TokenValidity
- Smart constructor hygiene: TokenValidity exports mkTokenValidity only

Includes 12 new test cases for the type behavior.
Add Servant.OAuth2.IDP.Trace module with:
- OperationResult ADT (Success | Failure) for type-safe boolean
- DenialReason ADT for authorization denial reasons
- OAuthTrace ADT with 11 trace constructors using domain newtypes:
  TraceClientRegistration, TraceAuthorizationRequest, TraceLoginPageServed,
  TraceLoginAttempt, TracePKCEValidation, TraceAuthorizationGranted,
  TraceAuthorizationDenied, TraceTokenExchange, TraceTokenRefresh,
  TraceSessionExpired, TraceValidationError

Includes comprehensive test coverage (32 test cases).
Create Servant.OAuth2.IDP.Config module with OAuthEnv record
for protocol-agnostic OAuth configuration. Fields include base URL,
expiry durations, prefixes, and supported OAuth capabilities.

Implementation:
- Uses URI from Network.URI for base URL
- NonEmpty lists for RFC-required fields (response types, grant types,
  auth methods, code challenge methods)
- Regular list for optional scopes
- Follows TDD: tests written first, watched fail, then implementation

Tests:
- Construction with all required fields
- Empty scope list support
- Multiple values for NonEmpty fields
- All 6 tests passing
Module was consolidated into Servant.OAuth2.IDP.Errors as part of
the OAuth extraction refactoring. All other new modules (Trace,
Config, Metadata, PKCE, Errors) already present.
Replace MCP.Server.Time import with Control.Monad.Time for MonadTime
typeclass. Update OAuthState record to use domain type keys (AuthCodeId,
AccessTokenId, RefreshTokenId, ClientId, SessionId) instead of Text,
eliminating all unXxx unwrapping calls.

This improves type safety and prepares Servant.OAuth2.IDP modules for
extraction to a separate package by removing MCP dependencies.
Update Test/Internal.hs for FR-001:
- Use Control.Monad.Time instead of MCP.Server.Time for MonadTime
- Fix module doc comment to match actual module path

Part of 005-servant-oauth-extraction: removing MCP.* dependencies.
Add Phase F to plan.md with 6 tasks:
- F.1-F.2: Smart constructor hygiene (9 types export raw constructors
  despite having validation)
- F.3: AuthorizationError ADT payloads (replace Text with precise ADTs)
- F.4: Token handler signatures (eliminate Map Text Text anti-pattern)
- F.5: Record field types (ClientInfo.clientName -> ClientName)
- F.6: Verification step

Update spec.md with design decisions:
- Identified 9 types violating smart constructor hygiene (3 critical:
  RedirectUri, SessionId, Scope bypass security validation)
- AuthorizationError ADT payloads for exhaustive pattern matching
- Token handler signature changes to pass typed fields directly

Create beads mcp-5wk.64-68 for Phase F implementation tracking.
…rization.hs

Update Authorization.hs handler to use protocol-agnostic imports:
- Replace MCP.Server.Time with Control.Monad.Time
- Replace HTTPServerConfig constraint with OAuthEnv
- Replace HTTPTrace with OAuthTrace
- Import ValidationError from Errors module

Add OAuthEnv and OAuthTracer to AppEnv composite type, enabling
handlers to access OAuth configuration without MCP dependencies.
Export mkOAuthEnvFromConfig helper for test fixtures.

Fix AuthorizationError response to use correct HTTP status code
(was hardcoded 400, now uses actual status from error type).

Move duplicate error types from Types.hs to Errors module.
Disable ErrorBoundarySecuritySpec tests pending migration work.
- Remove 10 unsafe* constructor functions from Types.hs exports
- Delete unsafe* function implementations (unsafeAuthCodeId, unsafeClientId,
  unsafeSessionId, unsafeAccessTokenId, unsafeRefreshTokenId, unsafeUserId,
  unsafeRedirectUri, unsafeScope, unsafeClientName, unsafeClientSecret)
- Remove -Wno-orphans from Backend.hs and Demo.hs (no longer needed)

All code now uses smart constructors (mk*) for type construction,
enforcing validation at type boundaries with no bypass mechanism.

Closes mcp-5wk.96.5
- Move generateJWTAccessToken to Token.hs
- Inline extractSessionFromCookie in Login.hs
- Inline generateAuthCode wrapper as generateAuthCodeId call
- Inline generateRefreshTokenWithConfig as generateRefreshTokenId call
- Remove Helpers module from cabal and re-exports
- Delete HelpersSpec.hs (tests for deleted module)
- Add GOLDEN RULE section documenting smart constructor hygiene
- Mark Boundary.hs, Helpers.hs, OAuth.hs as DELETED in project tree
- Add QuickCheck >= 2.14 to library dependencies listing
Verified completion of all 11 child tasks:
- Boundary.hs deleted
- Helpers.hs deleted
- test/Generators.hs deleted
- All unsafe* exports removed from Types.hs
- 504 tests passing, hlint clean
Add OAuthError m sum type that consolidates all OAuth error types:
- OAuthValidation for semantic validation failures
- OAuthAuthorization for OAuth protocol errors
- OAuthLoginFlow for login flow failures
- OAuthStore for storage backend errors (parameterized)

Enables single point of error-to-ServerError conversion with
exhaustive pattern matching per spec FR-004b.

Tests verify all four constructors can be created and pattern
matching correctly distinguishes between error types using
the in-memory store implementation.
RED: All 9 tests fail on stub implementation

Add comprehensive test coverage for OAuthError to ServerError conversion:
- OAuthValidation → 400 with plain text body
- OAuthAuthorization → 400/401/403 with JSON OAuth response
- OAuthLoginFlow → 400 with HTML error page
- OAuthStore → 500 with generic message (no backend leakage)

Tests verify proper HTTP status codes, response bodies, and Content-Type
headers for each error variant. Security-critical: OAuthStore tests ensure
backend error details are NOT leaked to clients.

Function stub added with type signature, will implement next.
GREEN: All 9 tests passing

Implement OAuthError to ServerError conversion with proper HTTP mappings:
- OAuthValidation → 400 Bad Request with plain text body
- OAuthAuthorization → 400/401/403 with JSON OAuth error response (RFC 6749)
- OAuthLoginFlow → 400 with HTML error page (via ToHtml instance)
- OAuthStore → 500 Internal Server Error with generic message

Security features:
- Storage backend errors never leak implementation details to clients
- Generic "Internal Server Error" message for all OAuthStore errors
- Proper Content-Type headers for each response format

Implementation uses local helper functions for clean separation:
- toServerErrorPlain: plain text responses
- toServerErrorOAuth: JSON OAuth responses
- toServerErrorLoginFlow: HTML error pages
RED: All 10 tests fail on stub implementation
- Tests OAuthStoreErr mapping to 500 (no backend leak)
- Tests ValidationErr mapping to 400 with descriptive text
- Tests AuthorizationErr mapping to proper status with JSON
- Tests LoginFlowErr mapping to 400 with HTML
- Tests AuthBackendErr mapping to 401 (no credential leak)

Stub implementation exported and documented but not yet implemented.
Tests verify error mapping behavior for new unified error handler.
…oServerError

GREEN: All 10 tests passing

Maps AppError constructors to OAuthError and delegates to unified handler:
- OAuthStoreErr → OAuthStore → 500 (no backend leakage)
- ValidationErr → OAuthValidation → 400 (descriptive text)
- AuthorizationErr → OAuthAuthorization → varies (JSON OAuth response)
- LoginFlowErr → OAuthLoginFlow → 400 (HTML error page)
- AuthBackendErr → direct 401 (MCP-specific, no credential leak)

Clean separation: OAuth errors handled by Servant module, MCP-specific
errors (AuthBackendErr) handled directly in MCP namespace.

All tests pass, zero hlint warnings, no regressions.
Replace domainErrorToServerError with appErrorToServerError in error
boundary tests. The new function delegates OAuth errors to the Servant
IDP layer while handling MCP-specific errors directly.

Changes:
- ErrorBoundarySecuritySpec: use direct appErrorToServerError calls
- Remove mock tracer infrastructure (function no longer traces)
- Remove tracerVerificationSpec (tracing moved to caller responsibility)
- BoundarySpec: replace placeholders with actual boundary tests

All 524 tests pass, security properties preserved.
Function was superseded by appErrorToServerError which delegates to
oauthErrorToServerError from the Servant.OAuth2.IDP namespace.
Clean up unused imports and TypeApplications pragma.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the Servant.OAuth2.IDP modules to eliminate all dependencies on the MCP namespace, preparing the OAuth implementation for extraction into a standalone package. The refactoring includes splitting configuration types, consolidating error handling with structured ADT payloads, implementing PKCE with constant-time validation, and introducing new modules for metadata (RFC 8414/9728), tracing, and configuration.

Key changes:

  • Split OAuthConfig into OAuthEnv (protocol settings in Servant) and MCPOAuthConfig (demo-specific in MCP)
  • Consolidated error types with structured ADT payloads instead of Text-based constructors
  • Added new modules: Config, Metadata, PKCE, Errors, Trace
  • Removed modules: MCP.Trace.OAuth, Servant.OAuth2.IDP.LoginFlowError, Servant.OAuth2.IDP.Types.Internal
  • Updated all tests to use smart constructors with proper validation

Reviewed changes

Copilot reviewed 73 out of 75 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/Trace/RenderSpec.hs Updated to use new OAuthTrace from Servant namespace with smart constructors
test/Trace/OAuthSpec.hs Removed (functionality moved to Servant.OAuth2.IDP.TraceSpec)
test/Trace/GoldenSpec.hs Updated golden tests for new trace constructors with domain types
test/Trace/FilterSpec.hs Updated trace filtering tests with new constructor names
test/TestMonad.hs Updated to use smart constructors and unwrap functions
test/Servant/OAuth2/IDP/TypesSpec.hs Extended with tests for new types (OAuthGrantType, LoginAction, TokenValidity)
test/Servant/OAuth2/IDP/TraceSpec.hs New test file for OAuthTrace ADT with domain newtypes
test/Servant/OAuth2/IDP/TokenRequestSpec.hs Updated to use smart constructors for token request tests
test/Servant/OAuth2/IDP/PKCESpec.hs New test file for PKCE implementation
test/Servant/OAuth2/IDP/MetadataSpec.hs New test file for RFC 8414/9728 metadata types
test/Servant/OAuth2/IDP/LucidRenderingSpec.hs Updated HTML rendering tests with new ErrorPage constructor
test/Servant/OAuth2/IDP/Handlers/MetadataSpec.hs New test file for metadata handler behavior
test/Servant/OAuth2/IDP/ErrorsSpec.hs New comprehensive test file for consolidated error types
test/Servant/OAuth2/IDP/ConfigSpec.hs New test file for OAuthEnv configuration
test/Servant/OAuth2/IDP/BrandingSpec.hs New test file for configurable branding
test/Servant/OAuth2/IDP/APISpec.hs Updated API tests with smart constructors
test/Security/SessionCookieSpec.hs Updated to use DemoOAuthBundle
test/Main.hs Updated test suite organization
test/MCP/Server/OAuth/TypesSpec.hs Disabled (tests moved to ErrorsSpec)
test/MCP/Server/OAuth/Test/Fixtures.hs Updated fixtures to use new bundle structure
test/MCP/Server/OAuth/BoundarySpec.hs Updated boundary layer tests
test/MCP/Server/HTTP/McpAuthSpec.hs Updated HTTP auth tests
test/MCP/Server/HTTP/AppEnvSpec.hs New test file for AppEnv error handling
test/MCP/Server/AuthSpec.hs New test file for MCP-specific OAuth config
test/Laws/*.hs Updated law tests to remove Generators import
test/Generators.hs Removed (Arbitrary instances moved to Types.hs)
src/Servant/OAuth2/IDP/Types.hs Major updates: smart constructor exports, Arbitrary instances, new types
src/Servant/OAuth2/IDP/Trace.hs New module for OAuth trace events
src/Servant/OAuth2/IDP/Test/Internal.hs Updated test utilities
src/Servant/OAuth2/IDP/Store/InMemory.hs Updated to use typed keys instead of Text
src/Servant/OAuth2/IDP/Store.hs Updated import for MonadTime
src/Servant/OAuth2/IDP/Server.hs Updated to use OAuthEnv and OAuthTrace
src/Servant/OAuth2/IDP/PKCE.hs New module for PKCE implementation
src/Servant/OAuth2/IDP/Metadata.hs New module for RFC 8414/9728 metadata
src/Servant/OAuth2/IDP/LoginFlowError.hs Removed (consolidated into Errors)
src/Servant/OAuth2/IDP/Handlers/Token.hs Updated token handlers
src/Servant/OAuth2/IDP/Handlers.hs Updated module exports

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Update module structure: remove deleted Boundary module, add
  Handlers section with all handler modules
- Update AppEnv code sample with new fields (envOAuthEnv,
  envOAuthTracer, envJWT, envServerState, envTimeProvider)
- Update AppError constructors (ValidationErr now takes
  ValidationError, add AuthorizationErr/LoginFlowErr)
- Add OAuthError unified type documentation with oauthErrorToServerError
- Expand Types & Errors section with reason ADTs
- Update README project structure to show Servant/OAuth2/IDP namespace
@albertov albertov marked this pull request as ready for review December 22, 2025 15:41
Add mkProtectedResourceMetadataForDemo to support HTTP URLs in
development/testing environments while maintaining HTTPS requirement
for production use via mkProtectedResourceMetadata.

This fixes a regression where demo mode would fail HTTPS validation
when using localhost URLs. The new function validates URI format
but allows both HTTP and HTTPS schemes.

Changes:
- Add mkProtectedResourceMetadataForDemo with relaxed validation
- Update mkDemoOAuthBundle to use demo-friendly constructor
- Refactor mkDemoOAuthBundle to accept custom URI parameter
- Add mkDemoOAuthBundleFromText convenience wrapper
- Maintain strict HTTPS validation for production paths
The login form button was sending action=login, but the LoginAction
type only accepts "approve" or "deny". This caused "Invalid action: login"
errors after users submitted credentials.

Changed the Sign In button value from "login" to "approve" to match
the FromHttpApiData instance in Types.hs.

Related to mcp-5wk.102 bug fix series.
Update http-server example to use mkDemoOAuthBundleFromText
with the CLI --base-url argument instead of hardcoded localhost.

This completes the baseUrl threading fix (mcp-5wk.102) by ensuring
the example server properly passes the configured base URL to the
OAuth bundle for resource metadata construction.
Replace primitive Text types with proper domain types per FR-004c:

- prResource: Text → URI (Network.URI)
- prAuthorizationServers: [Text] → NonEmpty URI (RFC requires ≥1)
- prBearerMethodsSupported: Maybe [Text] → Maybe (NonEmpty BearerMethod)

Add BearerMethod ADT for RFC 6750 bearer token methods:
- BearerHeader: Authorization header (Section 2.1)
- BearerBody: Form-encoded body (Section 2.2)
- BearerUri: Query parameter (Section 2.3)

Update smart constructors and JSON instances to use typed values.
Add BearerMethodSpec tests for JSON round-trip validation.
Add unsafeParseURI helper function to avoid hlint partial function
warnings. The helper provides clearer error messages when test URI
parsing fails.

Files fixed:
- test/MCP/Server/OAuth/Test/Fixtures.hs
- test/Servant/OAuth2/IDP/ConfigSpec.hs
- test/Servant/OAuth2/IDP/Handlers/MetadataSpec.hs
@albertov
Copy link
Author

Subsumed by #3

@albertov albertov closed this Dec 23, 2025
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