Skip to main content
NetBird Selfservice uses Google OAuth for secure, streamlined authentication. This eliminates the need for separate passwords and leverages your organization’s existing Google Workspace accounts.

Google OAuth Flow

The authentication process uses Laravel Socialite to integrate with Google’s OAuth 2.0 provider:

How It Works

Initial Login Request

When a user clicks the login button, they’re redirected to Google’s OAuth consent screen:
// From GoogleController.php:15-18
public function redirect(): RedirectResponse
{
    return Socialite::driver('google')->stateless()->redirect();
}
The stateless() method is used because this is an API-style authentication flow that doesn’t rely on server-side sessions during the OAuth handshake.

OAuth Callback

After the user authenticates with Google, they’re redirected back to the callback URL with an authorization code:
1

Exchange Authorization Code

Laravel Socialite exchanges the authorization code for an access token and retrieves the user’s profile.
2

Domain Validation

If domain restrictions are configured, the user’s email domain is checked against the allowed domain.
3

Create or Update User

The user account is created if new, or updated if it exists, using Google profile data.
4

Log User In

The user is authenticated into the application with a persistent session.

Complete Callback Implementation

// From GoogleController.php:20-45
public function callback(): RedirectResponse
{
    $googleUser = Socialite::driver('google')->stateless()->user();

    // Domain restriction check
    $allowedDomain = config('netbird.allowed_domain');
    if ($allowedDomain) {
        $emailDomain = substr(strrchr($googleUser->getEmail(), '@'), 1);
        if (strcasecmp($emailDomain, $allowedDomain) !== 0) {
            return redirect()->route('login')
                ->withErrors(['email' => 'Only users with @'.$allowedDomain.' email addresses are allowed.']);
        }
    }

    // Create or update user
    $user = User::updateOrCreate(
        ['google_id' => $googleUser->getId()],
        [
            'name' => $googleUser->getName(),
            'email' => $googleUser->getEmail(),
            'avatar' => $googleUser->getAvatar(),
        ]
    );

    Auth::login($user, remember: true);

    return redirect()->intended(route('home'));
}

Configuration

Google OAuth Credentials

Set up your Google OAuth application in the Google Cloud Console and configure the credentials:
# In .env file
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=/admin/oauth/callback/google
The redirect URI must match exactly what’s configured in your Google Cloud Console OAuth app settings.

Google Cloud Console Setup

1

Create OAuth Application

In Google Cloud Console, create a new OAuth 2.0 Client ID under APIs & Services > Credentials.
2

Configure Redirect URIs

Add your callback URL: https://yourdomain.com/admin/oauth/callback/google
3

Set OAuth Scopes

Request basic profile scopes:
  • openid
  • profile
  • email
4

Copy Credentials

Copy the Client ID and Client Secret to your .env file.

Domain Restriction

One of the key security features is the ability to restrict authentication to specific email domains.

Enabling Domain Restrictions

Configure the allowed domain in your environment:
NETBIRD_ALLOWED_DOMAIN=yourcompany.com
When set, only users with email addresses ending in @yourcompany.com can authenticate.

How Domain Validation Works

// From GoogleController.php:24-30
$allowedDomain = config('netbird.allowed_domain');
if ($allowedDomain) {
    $emailDomain = substr(strrchr($googleUser->getEmail(), '@'), 1);
    if (strcasecmp($emailDomain, $allowedDomain) !== 0) {
        return redirect()->route('login')
            ->withErrors(['email' => 'Only users with @'.$allowedDomain.' email addresses are allowed.']);
    }
}
The validation:
  1. Extracts the domain from the user’s email address
  2. Compares it case-insensitively to the configured allowed domain
  3. Rejects the login if domains don’t match
If you leave NETBIRD_ALLOWED_DOMAIN empty, any Google account can authenticate. Only disable domain restrictions if you truly want public access.

Multiple Domain Support

Currently, the system supports a single allowed domain. If you need multiple domains, you can modify the validation logic:
// Example extension for multiple domains
$allowedDomains = ['company.com', 'subsidiary.com'];
$emailDomain = substr(strrchr($googleUser->getEmail(), '@'), 1);

if (!in_array(strtolower($emailDomain), $allowedDomains, true)) {
    return redirect()->route('login')
        ->withErrors(['email' => 'Your email domain is not authorized.']);
}

User Management

User Model

Authenticated users are stored in the users table with the following attributes:
// From User.php:21-27
protected $fillable = [
    'name',
    'email',
    'password',  // Not used with OAuth
    'google_id',
    'avatar',
];

Create or Update Logic

The updateOrCreate method ensures:
  • New users are automatically created on first login
  • Existing users get their profile updated if changed in Google
$user = User::updateOrCreate(
    ['google_id' => $googleUser->getId()],  // Search criteria
    [
        'name' => $googleUser->getName(),      // Update these fields
        'email' => $googleUser->getEmail(),
        'avatar' => $googleUser->getAvatar(),
    ]
);
Users are identified by google_id, not email. This means if a user changes their email in Google, they’ll still be the same user in your system.

Session Management

Login with Remember Me

After successful authentication, users are logged in with a persistent session:
// From GoogleController.php:42
Auth::login($user, remember: true);
The remember: true parameter creates a long-lived “remember me” cookie, keeping users logged in across browser sessions.

Session Duration

Laravel’s default session configuration applies:
  • Session lifetime: 120 minutes (configurable in config/session.php)
  • Remember me token: 2 weeks (Laravel default)

Logout

Users can log out, which destroys their session and invalidates tokens:
// From GoogleController.php:47-54
public function logout(): RedirectResponse
{
    Auth::logout();

    request()->session()->invalidate();
    request()->session()->regenerateToken();

    return redirect()->route('home');
}
The logout process:
  1. Logs the user out of Laravel’s authentication
  2. Invalidates the current session
  3. Regenerates the CSRF token (prevents reuse)
  4. Redirects to the home page
Logging out of NetBird Selfservice does not log you out of your Google account. It only terminates the session within this application.

Security Considerations

Stateless OAuth

Using stateless() mode prevents CSRF attacks during the OAuth flow by not storing state in server sessions

HTTPS Required

Always use HTTPS in production. OAuth redirects with sensitive tokens must be encrypted

Token Regeneration

CSRF tokens are regenerated on logout to prevent session fixation attacks

Domain Whitelisting

Domain restrictions prevent unauthorized access from external Google accounts

User Profile Integration

The user’s Google profile information is stored and can be used throughout the application:

Avatar Display

// From User.php:52-62
public function initials(): string
{
    return Str::of($this->name)
        ->explode(' ')
        ->take(2)
        ->map(fn ($word) => Str::substr($word, 0, 1))
        ->implode('');
}
This method generates initials for users (e.g., “John Doe” → “JD”) which can be used as fallback avatars.

User Attributes

After authentication, you have access to:
AttributeSourceDescription
nameGoogle ProfileFull name of the user
emailGoogle AccountEmail address
google_idGoogle User IDUnique identifier from Google
avatarGoogle Profile PictureURL to profile image

Troubleshooting

”Only users with @domain email addresses are allowed”

Cause: Your email domain doesn’t match NETBIRD_ALLOWED_DOMAIN. Solution:
  • Verify you’re using the correct email domain
  • Check the NETBIRD_ALLOWED_DOMAIN configuration
  • Contact your administrator to add your domain

Redirect URI Mismatch

Cause: The callback URL doesn’t match what’s configured in Google Cloud Console. Solution:
  • Ensure GOOGLE_REDIRECT_URI matches your Google OAuth app configuration
  • Check for trailing slashes and http vs https

”Invalid Client” Error

Cause: Incorrect Google OAuth credentials. Solution:
  • Verify GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are correct
  • Ensure the OAuth app is enabled in Google Cloud Console
  • Check that you’re using credentials from the correct Google Cloud project

Best Practices

Enable Domain Restrictions

Always set NETBIRD_ALLOWED_DOMAIN in production to limit access to your organization

Use HTTPS

Never use OAuth over HTTP in production - Google requires HTTPS for OAuth redirects

Monitor Failed Logins

Track authentication failures to detect unauthorized access attempts

Keep Credentials Secret

Never commit OAuth credentials to version control - use environment variables

Build docs developers (and LLMs) love