Skip to content

Commit eb1c180

Browse files
committed
Add the Google OAuth2 login
1 parent 33c9f78 commit eb1c180

File tree

11 files changed

+73
-15
lines changed

11 files changed

+73
-15
lines changed

backend/.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ CELERY_RABBITMQ_PASSWORD='guest'
2626
# [ Plugin ] oauth2
2727
OAUTH2_GITHUB_CLIENT_ID='test'
2828
OAUTH2_GITHUB_CLIENT_SECRET='test'
29+
OAUTH2_GOOGLE_CLIENT_ID='test'
30+
OAUTH2_GOOGLE_CLIENT_SECRET='test'
2931
OAUTH2_LINUX_DO_CLIENT_ID='test'
3032
OAUTH2_LINUX_DO_CLIENT_SECRET='test'
3133
# [ Plugin ] email

backend/common/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ class UserSocialType(StrEnum):
113113
"""用户社交类型"""
114114

115115
github = 'GitHub'
116+
google = 'Google'
116117
linux_do = 'LinuxDo'
117118

118119

backend/core/conf.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ class Settings(BaseSettings):
223223
# .env
224224
OAUTH2_GITHUB_CLIENT_ID: str
225225
OAUTH2_GITHUB_CLIENT_SECRET: str
226+
OAUTH2_GOOGLE_CLIENT_ID: str
227+
OAUTH2_GOOGLE_CLIENT_SECRET: str
226228
OAUTH2_LINUX_DO_CLIENT_ID: str
227229
OAUTH2_LINUX_DO_CLIENT_SECRET: str
228230

backend/plugin/oauth2/api/router.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
from backend.core.conf import settings
66
from backend.plugin.oauth2.api.v1.github import router as github_router
7+
from backend.plugin.oauth2.api.v1.google import router as google_router
78
from backend.plugin.oauth2.api.v1.linux_do import router as linux_do_router
89

910
v1 = APIRouter(prefix=f'{settings.FASTAPI_API_V1_PATH}/oauth2')
1011

1112
v1.include_router(github_router, prefix='/github', tags=['Github OAuth2'])
13+
v1.include_router(google_router, prefix='/google', tags=['Google OAuth2'])
1214
v1.include_router(linux_do_router, prefix='/linux-do', tags=['LinuxDo OAuth2'])

backend/plugin/oauth2/api/v1/github.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,12 @@
1212

1313
router = APIRouter()
1414

15-
_github_client = GitHubOAuth20(settings.OAUTH2_GITHUB_CLIENT_ID, settings.OAUTH2_GITHUB_CLIENT_SECRET)
16-
_github_oauth2 = FastAPIOAuth20(_github_client, redirect_route_name='github_oauth2_callback')
15+
github_client = GitHubOAuth20(settings.OAUTH2_GITHUB_CLIENT_ID, settings.OAUTH2_GITHUB_CLIENT_SECRET)
1716

1817

1918
@router.get('', summary='获取 Github 授权链接')
2019
async def get_github_oauth2_url(request: Request) -> ResponseSchemaModel[str]:
21-
auth_url = await _github_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
20+
auth_url = await github_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
2221
return response_base.success(data=auth_url)
2322

2423

@@ -32,11 +31,11 @@ async def github_oauth2_callback(
3231
request: Request,
3332
response: Response,
3433
background_tasks: BackgroundTasks,
35-
oauth2: FastAPIOAuth20 = Depends(_github_oauth2),
34+
oauth2: FastAPIOAuth20 = Depends(FastAPIOAuth20(github_client, redirect_route_name='github_oauth2_callback')),
3635
):
3736
token, _state = oauth2
3837
access_token = token['access_token']
39-
user = await _github_client.get_userinfo(access_token)
38+
user = await github_client.get_userinfo(access_token)
4039
data = await oauth2_service.create_with_login(
4140
request=request,
4241
response=response,
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
from fastapi import APIRouter, BackgroundTasks, Depends, Request, Response
4+
from fastapi_limiter.depends import RateLimiter
5+
from fastapi_oauth20 import FastAPIOAuth20, GoogleOAuth20
6+
from starlette.responses import RedirectResponse
7+
8+
from backend.common.enums import UserSocialType
9+
from backend.common.response.response_schema import ResponseSchemaModel, response_base
10+
from backend.core.conf import settings
11+
from backend.plugin.oauth2.service.oauth2_service import oauth2_service
12+
13+
router = APIRouter()
14+
15+
google_client = GoogleOAuth20(settings.OAUTH2_GOOGLE_CLIENT_ID, settings.OAUTH2_GOOGLE_CLIENT_SECRET)
16+
17+
18+
@router.get('', summary='获取 google 授权链接')
19+
async def get_google_oauth2_url(request: Request) -> ResponseSchemaModel[str]:
20+
auth_url = await google_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
21+
return response_base.success(data=auth_url)
22+
23+
24+
@router.get(
25+
'/callback',
26+
summary='google 授权自动重定向',
27+
description='google 授权后,自动重定向到当前地址并获取用户信息,通过用户信息自动创建系统用户',
28+
dependencies=[Depends(RateLimiter(times=5, minutes=1))],
29+
)
30+
async def google_oauth2_callback(
31+
request: Request,
32+
response: Response,
33+
background_tasks: BackgroundTasks,
34+
oauth2: FastAPIOAuth20 = Depends(FastAPIOAuth20(google_client, redirect_route_name='google_oauth2_callback')),
35+
):
36+
token, _state = oauth2
37+
access_token = token['access_token']
38+
user = await google_client.get_userinfo(access_token)
39+
data = await oauth2_service.create_with_login(
40+
request=request,
41+
response=response,
42+
background_tasks=background_tasks,
43+
user=user,
44+
social=UserSocialType.google,
45+
)
46+
return RedirectResponse(
47+
url=f'{settings.OAUTH2_FRONTEND_REDIRECT_URI}?access_token={data.access_token}&session_uuid={data.session_uuid}'
48+
)

backend/plugin/oauth2/api/v1/linux_do.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,12 @@
1212

1313
router = APIRouter()
1414

15-
_linux_do_client = LinuxDoOAuth20(
16-
settings.OAUTH2_LINUX_DO_CLIENT_ID,
17-
settings.OAUTH2_LINUX_DO_CLIENT_SECRET,
18-
)
19-
_linux_do_oauth2 = FastAPIOAuth20(_linux_do_client, redirect_route_name='linux_do_oauth2_callback')
15+
linux_do_client = LinuxDoOAuth20(settings.OAUTH2_LINUX_DO_CLIENT_ID, settings.OAUTH2_LINUX_DO_CLIENT_SECRET)
2016

2117

2218
@router.get('', summary='获取 LinuxDo 授权链接')
2319
async def get_linux_do_oauth2_url(request: Request) -> ResponseSchemaModel[str]:
24-
auth_url = await _linux_do_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
20+
auth_url = await linux_do_client.get_authorization_url(redirect_uri=f'{request.url}/callback')
2521
return response_base.success(data=auth_url)
2622

2723

@@ -35,11 +31,11 @@ async def linux_do_oauth2_callback(
3531
request: Request,
3632
response: Response,
3733
background_tasks: BackgroundTasks,
38-
oauth2: FastAPIOAuth20 = Depends(_linux_do_oauth2),
34+
oauth2: FastAPIOAuth20 = Depends(FastAPIOAuth20(linux_do_client, redirect_route_name='linux_do_oauth2_callback')),
3935
):
4036
token, _state = oauth2
4137
access_token = token['access_token']
42-
user = await _linux_do_client.get_userinfo(access_token)
38+
user = await linux_do_client.get_userinfo(access_token)
4339
data = await oauth2_service.create_with_login(
4440
request=request,
4541
response=response,

backend/plugin/oauth2/model/user_social.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class UserSocial(Base):
1919
__tablename__ = 'sys_user_social'
2020

2121
id: Mapped[id_key] = mapped_column(init=False)
22-
sid: Mapped[str] = mapped_column(String(20), comment='第三方用户 ID')
22+
sid: Mapped[str] = mapped_column(String(255), comment='第三方用户 ID')
2323
source: Mapped[str] = mapped_column(String(20), comment='第三方用户来源')
2424

2525
# 用户社交信息一对多

backend/plugin/oauth2/plugin.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[plugin]
22
summary = 'OAuth 2.0'
3-
version = '0.0.4'
3+
version = '0.0.5'
44
description = '通过 OAuth 2.0 的方式登录系统'
55
author = 'wu-clan'
66

backend/plugin/oauth2/service/oauth2_service.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ async def create_with_login(
5454
username = user.get('login')
5555
nickname = user.get('name')
5656

57+
if social == UserSocialType.google:
58+
sid = user.get('id')
59+
username = user.get('name')
60+
nickname = user.get('given_name')
61+
avatar = user.get('picture')
62+
5763
if social == UserSocialType.linux_do:
5864
sid = user.get('id')
5965
nickname = user.get('name')

0 commit comments

Comments
 (0)