Implementing OAuth 2.0 with Google Drive using FastAPI
What is OAuth 2.0 and why is it necessary?
OAuth 2.0 is a popular method for allowing third-party apps to access user data without needing passwords, commonly used for services like Google Drive. Instead of passwords, OAuth 2.0 uses tokens for secure permission, which avoids storing sensitive login details and enhances security.
This blog covers implementing OAuth 2.0 with Google Drive in Python and FastAPI. It explains how to set up credentials and includes code for listing and downloading files from Google Drive, giving a clear example of how to connect FastAPI to Google Drive using OAuth.
Setting Up The Project
Step 1: Install Required Libraries
pip install google-auth google-auth-oauthlib google-auth-httplib2 google-api-python-client fastapi uvicorn
Step 2: Setting up OAuth Credentials in Google Cloud Console
2. Enable Google Drive API:
3. Set Up OAuth Consent Screen:
4. Create OAuth Credentials:
Step 3: Code Implementation
Create a main.py file with the following endpoints:
# Necessary imports
import os
import io
from fastapi import FastAPI
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.http import MediaIoBaseDownload
# Initialize FastAPI app
app = FastAPI()
# Google OAuth 2.0 scopes for Google Drive
SCOPES = ["https://www.googleapis.com/auth/drive.readonly"]
Recommended by LinkedIn
File paths for OAuth token and client secrets
# File paths for token storage
TOKEN_FILE_PATH = "token.json"
CLIENT_SECRET_FILE = "client_secret.json"
These paths refer to where the token and client secret files will be stored. The client_secret.json file contains the OAuth credentials. The token.json stores the OAuth token, allowing the application to reuse it without requiring repeated logins.
load_creds() Function
def load_creds():
"""Load and refresh credentials if necessary."""
if os.path.exists(TOKEN_FILE_PATH):
creds = Credentials.from_authorized_user_file(TOKEN_FILE_PATH, SCOPES)
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
with open(TOKEN_FILE_PATH, "w") as token_file:
token_file.write(creds.to_json())
return creds
return None
auth() Endpoint
@app.get("/auth")
async def auth():
"""Perform authentication and return a success message."""
creds = load_creds()
if not creds:
flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRET_FILE, SCOPES)
creds = flow.run_local_server(port=0)
with open(TOKEN_FILE_PATH, "w") as token_file:
token_file.write(creds.to_json())
return {"message": "Successfully logged in."}
The /auth endpoint begins the OAuth process. It uses the InstalledAppFlow class from google_auth_oauthlib to handle authentication. A browser window opens where the user logs into their Google account and grants permissions. After authorization, the app gets an access token, which is saved in token.json for future use.
list_files() Endpoint
@app.get("/drive/list")
async def list_files():
"""List all files from Google Drive."""
creds = load_creds()
if not creds:
return {"message": "User not authenticated."}
service = build("drive", "v3", credentials=creds)
# List files with the required fields (id, name)
results = service.files().list(fields="files(id, name)").execute()
items = results.get("files", [])
# Collect file information (id, name)
files_with_info = [{"id": item["id"], "name": item["name"]} for item in items]
return files_with_info
download_file() Endpoint
@app.get("/drive/download/{file_id}")
async def download_file(file_id: str):
"""Download a specific file from Google Drive."""
creds = load_creds()
if not creds:
return {"message": "User not authenticated."}
service = build("drive", "v3", credentials=creds)
request = service.files().get_media(fileId=file_id)
file_name = service.files().get(fileId=file_id).execute().get("name")
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while not done:
status, done = downloader.next_chunk()
fh.seek(0)
with open(file_name, "wb") as file:
file.write(fh.read())
return {"message": f"File '{file_name}' downloaded successfully."}
Step 4: Running the FastAPI Application
To start the application, use: uvicorn main:app --reload Access the Swagger UI at http://localhost:8000/docs to test the endpoints directly.
Conclusion
This guide demonstrates how to implement OAuth 2.0 in FastAPI to connect to Google Drive for listing and downloading files. This foundation can be adapted to access other Google services by adjusting the OAuth scopes.
Very informative
Very helpful