@@ -19,73 +19,77 @@ async def login() -> RedirectResponse:
19
19
책임
20
20
- kakao oauth server로 redirect
21
21
"""
22
- kakao_login_url = "https://kauth.kakao.com/oauth/authorize"
23
- query_param = {
24
- "client_id" : Config .Kakako .ACCESS_KEY ,
25
- "redirect_uri" : Config .Kakako .REDIRECT_URI ,
26
- "response_type" : "code" ,
27
- }
28
- return RedirectResponse (
29
- kakao_login_url + "?" + utils .build_query_param (query_param )
22
+ kakao_auth_url = (
23
+ f"https://kauth.kakao.com/oauth/authorize"
24
+ f"?client_id={ Config .Kakako .ACCESS_KEY } "
25
+ f"&redirect_uri={ Config .Kakako .REDIRECT_URI } "
26
+ f"&response_type=code"
30
27
)
28
+ return RedirectResponse (url = kakao_auth_url )
31
29
32
-
30
+
33
31
@router .get ("/authenticate" )
34
- async def auhtenticate (
35
- response : Response ,
32
+ async def authenticate (
33
+ response : Response ,
36
34
user_repo : Annotated [UserRepository , Depends (get_user_repository )],
37
35
code : str | None = None ,
38
36
error : str | None = None ,
39
37
error_description : str | None = None ,
40
- ) -> JwtResponse :
38
+ ) -> dict :
41
39
"""
42
- (참고) 인증 흐름
43
- 1. /login 에서 kauth.kakako.com/oauth/authroize로 redirect
44
- 2. 카카오톡 서버에서 이 api를 호출하며 query param으로 인증코드와 에러 코드들을 넘겨준다.
45
-
46
- 책임
47
- - 카카오톡 서버로부터 전달받은 인증코드로 access_token 요청 보내기
48
- - access_token으로 user info 요청 보내기
49
- :param
50
- code: 카카오톡 access_token 인증코드
40
+ Callback function for handling OAuth with Kakao.
51
41
"""
52
42
if not code :
53
43
raise HTTPException (
54
- status_code = 400 , detail = {"error" : error , "error_desc" : error_description }
44
+ status_code = 400 ,
45
+ detail = {
46
+ "error" : error or "Authorization code missing" ,
47
+ "error_description" : error_description or "No further details provided" ,
48
+ },
55
49
)
56
50
57
- access_token : str = request_access_token (
58
- redirect_uri = Config .Kakako .REDIRECT_URI ,
59
- auth_code = code ,
60
- client_id = Config .Kakako .ACCESS_KEY ,
61
- )["access_token" ]
62
- user_kakao_id : int = int (request_user_info (access_token )["id" ])
63
-
64
- # register new user
65
- # user: User = User(kakao_id=user_id, username="foo", nickname="foo")
66
- user : User | None = user_repo .find_by_kakao_id (user_kakao_id )
67
- if user is None :
68
- user = User (kakao_id = user_kakao_id , username = "foo" , nickname = "foo" )
69
- user_repo .insert (user )
70
-
71
- if user .id is None :
72
- raise Exception ("user id must not be None" )
73
-
74
- # TODO: expire and path
75
- jwt_token = JwtAuth .create_token (user .id )
76
-
77
- # 5. JWT를 HttpOnly 쿠키에 저장
78
- response .set_cookie (
79
- key = "access_token" , # 쿠키 이름
80
- value = jwt_token , # JWT 토큰 값
81
- httponly = True , # HttpOnly 속성 (JS에서 접근 불가)
82
- secure = False , # HTTPS 환경에서 True로 설정
83
- samesite = "Lax" , # CSRF 방지
84
- max_age = 3600 , # 쿠키 만료 시간 (초)
85
- )
51
+ try :
52
+ # Step 1: Exchange the authorization code for an access token
53
+ access_token : str = request_access_token (
54
+ redirect_uri = Config .Kakao .REDIRECT_URI ,
55
+ auth_code = code ,
56
+ client_id = Config .Kakao .ACCESS_KEY ,
57
+ )["access_token" ]
58
+
59
+ # Step 2: Fetch user info from Kakao API
60
+ user_info = request_user_info (access_token )
61
+ user_kakao_id : int = int (user_info ["id" ])
62
+ username = user_info .get ("properties" , {}).get ("nickname" , "default_username" )
63
+
64
+ # Step 3: Register user if not exists
65
+ user = user_repo .find_by_kakao_id (user_kakao_id )
66
+ if user is None :
67
+ user = User (kakao_id = user_kakao_id , username = username , nickname = username )
68
+ user_repo .insert (user )
69
+
70
+ if user .id is None :
71
+ raise Exception ("User ID must not be None after insertion" )
72
+
73
+ # Step 4: Create JWT token
74
+ jwt_token = JwtAuth .create_token (user .id )
75
+
76
+ # Step 5: Set the token in an HttpOnly cookie
77
+ response .set_cookie (
78
+ key = "access_token" ,
79
+ value = jwt_token ,
80
+ httponly = True ,
81
+ secure = False , # Set to True in production with HTTPS
82
+ samesite = "Lax" ,
83
+ max_age = 3600 ,
84
+ )
86
85
87
- # 6. 프론트엔드 대시보드로 리디렉션
88
- return RedirectResponse (url = "http://localhost:8001" )
86
+ # Step 6: Redirect to frontend dashboard or return a response
87
+ return {"message" : "Authentication successful" , "user" : {"id" : user .id , "nickname" : user .nickname }}
88
+
89
+ except HTTPException as http_exc :
90
+ raise http_exc
91
+ except Exception as exc :
92
+ raise HTTPException (status_code = 500 , detail = f"Unexpected error: { str (exc )} " )
89
93
90
94
91
95
0 commit comments