Skip to main content

OAuth Management

Google OAuth authentication allows users to access Zuora Workflow Manager using their own Google Account, simplifying credential management and improving security.

Overview

OAuth Benefits

BenefitDescription
SecurityPasswords managed by Google, not stored locally
ConvenienceOne-click access (Single Sign-On)
User managementAutomatic account creation on first login
AvatarAutomatic avatar from Google Profile
Additional securityEmail domain verification

How It Works

OAuthService Role

The OAuthService centralizes OAuth logic:
// Retrieve OAuth configuration
OAuthService::getGoogleOAuthConfig();
// Returns: [client_id, client_secret, redirect, enabled, allowed_domains]

// Check if OAuth is enabled
OAuthService::isEnabled();
// Returns: true/false

// Get allowed domains
OAuthService::getAllowedDomains();
// Returns: ['example.com', 'company.org']

OAuth Configuration

Prerequisites

  1. Google account with Google Cloud Console access
  2. Access to create OAuth credentials
  3. super_admin role in Zuora Workflow Manager

Step 1: Create OAuth Credentials on Google

1.1 Access Google Cloud Console

  1. Go to Google Cloud Console
  2. Create or select an existing project

1.2 Enable Google+ API

  1. Navigate to APIs & ServicesLibrary
  2. Search for “Google+ API” or “People API”
  3. Click on Enable
  1. Navigate to APIs & ServicesOAuth consent screen
  2. Select External (for production)
  3. Fill out:
    • App name: Your application name
    • User support email: Support email
    • Developer contact email: Contact email
  4. Click on Save and Continue
  5. Scroll through subsequent sections and click Save and Continue

1.4 Create OAuth Client ID

  1. Navigate to APIs & ServicesCredentials
  2. Click on Create CredentialsOAuth client ID
  3. Select Web application
  4. Fill out:
    • Name: Descriptive name (e.g., “Zuora Workflow Manager”)
    • Authorized redirect URIs:
      {APP_URL}/oauth/google/callback
      
      • Development: https://zuora-workflows.lndo.site/oauth/google/callback
      • Production: https://yourdomain.com/oauth/google/callback
  5. Click on Create

1.5 Copy Credentials

After creation, Google will display:
  • Client ID: Copy and save
  • Client Secret: Copy and save
The Client Secret is shown only once. Save it in a secure location.

Step 2: Configure OAuth in Settings

2.1 Access Settings

  1. Login to Zuora Workflow Manager as super_admin
  2. Navigate to SettingsGeneral Settings

2.2 OAuth Configuration

In the OAuth Configuration section:
FieldDescriptionExample
OAuth EnabledEnable/disable Google logintrue / false
Allowed DomainsAllowed email domainsexample.com,company.org
Google Client IDClient ID from Google Cloud Console123456789-abc...apps.googleusercontent.com
Google Client SecretClient Secret from Google Cloud ConsoleGOCSPX-...

2.3 Configure Fields

OAuth Enabled:
  • Toggle to true to enable
Allowed Domains:
  • Enter allowed email domains
  • Separate with commas: example.com,company.org
  • Supports wildcard: *.example.com
Only users with emails in these domains can access via OAuth.
Google Client ID:
  • Paste the Client ID copied from Google Cloud Console
  • Ensure you copy it completely
Google Client Secret:
  • Paste the Client Secret
  • Will be automatically encrypted in the database
  • Won’t be displayed in plain text after saving

2.4 Save Settings

Click on Save in the bottom right.
OAuth settings configured via UI have priority over environment variables.

Configuring Email Domains

Specific Domains

Allow only specific domains:
example.com
company.org
startup.io

Wildcard

Use wildcard to allow subdomains:
*.example.com  // Allows user@example.com, mail.example.com
*.company.org  // Allows user@company.org, admin.company.org
Use wildcard with caution. Only allow domains you trust.

Multiple

Separate domains with commas or new lines:
example.com
company.org
*.startup.io

Validation

Domain validation happens via ValidateDomain rule:
// Rule implementation
public function passes($attribute, $value)
{
    $allowedDomains = OAuthService::getAllowedDomains();

    foreach ($allowedDomains as $domain) {
        if ($this->matchesDomain($value, $domain)) {
            return true;
        }
    }

    return false;
}

Accessing with OAuth

First Login

1. Login Page

On the login page, you’ll see:
  • Email: Email field for traditional login
  • Password: Password field for traditional login
  • “Sign in with Google”: OAuth button

2. Click “Sign in with Google”

Click on the Google button. You’ll be redirected to Google.

3. Google Authorization

Google will show you:
  • Application name
  • Domains it will have access to (email, profile)
  • Authorization request
Click on Allow to proceed.

4. Automatic Account Creation

If the user doesn’t exist:
  1. App retrieves Google profile
  2. Automatically creates a new User:
    User::create([
        'name' => $googleData['given_name'],
        'surname' => $googleData['family_name'],
        'email' => $googleData['email'],
        'avatar_url' => $googleData['picture'],
    ]);
    
  3. Automatically assigns workflow_user role
  4. Logs in
The new user is assigned workflow_user role by default.

5. Login Complete

You’ll be redirected to the dashboard with active session.

Subsequent Logins

For subsequent logins, the process is faster:
  1. Click “Sign in with Google”
  2. If already logged in to Google, automatic authorization
  3. Immediate redirect to dashboard

Logout

Logout works like traditional logout:
  1. Click on profile avatar in the header
  2. Click on Logout
  3. Local session terminated
Logout from Zuora Workflow Manager doesn’t logout from Google. For complete logout, you must also logout from Google.

Managing OAuth Users

Avatar

OAuth users automatically get:
  • Avatar URL: Profile image from Google
  • Saved in the avatar_url field of the User model
  • Displayed in the admin panel

Assigned Role

The listener AssignWorkflowRoleOnSocialiteRegistration automatically assigns workflow_user role to new OAuth users:
// Listener
public function handle(SocialiteUserConnected $event): void
{
    $user = $event->user;

    if ($user->roles->isEmpty()) {
        $user->assignRole('workflow_user');
    }
}

Modifying OAuth User Role

To modify an OAuth user’s role:
  1. Navigate to Users
  2. Click on the OAuth user
  3. Modify the Roles section
  4. Add or remove roles
  5. Click on Save

Reset Password

OAuth users don’t have a local password:
  • They can’t login with email + password
  • If you want to enable traditional login too, set a password manually
# Set password for OAuth user
lando artisan tinker

>>> $user = User::where('email', 'oauth.user@example.com')->first()
>>> $user->password = Hash::make('password')
>>> $user->save()

OAuth Troubleshooting

Error: “Domain not allowed”

Symptom:
The email domain is not allowed to access this application
Causes:
  1. The email domain is not in “Allowed Domains”
  2. OAuth configuration is not saved
  3. The domain has incorrect syntax
Solutions:
  1. Verify Allowed Domains:
    • Settings → General Settings → OAuth Configuration
    • Check that the domain is present
    • Add the domain if missing
  2. Verify configuration:
    lando artisan tinker
    >>> app(OAuthService::class)->getAllowedDomains()
    // You should see your domain
    
  3. Check domain syntax:
    • Correct: example.com
    • Incorrect: @example.com, http://example.com

Error: “Invalid OAuth credentials”

Symptom:
invalid_client
Client is unauthorized to retrieve access tokens
Causes:
  1. Incorrect Client ID or Secret
  2. OAuth Client not configured correctly on Google
  3. Redirect URI doesn’t match
Solutions:
  1. Verify Client ID and Secret:
    • Settings → General Settings → OAuth Configuration
    • Copy again from Google Cloud Console
    • Ensure no extra spaces
  2. Verify Redirect URI:
    • Google Cloud Console → Credentials → OAuth Client ID
    • Check Authorized redirect URIs
    • Must be exactly: {APP_URL}/oauth/google/callback
  3. Test with cURL:
    curl -X POST https://oauth2.googleapis.com/token \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=authorization_code" \
      -d "client_id=YOUR_CLIENT_ID" \
      -d "client_secret=YOUR_CLIENT_SECRET" \
      -d "code=AUTH_CODE" \
      -d "redirect_uri={APP_URL}/oauth/google/callback"
    

Error: “Access denied”

Symptom:
Error: access_denied
The user denied access to application
Causes:
  1. User clicked “Cancel” on Google
  2. OAuth consent screen not configured
  3. Scopes not approved
Solutions:
  1. User must accept:
    • Click “Sign in with Google” again
    • Click “Allow” on the Google screen
  2. Verify OAuth consent screen:
    • Google Cloud Console → OAuth consent screen
    • Ensure it’s configured
    • If in “Testing”, add users as test users

Error: “Redirect URI mismatch”

Symptom:
Error: redirect_uri_mismatch
The redirect URI in request does not match one authorized for OAuth client
Causes:
  1. APP_URL in .env doesn’t match Redirect URI
  2. Different port between .env and Google Cloud Console
Solutions:
  1. Verify APP_URL:
    # In .env
    APP_URL=https://zuora-workflows.lndo.site
    
  2. Verify Redirect URI in Google:
    • Must be exactly: https://zuora-workflows.lndo.site/oauth/google/callback
    • No trailing slash
  3. Update if necessary:
    lando artisan cache:clear
    lando artisan config:clear
    

Avatar Not Showing

Symptom: OAuth user doesn’t show avatar Solutions:
  1. Verify avatar_url:
    >>> $user = User::where('email', 'oauth.user@example.com')->first()
    >>> $user->avatar_url // Should be a URL
    
  2. Check listener:
    lando logs -f | grep -i "avatar"
    
  3. Verify configuration:
    • The UpdateUserAvatarOnSocialiteLogin listener must be registered
    • Check app/Listeners/UpdateUserAvatarOnSocialiteLogin.php

User Not Created After OAuth

Symptom: OAuth login appears to work but user not created Diagnosis:
# Verify if user exists
lando artisan tinker
>>> User::where('email', 'oauth.user@example.com')->first()

# Check logs
lando logs -f | grep -i "socialite"
Solutions:
  1. Verify listener registered:
    // In EventServiceProvider
    Event::listen(SocialiteUserConnected::class, AssignWorkflowRoleOnSocialiteRegistration::class);
    
  2. Verify domain validation:
    • Is the email domain in Allowed Domains?
    • Is the ValidateDomain rule configured?
  3. Check for errors:
    lando logs -f | grep -i "error"
    

Best Practices

Security

1. Limit allowed domains: Good practices:
  • Specify specific enterprise domains
  • Use wildcard only if necessary
  • Remove unused domains
Avoid:
  • Leaving Allowed Domains empty (allows all)
  • Using generic wildcards (e.g., *)
  • Including public email provider domains (gmail.com, etc.) if not needed
2. Initial roles:
  • Assign roles with least privilege possible
  • workflow_user is a good default for most users
  • Consider assigning higher roles only after approval
3. Monitoring:
  • Check OAuth login logs
  • Monitor new user registrations
  • Investigate logins from unusual domains

User Experience

1. Clear communication:
  • Explain to users how OAuth works
  • Provide instructions for first login
  • Communicate which domains are supported
2. Fallback:
  • Keep traditional login available
  • Users without Google Account can still access
  • OAuth users can also have a password (for backup)
3. Support:
  • Document account recovery process
  • Provide contacts for OAuth issues
  • Create FAQ for common questions

Configuration

1. Separate environments:
  • Use separate OAuth credentials for dev/test/prod
  • Don’t reuse Client Secrets between environments
  • Update Redirect URI for each environment
2. Versioning:
  • Record when OAuth credentials are generated/updated
  • Keep track of who has access to credentials
  • Rotate credentials regularly (6-12 months)
3. Testing:
  • Test complete OAuth flow before enabling in production
  • Verify all scenarios (first login, subsequent login, errors)
  • Test with multiple email domains

API Reference

OAuthService

// Get full OAuth configuration
$config = OAuthService::getGoogleOAuthConfig();
// Returns:
// [
//     'client_id' => '12345...',
//     'client_secret' => 'GOCSPX-...',
//     'redirect' => 'https://.../oauth/google/callback',
//     'enabled' => true,
//     'allowed_domains' => ['example.com'],
// ]

// Check if OAuth is enabled
$enabled = OAuthService::isEnabled();
// Returns: true/false

// Get allowed domains
$domains = OAuthService::getAllowedDomains();
// Returns: ['example.com', 'company.org']

Events & Listeners

// Event: SocialiteUserConnected
// Dispatched when user successfully authenticates with OAuth

// Listener: AssignWorkflowRoleOnSocialiteRegistration
// Automatically assigns 'workflow_user' role to new users

// Listener: UpdateUserAvatarOnSocialiteLogin
// Updates avatar_url from Google Profile

Next Steps

After configuring OAuth: