Home Google OAuth in fastapi
Post
Cancel

Google OAuth in fastapi

為什麼需要 OAuth

生活當中我們常用的服務越來越多了,這時候會發現,如果每種服務都要記一組帳號,常常會”忘記密碼”,不然就是所有的帳密都是同一組,這是很危險的。

OAuth 可以幫助我們使用既有的帳號做第三方應用的登入,常見的有 google, facebook, wechat..等。這樣不只使用者不用記住各種密碼,對於服務的提供者,也不用存下敏感的使用者資料,提高了資訊的安全性。

Google OAuth 2.0 設定

到 Google Cloud Console -> API 和服務 -> 憑證 -> 建立憑證

Desktop View

OAuth 用戶端 ID

Desktop View

網頁應用程式(這邊選你自己的應用程式吧)

Desktop View

輸入允許的 domain, 這邊會和你的 server code 搭配

Desktop View

完成後,得到 GOOGLE_CLIENT_ID 和 GOOGLE_CLIENT_SECRET 記下來,等等 code 也會用上。

Desktop View

codes

透過以下4 個檔案完成 OAuth

Desktop View

main.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2AuthorizationCodeBearer
from google.auth.transport import requests
from google.oauth2 import id_token
from requests_oauthlib import OAuth2Session
from starlette.responses import RedirectResponse
from dotenv import load_dotenv
import os

load_dotenv()

app = FastAPI()

# OAuth 2.0 settings
client_id = os.getenv("GOOGLE_CLIENT_ID")
client_secret = os.getenv("GOOGLE_CLIENT_SECRET")
redirect_uri = os.getenv("GOOGLE_REDIRECT_URI")
authorization_base_url = "https://accounts.google.com/o/oauth2/auth"
token_url = "https://oauth2.googleapis.com/token"
print(client_id,client_secret,redirect_uri)
# OAuth 2.0 flow initialization
oauth = OAuth2Session(client_id, redirect_uri=redirect_uri, scope=[
        "https://www.googleapis.com/auth/userinfo.email",
        "https://www.googleapis.com/auth/userinfo.profile",
        "openid"
    ])

# 跳轉到 Google 認證頁面
@app.get("/auth/login")
def login():
    print("login()")
    authorization_url, state = oauth.authorization_url(authorization_base_url, access_type="offline")
    return RedirectResponse(authorization_url)

# Google 認證完成後的回調處理
@app.get("/auth/callback")
def callback(code: str):
    print("callback()")
    try:
        # 交換 authorization code 取得 token
        token = oauth.fetch_token(token_url, code=code, client_secret=client_secret)
        # 使用 token 獲取用戶資訊
        user_info = oauth.get("https://www.googleapis.com/oauth2/v1/userinfo").json()
        return user_info

    except Exception as e:
        print(f"Error during OAuth callback: {e}")  # 打印詳細的錯誤訊息
        raise HTTPException(status_code=400, detail="Error during OAuth callback")

.env 檔案內容

Desktop View

dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Use an official Python runtime as a parent image
FROM python:3.9-slim-buster

# Set the working directory to /app
WORKDIR /app

# Copy the requirements file into the container at /app
COPY requirements.txt .

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt && \
    rm -rf /root/.cache/pip/*

# Copy the rest of the application code into the container at /app
COPY . .

# Expose the port that Django runs on
EXPOSE 8000

requirements.txt

1
2
3
4
5
6
fastapi
uvicorn
psycopg2-binary
google-auth
requests-oauthlib
python-dotenv

在 container 中透過指令啟動 fastapi 的服務

1
uvicorn main:app --reload --host 0.0.0.0 --port 8000

結果

如果你沒登入會要求要登入

Desktop View

如果你已登入,會請你選帳號

Desktop View

選好帳號後會告知有哪些資訊傳給此服務

Desktop View

完成後,就會 call main.py 中的 callback function.

因為 callback 回去的資料滿滿都是個人的資料,所以就不截圖了。

☝ツ☝

This post is licensed under CC BY 4.0 by the author.

👈 ツ 👍