Google Login Automation¶
This document describes the technical implementation of Google OAuth authentication for the Spokane Mountaineers Experience Cloud site.
Access¶
- Apex Class: GoogleAuthRegistrationHandler
- Test Class: GoogleAuthRegistrationHandlerTest
- Auth Provider: Setup โ Identity โ Auth. Providers โ Google
๐ฏ Purpose¶
The GoogleAuthRegistrationHandler implements Salesforce's Auth.RegistrationHandler interface to manage user authentication for Google OAuth login on Experience Cloud sites. It:
- Authenticates existing users via Google OAuth
- Matches users by username pattern (
email + '.smi') - Prevents new account creation (Donorbox-only registration)
- Provides actionable error messages for users
โ๏ธ Configuration¶
Prerequisites¶
- My Domain must be deployed
- Google Auth Provider must be configured with:
- Consumer Key and Secret from Google Cloud Console
- Scopes:
openid email profile - Registration Handler:
GoogleAuthRegistrationHandler
- Experience Cloud Site must have:
- Google Auth Provider enabled in Login & Registration settings
- Social Login component added to the Login page
- Self-Registration disabled (to prevent bypassing Donorbox)
Setup Steps¶
-
Configure Google Auth Provider:
- Navigate to: Setup โ Identity โ Auth. Providers โ Google
- Assign Registration Handler:
GoogleAuthRegistrationHandler - Set "Execute Registration As" to a user with appropriate permissions
-
Enable for Experience Cloud Site:
- Navigate to: Setup โ Digital Experiences โ All Sites โ Spokane Mountaineers โ Administration โ Login & Registration
- Under Authentication Providers, enable Google
- Under Registration, set Self-Registration to Disabled
-
Add Social Login Component:
- Open Experience Builder for your site
- Navigate to the Login page
- Add the Social Login component
- Publish changes
๐งฑ Implementation Details¶
User Matching Strategy¶
The handler uses username pattern matching for reliable user identification:
String usernamePattern = email.toLowerCase().trim() + '.smi';
List<User> usersByUsername = [
SELECT Id, Username, Email, IsActive
FROM User
WHERE Username = :usernamePattern
LIMIT 1
];
Why username pattern matching?
- Usernames cannot be modified - Provides a stable identifier for authentication
- Email addresses can change - Members might update their email in Salesforce, but username remains constant
- Single query - Efficient database lookup using indexed Username field
- Predictable format - Always follows
email@example.com.smipattern
Account Creation Prevention¶
The handler does not create new accounts. If no matching user is found, it throws an exception with actionable guidance:
if (!usersByUsername.isEmpty()) {
return usersByUsername[0];
}
// No user found - provide actionable guidance
throw new RegistrationHandlerException(
'No account found for this email address.\n\n' +
'If you are a new member, please sign up at:\n' +
'https://donorbox.org/spokanemountaineers-membership-2\n\n' +
'If you already have an account, please:\n' +
'1. Use your usual login method for now\n' +
'2. Report this issue to webdev@spokanemountaineers.org\n\n' +
'We will help you link your Google account to your existing membership.'
);
This ensures that:
- New memberships go through Donorbox (payment required)
- Existing members get clear guidance on next steps
- No duplicate accounts are created
๐ Flow Diagram¶
Source: google-login-flow.d2
๐ Code Structure¶
Main Methods¶
createUser(Id portalId, Auth.UserData data)¶
Main entry point called by Salesforce during Google OAuth flow.
Parameters:
portalId: Network (Experience Cloud site) IDdata: User data from Google OAuth callback (includes email, firstName, lastName)
Returns: User record if found, throws exception if not found
Logic:
- Validates email is present
- Calls
findExistingUser()to locate user - If found, returns user
- If not found, throws exception with actionable guidance
findExistingUser(String email)¶
Finds existing user by username pattern.
Parameters:
email: Email address from Google OAuth
Returns: User record if found, null if not found
Logic:
- Constructs username pattern:
email.toLowerCase().trim() + '.smi' - Queries User table for matching username
- Returns first match or
null
updateUser(Id userId, Id portalId, Auth.UserData data)¶
Called when user data needs updating (not used in this implementation).
Note: This method intentionally does nothing. Existing flows handle user updates automatically.
๐งช Testing¶
Test Coverage¶
The test class GoogleAuthRegistrationHandlerTest provides 100% code coverage with 22 test methods covering:
- User matching by username pattern
- Error handling for blank emails
- Error handling for non-existent users
- Helper method testing (alias generation, password generation, etc.)
Running Tests¶
sf apex run test --class-names GoogleAuthRegistrationHandlerTest --target-org smi --code-coverage
Test Scenarios¶
- Existing User Found: Verifies successful login when username pattern matches
- User Not Found: Verifies exception is thrown with actionable error message
- Blank Email: Verifies exception is thrown for invalid input
- Edge Cases: Tests helper methods with various inputs
๐จ Error Handling¶
Common Error Scenarios¶
No Account Found¶
User sees:
No account found for this email address.
If you are a new member, please sign up at:
https://donorbox.org/spokanemountaineers-membership-2
If you already have an account, please:
1. Use your usual login method for now
2. Report this issue to webdev@spokanemountaineers.org
We will help you link your Google account to your existing membership.
Resolution:
- New members: Direct to Donorbox signup
- Existing members: Contact webdev for account linking assistance
Blank Email¶
User sees:
Email is required for authentication
Resolution: This should not occur in normal operation. If it does, contact webdev.
๐ง Maintenance¶
Updating Username Pattern¶
If the .smi suffix is removed in the future, update line 96 in GoogleAuthRegistrationHandler.cls:
Current:
String usernamePattern = email.toLowerCase().trim() + '.smi';
Future (if .smi removed):
String usernamePattern = email.toLowerCase().trim();
Adding Additional Auth Providers¶
To add support for additional OAuth providers (e.g., Microsoft, Facebook):
- Create new Auth Provider in Setup
- Create new Registration Handler class (or extend existing)
- Assign handler to Auth Provider
- Enable provider in Experience Cloud site settings
Monitoring¶
Monitor for:
- Failed login attempts (check debug logs)
- User-reported issues (webdev@spokanemountaineers.org)
- Exception frequency (Salesforce debug logs)
๐ Performance¶
Query Optimization¶
- Single SOQL query per login attempt
- Indexed field (Username) for fast lookups
- LIMIT 1 to minimize data transfer
- Efficient database lookup with minimal overhead
๐ Security Considerations¶
Account Creation Prevention¶
- Self-Registration must be disabled in Experience Cloud settings
- Handler explicitly throws exceptions instead of creating users
- Donorbox remains the only account creation path
User Matching¶
- Username pattern matching provides a stable authentication identifier
- Usernames cannot be modified, preventing account hijacking
- Email changes don't break authentication since matching is based on username
Error Messages¶
- Error messages are user-friendly but don't expose system internals
- Clear guidance directs users to appropriate support channels
๐ Related Documentation¶
- Google Login Article - User-friendly overview
- Experience Cloud Setup - Salesforce documentation
- Auth.RegistrationHandler Interface - Salesforce Apex documentation
๐ Troubleshooting¶
Google Button Not Appearing¶
- Verify Auth Provider is enabled for the Experience Cloud site
- Check that Social Login component is added to Login page
- Verify Self-Registration settings (should be disabled)
- Check browser console for JavaScript errors
Login Fails for Existing User¶
- Verify user's username follows pattern:
email@example.com.smi - Check that user is active (
IsActive = true) - Review debug logs for exception details
- Verify email from Google matches username pattern
Exception Messages Not Showing¶
- Check Salesforce debug logs for full exception details
- Verify error handling in Experience Cloud login component
- Test with different browsers/devices
๐ Support¶
For issues or questions about Google login automation:
- Email: webdev@spokanemountaineers.org
- GitHub Issues: Create an issue