mirror of
https://github.com/fastapi-practices/fastapi-best-architecture.git
synced 2026-09-21 21:15:13 +00:00
Add the Google OAuth2 login (#790)
This commit is contained in:
@@ -26,6 +26,8 @@ CELERY_RABBITMQ_PASSWORD='guest'
|
||||
# [ Plugin ] oauth2
|
||||
OAUTH2_GITHUB_CLIENT_ID='test'
|
||||
OAUTH2_GITHUB_CLIENT_SECRET='test'
|
||||
OAUTH2_GOOGLE_CLIENT_ID='test'
|
||||
OAUTH2_GOOGLE_CLIENT_SECRET='test'
|
||||
OAUTH2_LINUX_DO_CLIENT_ID='test'
|
||||
OAUTH2_LINUX_DO_CLIENT_SECRET='test'
|
||||
# [ Plugin ] email
|
||||
|
||||
@@ -113,6 +113,7 @@ class UserSocialType(StrEnum):
|
||||
"""用户社交类型"""
|
||||
|
||||
github = 'GitHub'
|
||||
google = 'Google'
|
||||
linux_do = 'LinuxDo'
|
||||
|
||||
|
||||
|
||||
@@ -223,6 +223,8 @@ class Settings(BaseSettings):
|
||||
# .env
|
||||
OAUTH2_GITHUB_CLIENT_ID: str
|
||||
OAUTH2_GITHUB_CLIENT_SECRET: str
|
||||
OAUTH2_GOOGLE_CLIENT_ID: str
|
||||
OAUTH2_GOOGLE_CLIENT_SECRET: str
|
||||
OAUTH2_LINUX_DO_CLIENT_ID: str
|
||||
OAUTH2_LINUX_DO_CLIENT_SECRET: str
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@ from fastapi import APIRouter
|
||||
|
||||
from backend.core.conf import settings
|
||||
from backend.plugin.oauth2.api.v1.github import router as github_router
|
||||
from backend.plugin.oauth2.api.v1.google import router as google_router
|
||||
from backend.plugin.oauth2.api.v1.linux_do import router as linux_do_router
|
||||
|
||||
v1 = APIRouter(prefix=f'{settings.FASTAPI_API_V1_PATH}/oauth2')
|
||||
|
||||
v1.include_router(github_router, prefix='/github', tags=['Github OAuth2'])
|
||||
v1.include_router(google_router, prefix='/google', tags=['Google OAuth2'])
|
||||
v1.include_router(linux_do_router, prefix='/linux-do', tags=['LinuxDo OAuth2'])
|
||||
|
||||
@@ -12,13 +12,12 @@ from backend.plugin.oauth2.service.oauth2_service import oauth2_service
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
_github_client = GitHubOAuth20(settings.OAUTH2_GITHUB_CLIENT_ID, settings.OAUTH2_GITHUB_CLIENT_SECRET)
|
||||
_github_oauth2 = FastAPIOAuth20(_github_client, redirect_route_name='github_oauth2_callback')
|
||||
github_client = GitHubOAuth20(settings.OAUTH2_GITHUB_CLIENT_ID, settings.OAUTH2_GITHUB_CLIENT_SECRET)
|
||||
|
||||
|
||||
@router.get('', summary='获取 Github 授权链接')
|
||||
async def get_github_oauth2_url(request: Request) -> ResponseSchemaModel[str]:
|
||||
auth_url = await _github_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
|
||||
auth_url = await github_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
|
||||
return response_base.success(data=auth_url)
|
||||
|
||||
|
||||
@@ -32,11 +31,11 @@ async def github_oauth2_callback(
|
||||
request: Request,
|
||||
response: Response,
|
||||
background_tasks: BackgroundTasks,
|
||||
oauth2: FastAPIOAuth20 = Depends(_github_oauth2),
|
||||
oauth2: FastAPIOAuth20 = Depends(FastAPIOAuth20(github_client, redirect_route_name='github_oauth2_callback')),
|
||||
):
|
||||
token, _state = oauth2
|
||||
access_token = token['access_token']
|
||||
user = await _github_client.get_userinfo(access_token)
|
||||
user = await github_client.get_userinfo(access_token)
|
||||
data = await oauth2_service.create_with_login(
|
||||
request=request,
|
||||
response=response,
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, Request, Response
|
||||
from fastapi_limiter.depends import RateLimiter
|
||||
from fastapi_oauth20 import FastAPIOAuth20, GoogleOAuth20
|
||||
from starlette.responses import RedirectResponse
|
||||
|
||||
from backend.common.enums import UserSocialType
|
||||
from backend.common.response.response_schema import ResponseSchemaModel, response_base
|
||||
from backend.core.conf import settings
|
||||
from backend.plugin.oauth2.service.oauth2_service import oauth2_service
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
google_client = GoogleOAuth20(settings.OAUTH2_GOOGLE_CLIENT_ID, settings.OAUTH2_GOOGLE_CLIENT_SECRET)
|
||||
|
||||
|
||||
@router.get('', summary='获取 google 授权链接')
|
||||
async def get_google_oauth2_url(request: Request) -> ResponseSchemaModel[str]:
|
||||
auth_url = await google_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
|
||||
return response_base.success(data=auth_url)
|
||||
|
||||
|
||||
@router.get(
|
||||
'/callback',
|
||||
summary='google 授权自动重定向',
|
||||
description='google 授权后,自动重定向到当前地址并获取用户信息,通过用户信息自动创建系统用户',
|
||||
dependencies=[Depends(RateLimiter(times=5, minutes=1))],
|
||||
)
|
||||
async def google_oauth2_callback(
|
||||
request: Request,
|
||||
response: Response,
|
||||
background_tasks: BackgroundTasks,
|
||||
oauth2: FastAPIOAuth20 = Depends(FastAPIOAuth20(google_client, redirect_route_name='google_oauth2_callback')),
|
||||
):
|
||||
token, _state = oauth2
|
||||
access_token = token['access_token']
|
||||
user = await google_client.get_userinfo(access_token)
|
||||
data = await oauth2_service.create_with_login(
|
||||
request=request,
|
||||
response=response,
|
||||
background_tasks=background_tasks,
|
||||
user=user,
|
||||
social=UserSocialType.google,
|
||||
)
|
||||
return RedirectResponse(
|
||||
url=f'{settings.OAUTH2_FRONTEND_REDIRECT_URI}?access_token={data.access_token}&session_uuid={data.session_uuid}'
|
||||
)
|
||||
@@ -12,16 +12,12 @@ from backend.plugin.oauth2.service.oauth2_service import oauth2_service
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
_linux_do_client = LinuxDoOAuth20(
|
||||
settings.OAUTH2_LINUX_DO_CLIENT_ID,
|
||||
settings.OAUTH2_LINUX_DO_CLIENT_SECRET,
|
||||
)
|
||||
_linux_do_oauth2 = FastAPIOAuth20(_linux_do_client, redirect_route_name='linux_do_oauth2_callback')
|
||||
linux_do_client = LinuxDoOAuth20(settings.OAUTH2_LINUX_DO_CLIENT_ID, settings.OAUTH2_LINUX_DO_CLIENT_SECRET)
|
||||
|
||||
|
||||
@router.get('', summary='获取 LinuxDo 授权链接')
|
||||
async def get_linux_do_oauth2_url(request: Request) -> ResponseSchemaModel[str]:
|
||||
auth_url = await _linux_do_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
|
||||
auth_url = await linux_do_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
|
||||
return response_base.success(data=auth_url)
|
||||
|
||||
|
||||
@@ -35,11 +31,11 @@ async def linux_do_oauth2_callback(
|
||||
request: Request,
|
||||
response: Response,
|
||||
background_tasks: BackgroundTasks,
|
||||
oauth2: FastAPIOAuth20 = Depends(_linux_do_oauth2),
|
||||
oauth2: FastAPIOAuth20 = Depends(FastAPIOAuth20(linux_do_client, redirect_route_name='linux_do_oauth2_callback')),
|
||||
):
|
||||
token, _state = oauth2
|
||||
access_token = token['access_token']
|
||||
user = await _linux_do_client.get_userinfo(access_token)
|
||||
user = await linux_do_client.get_userinfo(access_token)
|
||||
data = await oauth2_service.create_with_login(
|
||||
request=request,
|
||||
response=response,
|
||||
|
||||
@@ -19,7 +19,7 @@ class UserSocial(Base):
|
||||
__tablename__ = 'sys_user_social'
|
||||
|
||||
id: Mapped[id_key] = mapped_column(init=False)
|
||||
sid: Mapped[str] = mapped_column(String(20), comment='第三方用户 ID')
|
||||
sid: Mapped[str] = mapped_column(String(255), comment='第三方用户 ID')
|
||||
source: Mapped[str] = mapped_column(String(20), comment='第三方用户来源')
|
||||
|
||||
# 用户社交信息一对多
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[plugin]
|
||||
summary = 'OAuth 2.0'
|
||||
version = '0.0.4'
|
||||
version = '0.0.5'
|
||||
description = '通过 OAuth 2.0 的方式登录系统'
|
||||
author = 'wu-clan'
|
||||
|
||||
|
||||
@@ -54,6 +54,12 @@ class OAuth2Service:
|
||||
username = user.get('login')
|
||||
nickname = user.get('name')
|
||||
|
||||
if social == UserSocialType.google:
|
||||
sid = user.get('id')
|
||||
username = user.get('name')
|
||||
nickname = user.get('given_name')
|
||||
avatar = user.get('picture')
|
||||
|
||||
if social == UserSocialType.linux_do:
|
||||
sid = user.get('id')
|
||||
nickname = user.get('name')
|
||||
|
||||
Reference in New Issue
Block a user