Skip to content

Conversation

@pfefferle
Copy link
Member

Summary

Implements FedCM for IndieAuth as specified at https://indieweb.org/FedCM_for_IndieAuth

This enables seamless browser-native sign-in without pop-ups or redirects for supporting browsers.

New Endpoints

  • GET /indieauth/1.0/fedcm/config.json - IdP configuration
  • GET /indieauth/1.0/fedcm/accounts - Returns logged-in user accounts
  • GET /indieauth/1.0/fedcm/client_metadata - Client privacy/terms URLs
  • POST /indieauth/1.0/fedcm/assertion - Issues authorization codes with PKCE

Features

  • Well-known endpoint: /.well-known/web-identity for FedCM discovery
  • Login Status API: Sends Set-Login headers on login/logout
  • Automatic IdP registration: Calls IdentityProvider.register() when user visits admin
  • Security: Validates Sec-Fetch-Dest: webidentity header and Origin matching
  • PKCE required: Enforces code_challenge/code_verifier for all flows

New Files

  • includes/class-indieauth-fedcm-endpoint.php - FedCM REST API endpoints
  • includes/class-indieauth-webidentity.php - Well-known handler
  • js/fedcm-register.js - Browser IdP registration script

Test Plan

  • Verify /.well-known/web-identity returns correct provider URL
  • Test FedCM config endpoint returns valid JSON
  • Test accounts endpoint returns 401 when not logged in
  • Test accounts endpoint returns user data when logged in with correct header
  • Test assertion endpoint issues valid authorization codes
  • Verify codes can be exchanged at token endpoint
  • Test Login Status headers are sent on login/logout
  • Verify IdP registration script loads on dashboard

Implements FedCM for IndieAuth as specified at indieweb.org/FedCM_for_IndieAuth

New endpoints:
- GET /indieauth/1.0/fedcm/config.json - IdP configuration
- GET /indieauth/1.0/fedcm/accounts - User accounts list
- GET /indieauth/1.0/fedcm/client_metadata - Client metadata
- POST /indieauth/1.0/fedcm/assertion - Authorization code issuance

Features:
- Well-known web-identity endpoint (/.well-known/web-identity)
- Login Status API integration (Set-Login headers)
- Automatic IdP registration via IdentityProvider.register()
- PKCE support for all FedCM flows
- CORS headers for cross-origin requests
- Sec-Fetch-Dest validation for security
@dshanske
Copy link
Member

dshanske commented Jan 9, 2026

I'm going to love reading this.

Copy link
Contributor

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 pull request implements FedCM (Federated Credential Management) support for IndieAuth, enabling browser-native authentication without popups or redirects. The implementation adds four new REST API endpoints for FedCM IdP functionality, a well-known discovery endpoint, Login Status API integration, and automatic IdP registration.

Key Changes

  • New FedCM REST API endpoints (config, accounts, client_metadata, assertion) with security validations
  • Well-known endpoint handler for FedCM discovery at /.well-known/web-identity
  • Login Status API integration via Set-Login headers on login/logout events
  • Client-side JavaScript for automatic IdP registration in the browser

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 10 comments.

File Description
js/fedcm-register.js Client-side script that registers the site as a FedCM Identity Provider using the IdentityProvider API
indieauth.php Updated plugin initialization to load new FedCM classes and flush rewrite rules on activation
includes/class-indieauth-webidentity.php Handles the /.well-known/web-identity endpoint for FedCM discovery with proper CORS headers
includes/class-indieauth-fedcm-endpoint.php Core FedCM implementation with four REST endpoints, security validations, PKCE enforcement, and authorization code issuance

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

- Use absolute URLs in config endpoint instead of relative paths
- Add validation/sanitization for account_id parameter
- Sanitize nonce parameter with sanitize_text_field()
- Validate code_challenge_method is S256
- Sanitize code_challenge and code_challenge_method from params
- Use filemtime() for dynamic script versioning
- Add JSON decode error checking for params
Copy link
Contributor

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

Copilot reviewed 4 out of 4 changed files in this pull request and generated 16 comments.


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

Tests cover:
- Config endpoint returns valid configuration with absolute URLs
- Accounts endpoint requires Sec-Fetch-Dest header
- Accounts endpoint requires authentication
- Accounts endpoint returns user data when authenticated
- Client metadata endpoint returns data for known clients
- Assertion endpoint requires Sec-Fetch-Dest header
- Assertion endpoint requires matching Origin header
- Assertion endpoint requires authentication
- Assertion endpoint requires PKCE parameters
- Assertion endpoint requires S256 code_challenge_method
- Assertion endpoint rejects invalid JSON in params
- Assertion endpoint issues valid authorization codes
- Assertion endpoint verifies account_id matches current user
- Assertion endpoint stores nonce in authorization code
- FedCM-issued codes are marked with fedcm flag
Copy link
Contributor

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

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.


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

- Change generic 'Invalid request' to 'Missing or invalid Sec-Fetch-Dest header'
- Add scheme validation to Origin check (prevents http/https mismatch)
- Remove redundant Content-Type headers (WP_REST_Server sets automatically)
- Add scope flexibility with indieauth_fedcm_scope filter
- Add console.debug logging for registration failures
- Fix activation hook to load class file before checking existence
- Improve params type validation with explicit error for invalid format
- Add test for Origin scheme mismatch
);
}

// Parse PKCE params if provided.
Copy link
Member

Choose a reason for hiding this comment

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

Should we not require this? As we did in the rest of the plugin?

Copy link
Member

Choose a reason for hiding this comment

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

I see it fails later, but why not failing here?

}

// Generate authorization code.
$uuid = wp_generate_uuid4();
Copy link
Member

Choose a reason for hiding this comment

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

Since we do authorization codes and PKCE in multiple sections, wonder about a future PR to refactor them to avoid duplicative code.

…ation

- Use 'urn:ietf:wg:oauth:2.0:oob' for redirect_uri since FedCM doesn't redirect
- Add CORS headers to config.json endpoint per FedCM spec requirement
- Add port validation to Origin check (scheme + host + port must all match)
- Add test case for port mismatch in Origin validation
- Add 'required' => true to params arg to fail early if PKCE params missing
- Add sanitize_callback for nonce in route definition for consistency
- Fix wp-env mapping for tests to include vendor directory
- Fix package.json test script path
- Fix composer.json script typo and macOS cp compatibility
- Update FedCM tests to include params and handle account_id validation
- Update test-functions.php to handle URL validation in test environment
- Add .phpunit.result.cache to .gitignore
Updated .gitignore to exclude the .claude file from version control.
Copy link
Member

@dshanske dshanske left a comment

Choose a reason for hiding this comment

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

Looks good. I'm a Firefox user so I need to try this with a Chrome build I suppose

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.

3 participants