Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/betterbetterbetter/wp-access-sso/archive/refs/heads/main.zipAccess Platform SSO WordPress Plugin
A comprehensive Single Sign-On (SSO) plugin that integrates WordPress sites with your Access Platform (Supabase Auth).
Features
- JWT-based Authentication: Secure token-based authentication using your existing Supabase infrastructure
- Safe User Provisioning: Creates WordPress users without allowing external claims to grant or change privileged WordPress roles
- Authorization Separation: Access proves identity; WordPress and plugins such as MemberPress remain the source of roles and permissions
- Session Management: Tracks SSO sessions with tokens and request fingerprints hashed at rest
- Security Features: Browser-bound login state, single-use short-lived JWTs, rate limiting, and redacted diagnostics
- Professional Admin Interface: Easy-to-use configuration and monitoring dashboard
- Login Form Detection: Automatically detects and enhances login forms from MemberPress, LearnDash, WooCommerce, and more
Installation
- Upload the plugin files to
/wp-content/plugins/access-platform-sso/ - Activate the plugin through the WordPress admin panel
- Go to Settings > Access Platform SSO to configure
Configuration
Required Settings
- Access Platform URL: The URL of your Access Platform (e.g.,
https://your-platform.com) - Site ID: The canonical site identifier copied from Access and verified against this WordPress host
- JWT Secret Key: Shared secret for JWT token validation (must match your Access Platform)
Optional Settings
- Callback Path: Path where SSO callback is processed. Use this if your homepage doesn't run WordPress code (e.g., static homepage). Set to
welcomeormembersto use/welcome/?access_sso_callback=1instead. - Post-Login Redirect URL: Where to redirect users after successful SSO login
- Button and Form Detection Settings: Control the injected login button and which form types are enhanced
- Excluded Routes: Prevent automatic form detection where it is not wanted
Sites with Static Homepages
If your WordPress site has a homepage that doesn't run WordPress code (e.g., static HTML, different CMS, or reverse proxy), the SSO callback won't work on the root URL.
Solution: Set the Callback Path to a WordPress page that does run PHP:
- Go to Settings > Access Platform SSO
- Set Callback Path to
welcome(or any WordPress page slug) - The SSO callback will now use
https://your-site.com/welcome/?access_sso_callback=1 - Set Post-Login Redirect URL to where you want users to land after login
Login Form Detection
The plugin automatically detects login forms across your site and injects an SSO login button. This works with:
Supported Plugins
- MemberPress - All login forms and widgets
- LearnDash - Course login forms and widgets
- WooCommerce - My Account login, checkout login
- Ultimate Member - Login forms and widgets
- BuddyPress / BuddyBoss - Community login forms
- Generic - Any form with username/password fields
How It Works
- The JavaScript detector scans the page for known login form patterns
- When a login form is found, an SSO button is automatically injected
- The button appears above the form fields with an "or" divider
- Users can click to authenticate via Access Platform
Configuration
In Settings > Access Platform SSO > Login Form Detection:
- Button Text: Customize the SSO button text (default: "Login with Access Platform")
- Enabled Form Types: Choose which plugin forms to detect
- Disable Auto-Detection: Turn off automatic detection if needed
Manual Integration
If the automatic detector doesn't find your form, you can manually trigger it:
// Inject SSO button into a specific form
AccessSSODetector.injectInto('#my-custom-login-form');
// Re-scan the page for forms
AccessSSODetector.detect();
Adding Custom Form Selectors
You can extend the detector with custom selectors:
// Add custom selectors before page load
window.accessSSODetector = window.accessSSODetector || {};
window.accessSSODetector.custom_selectors = [
'#my-custom-form',
'.my-login-widget form'
];
Account Page: Manage or Cancel via Access
Members who joined through Access are billed by Stripe via Access, not by
MemberPress. On the MemberPress account page (/mepr-account/) they see no
subscription they can cancel, so they contact support instead. The plugin adds
a clearly labelled button that sends those members to Access.
Who sees it
Only logged-in users with a MemberPress subscription billed by Access: gateway
manual and a subscr_id starting with sub_ (the Stripe subscription id
Access provisions with), in any status except pending. Legacy members billed
by MemberPress's own Stripe gateway never see the button, so their normal
cancel flow is untouched; MemberPress admin comps (mp-sub-…) don't count.
A cancelled Access subscription only counts while no other subscription is
active or paused, so a member who left Access and now pays through MemberPress
isn't sent to Access to cancel.
The access_platform_id user meta is not used for this. The provisioner writes
it on every SSO login, including admin "Login as" impersonation, so it only
says a user has used Access, not who bills them.
How it renders
assets/js/account-manage-detector.js (enqueued only for Access-billed users)
detects the MemberPress account page and inserts a single banner immediately
after #mepr-account-nav, falling back to just above .mepr-account-table
or the top of the account content. It never inserts inside the nav: MemberPress
lays the tabs out with flex-wrap and anything injected between them breaks the
row. It watches for late-rendered account tabs for ten seconds and never adds
a second banner. There is deliberately no mepr_account_nav nav item.
The button links to <Access Platform URL>/subscriptions by default. Access
owns billing, so the plugin deliberately does not cancel anything through
the MemberPress API.
Settings (Settings > Access Platform SSO > Account Page)
- Disable Manage/Cancel Button: turn the feature off for this site.
- Button Text: default "Manage or cancel your membership".
- Help Text: one-line explanation shown in the notice.
- Access Path: path on Access to link to (default
/subscriptions).
Manual test plan
- In Access admin, impersonate ("Login as") an Access-billed member, open this site and press "Login with Access Platform".
- Visit
/mepr-account/?action=subscriptions. Expect one banner with the button directly under the account nav, above the table, and the nav itself unchanged (one row, no extra tab). - Click the button. Expect to land on the member's Access subscription list with "Manage Billing" and "Cancel Subscription" visible (log in to Access if prompted).
- Log in as a legacy MemberPress-billed member. Expect no button and the normal MemberPress cancel link.
Usage
Library return URLs
The uncached SSO start URL must preserve the complete same-site WordPress
authorization URL inside return_to, including its PKCE challenge, state,
callback, and empty scope. Pre-encode nested URLs passed to WordPress
add_query_arg(); otherwise their query parameters become outer SSO parameters
and the return request is rejected. External destinations still fall back to
the WordPress home URL. Run python3 -m unittest discover -s tests to verify
the round-trip and redirect-safety regression contracts.
For End Users
- Visit any WordPress site with the plugin installed
- Click "Login with Access Platform" on the login page
- You'll be redirected to your Access Platform for authentication
- After successful login, you'll be redirected back and automatically logged in
- Logout from any site will optionally log you out from all sites
For Administrators
- Configure the plugin settings in WordPress admin
- Test the connection to your Access Platform
- Monitor SSO statistics and active sessions
- View detailed logs of authentication events
- Manage user sessions and revoke access if needed
Access Platform Integration
This plugin works with your existing Access Platform JWT endpoint at /api/sso/jwt. The endpoint should:
- Generate JWT tokens for authenticated users
- Include user identity data and the required trust claims (
iss,aud,site_id,iat, andexp) - Sign tokens with the shared JWT secret
- Handle token validation requests
Example JWT Payload
{
"id": "user-123",
"email": "user@example.com",
"name": "John Doe",
"first_name": "John",
"last_name": "Doe",
"iss": "https://access.example.com",
"aud": "wordpress-sso",
"iat": 1640995200,
"exp": 1640996100,
"site_id": "wp-site-456"
}
Identity and Authorization Boundary
Access authenticates the person and supplies signed identity claims. A fully validated, site-bound, single-use SSO token may promote an Access administrator to WordPress administrator; non-admin claims never downgrade or otherwise replace an existing WordPress role. New non-admin SSO users receive only the site's safe non-privileged default role (falling back to subscriber). MemberPress memberships, course access, and all other authorization remain in WordPress and MemberPress. Admin promotion is applied when the user next signs in to each attached site through Access SSO.
Security Features
- JWT Signature Verification: HMAC SHA256 validation
- Bounded, Single-Use Tokens:
iatandexpare required, JWT lifetime is capped at 15 minutes, and callbacks cannot be replayed - Browser-Bound State: WordPress-started login uses a short-lived HttpOnly, Secure, SameSite=Lax state cookie
- Safe Redirects: Post-login redirects are limited to the WordPress host and an empty setting falls back to the homepage
- Continuation-Aware Login Buttons: Injected login buttons preserve WordPress and MemberPress
redirect_todestinations, including OAuth authorization requests started by connected applications - Private Session Storage: Session tokens, Access IDs, IP addresses, and user agents are one-way hashed at rest
- Rate Limiting: Application-level limits protect the login start and callback endpoints
- Cache Protection: Authentication responses use
no-store, mark requestsDONOTCACHEPAGE, and register WP Rocket exclusions
Database Tables
The plugin creates the following table:
wp_access_sso_sessions: Stores SSO session data
Hooks and Filters
Actions
access_sso_user_created: Fired when a new user is created via SSOaccess_sso_user_updated: Fired when an existing user is updated via SSOaccess_sso_login_success: Fired on successful SSO loginaccess_sso_login_failed: Fired on failed SSO login attempt
Filters
access_sso_user_data: Modify user data before provisioningaccess_sso_user_role: Modify the assigned user roleaccess_sso_redirect_url: Modify the post-login redirect URLaccess_sso_jwt_claims: Modify JWT claims before validation
Troubleshooting
Common Issues
- Connection Failed: Check that your Access Platform URL is correct and accessible
- Invalid Token: Ensure JWT secret matches between plugin and Access Platform
- User Not Created: Check that auto-provisioning is enabled
- Login Loop: Verify the callback URL, browser state cookie, and that cache/CDN rules bypass authentication endpoints
Debug Mode
Enable WordPress debug logging temporarily when diagnosing a development site. The plugin intentionally emits only generic/redacted authentication failures:
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
Testing Connection
Use the "Test Connection" button in the plugin settings to verify:
- Access Platform URL is reachable
- JWT secret is configured correctly
- Token validation is working
Requirements
- WordPress 5.0 or higher
- PHP 7.4 or higher
- SSL/HTTPS (required for secure token transmission)
- Active Access Platform with JWT SSO endpoint
Security Considerations
- Always use HTTPS in production environments
- Rotate JWT secrets regularly for enhanced security
- Monitor logs for suspicious authentication attempts
- Limit admin bypass to trusted administrators only
- Regular updates to keep security patches current
Support
For support and bug reports, please contact your Access Platform administrator or create an issue in the project repository.
License
This plugin is licensed under GPL v2 or later.
Changelog
Version 1.2.4
- Fixed the account-page banner showing for legacy MemberPress-billed members. The gate now checks who bills the member's MemberPress subscriptions (Access: gateway
manualwith asub_subscr_id) instead of theaccess_platform_idmeta, which every SSO login sets. Access-billed members who log in with a WordPress password now see the banner too. - A cancelled Access subscription no longer shows the banner while another subscription is active or paused, so members MemberPress now bills aren't sent to Access to cancel.
- The account-page subscription lookup never prints a database error into the page.
Version 1.2.2
- Fixed site-initiated "Login with Access" on hosts that strip cookies from cacheable URLs (WP Engine): the browser-bound state cookie is now
wordpress_access_sso_stateand state logins return through the uncachedadmin-post.php?action=access_sso_callbackendpoint instead of the front page - Access-initiated dashboard launches now land on the page Access configured for the site (the signed
redirect_to), same-site only, instead of always the plugin's default redirect
Version 1.2.1
- Fixed the account-page banner being injected inside the MemberPress nav (it split the tabs into two rows) and removed the extra nav tab; the banner now renders as a single card directly under the nav
- Restyled the banner: neutral card, inherits the page font, compact primary button, stacks on narrow screens
Version 1.2.0
- NEW: Account page "Manage or cancel your membership" button for Access-billed members (users with
access_platform_idmeta), linking to Access/subscriptions; banner injected below the MemberPress account nav byassets/js/account-manage-detector.js; Account Page settings section (disable toggle, button text, help text, Access path). Legacy MemberPress-billed members unaffected.
Version 1.1.9
- Detect blocked first-party cookies and
sessionStoragebefore starting SSO - Show Brave-compatible privacy guidance and a reload action instead of allowing an uncaught storage error
- Guard all
sessionStorageoperations against browserSecurityErrorexceptions - Added browser-bound state for WordPress-started SSO and retained constrained signed compatibility for Access dashboard launches
- Enforced 15-minute JWT lifetimes and one-time callback token consumption
- Prevented Access claims from granting or changing WordPress roles
- Hashed session tokens and request fingerprints at rest, including incremental legacy-data migration
- Added strict admin nonces, application rate limits, safe local redirects, no-store responses, and WP Rocket exclusions
- Removed the frontend processing splash and sensitive diagnostics
Version 1.1.0
- NEW: Login Form Detector - Automatically detects and enhances login forms
- NEW: MemberPress support - Works with all MemberPress login forms and widgets
- NEW: LearnDash support - Detects course and widget login forms
- NEW: WooCommerce support - My Account and checkout login forms
- NEW: Callback Path setting - Use custom path for SSO on sites with static homepages
- NEW: Post-Login Redirect URL setting - Configure where users land after SSO
- NEW: Configurable button text and enabled form types
- Updated MemberPress selectors based on official documentation
- MutationObserver for detecting dynamically loaded forms
Version 1.0.0
- Initial release
- JWT-based SSO authentication
- User provisioning and role mapping
- Session management and security logging
- Professional admin interface
- Comprehensive documentation
© 2024 Access Platform Team. All rights reserved.