Python Google Oauth2 Login Integration

Written by

in

Integrating Google OAuth 2.0 into a Python web application is one of the most effective ways to offer a seamless, secure, and familiar login experience for users. In this guide we’ll walk through every step—from creating credentials in the Google Cloud Console to writing clean, production‑ready Python code—so you can add “Sign in with Google” to your Flask or Django project in minutes. By the end of the article you’ll understand the OAuth 2.0 flow, how to verify ID tokens, and best practices for keeping your implementation safe and SEO‑friendly.

Why Choose Google OAuth 2.0 for Python Applications?

  • Trusted identity provider: Over 2 billion users already have Google accounts, reducing friction and boosting conversion rates.
  • Reduced password fatigue: Users never need to create or remember another password, which lowers support tickets.
  • Built‑in security: Google handles password storage, multi‑factor authentication, and suspicious‑login detection.
  • Rich user profile data: Access to email, name, profile picture, and locale with a single API call.
  • SEO advantage: Faster login leads to lower bounce rates, longer session duration, and higher rankings for user‑centric signals.

Prerequisites Before You Start

  1. A Google account with access to the Google Cloud Console.
  2. Python 3.8+ installed on your development machine.
  3. Basic familiarity with either Flask or Django (the examples cover both).
  4. Virtual environment tools such as venv or pipenv.

Step 1: Create OAuth 2.0 Credentials in Google Cloud Console

1.1 Enable the Google Identity Services API

Navigate to APIs & Services > Library and search for Google Identity Services. Click Enable to activate the API for your project.

1.2 Configure the OAuth consent screen

  • Go to APIs & Services > OAuth consent screen.
  • Select External (unless you’re building an internal app).
  • Fill in the required fields: App name, Support email, and Authorized domains.
  • Add the scopes you’ll request, e.g., openid, email, profile.
  • Save and continue; you can skip optional sections for a quick setup.

1.3 Generate a client ID and client secret

Under Credentials click Create credentials > OAuth client ID. Choose Web application** and set the following:

  • Authorized JavaScript origins: http://localhost:5000 (or your production domain).
  • Authorized redirect URIs: http://localhost:5000/auth/callback (Flask) or http://localhost:8000/accounts/google/login/callback/ (Django).

Copy the Client ID and Client secret**; you’ll need them in your Python code.

Step 2: Install Required Python Packages

python -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install Flask==2.3.*   # or Django==5.0.*
pip install google-auth google-auth-oauthlib google-auth-httplib2 requests

The google-auth family handles token verification, while requests is used for optional profile calls.

Step 3: Implement the OAuth Flow in Flask

3.1 Basic Flask app skeleton

from flask import Flask, redirect, url_for, request, session, jsonify
import os
import google.auth.transport.requests
from google.oauth2 import id_token

app = Flask(__name__)
app.secret_key = os.urandom(24)

# Load credentials from environment variables for security
GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID')
GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET')
REDIRECT_URI = 'http://localhost:5000/auth/callback'

3.2 Build the authorization URL

from urllib.parse import urlencode

@app.route('/login')
def login():
    params = {
        'client_id': GOOGLE_CLIENT_ID,
        'redirect_uri': REDIRECT_URI,
        'response_type': 'code',
        'scope': 'openid email profile',
        'access_type': 'offline',
        'prompt': 'consent'   # forces a refresh token on first login
    }
    auth_url = f"https://accounts.google.com/o/oauth2/v2/auth?{urlencode(params)}"
    return redirect(auth_url)

3.3 Handle the callback and exchange the code for tokens

import requests

@app.route('/auth/callback')
def callback():
    error = request.args.get('error')
    if error:
        return f"Error: {error}", 400

    code = request.args.get('code')
    token_endpoint = 'https://oauth2.googleapis.com/token'
    data = {
        'code': code,
        'client_id': GOOGLE_CLIENT_ID,
        'client_secret': GOOGLE_CLIENT_SECRET,
        'redirect_uri': REDIRECT_URI,
        'grant_type': 'authorization_code'
    }
    token_response = requests.post(token_endpoint, data=data)
    token_response.raise_for_status()
    tokens = token_response.json()
    id_info = verify_id_token(tokens['id_token'])
    session['user'] = {
        'sub': id_info['sub'],
        'email': id_info['email'],
        'name': id_info.get('name'),
        'picture': id_info.get('picture')
    }
    return redirect(url_for('profile'))

3.4 Verify the ID token securely

def verify_id_token(token):
    request_adapter = google.auth.transport.requests.Request()
    try:
        id_info = id_token.verify_oauth2_token(
            token,
            request_adapter,
            GOOGLE_CLIENT_ID
        )
        return id_info
    except ValueError as e:
        # Token is invalid
        raise RuntimeError(f"Invalid token: {e}")

3.5 Display a simple profile page

@app.route('/profile')
def profile():
    user = session.get('user')
    if not user:
        return redirect(url_for('login'))
    return f"""
    

Welcome, {user['name']}!

Profile picture

Email: {user['email']}

Logout """

3.6 Add a logout route

@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('login'))

Step 4: Django Integration (Alternative)

4.1 Install Django‑allauth for a turnkey solution

pip install django-allauth

Allauth abstracts most of the OAuth boilerplate. Add the following to settings.py:

INSTALLED_APPS = [
    # default Django apps …
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.google',
]

SITE_ID = 1

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

LOGIN_REDIRECT_URL = '/'
SOCIALACCOUNT_PROVIDERS = {
    'google': {
        'SCOPE': ['profile', 'email'],
        'AUTH_PARAMS': {'access_type': 'offline'},
        'APP': {
            'client_id': os.getenv('GOOGLE_CLIENT_ID'),
            'secret': os.getenv('GOOGLE_CLIENT_SECRET'),
            'key': ''
        }
    }
}

Include the URLs in urls.py:

from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('accounts/', include('allauth.urls')),
]

Run migrations and start the server. Users can now sign in via /accounts/login/ and select the Google button automatically rendered by Allauth.

Step 5: Secure Your OAuth Implementation

  • Never hard‑code secrets: Store GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in environment variables or a secret manager.
  • Validate the state parameter: Include a cryptographically random state token in the auth request and verify it on callback to protect against CSRF attacks.
  • Use HTTPS in production: Google blocks insecure redirect URIs, and browsers flag mixed‑content warnings.
  • Limit token scopes: Request only the data you need (e.g., email and profile

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *