-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature] 구글 로그인 구현 #27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1d7f0ec
901c709
8dd8cc6
4683f3a
b8e2c54
2c973c3
89204f5
5161110
0c7e6de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| ### Configuration ### | ||
| Configuration/ | ||
|
|
||
| ### Firebase ### | ||
| GoogleService-Info*.plist | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,21 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict/> | ||
| <dict> | ||
| <key>GIDClientID</key> | ||
| <string>$(GID_CLIENT)</string> | ||
| <key>CFBundleURLTypes</key> | ||
| <array> | ||
| <dict> | ||
| <key>CFBundleTypeRole</key> | ||
| <string>Editor</string> | ||
| <key>CFBundleURLName</key> | ||
| <string>$(URL_SCHEMES)</string> | ||
| <key>CFBundleURLSchemes</key> | ||
| <array> | ||
| <string>$(URL_SCHEMES)</string> | ||
| </array> | ||
| </dict> | ||
| </array> | ||
| </dict> | ||
| </plist> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -110,6 +110,7 @@ private struct SignInButtonList: View { | |
|
|
||
| SignInButton(provider: .google) { | ||
| // TODO: 구글 로그인 로직 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 주석 제거 필요 |
||
| loginViewModel.send(.googleLoginButtonTapped) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ import AuthenticationServices | |
| import SwiftUI | ||
|
|
||
| import FirebaseAuth | ||
| import GoogleSignIn | ||
|
|
||
| import Util | ||
|
|
||
|
|
@@ -21,6 +22,7 @@ final class LoginViewModel: Reducer { | |
|
|
||
| enum Action { | ||
| case appleLoginButtonTapped(AuthorizationController) | ||
| case googleLoginButtonTapped | ||
|
|
||
| case signInError(SignInError) | ||
|
|
||
|
|
@@ -48,15 +50,15 @@ final class LoginViewModel: Reducer { | |
| return .run { [nonce = requestProvider.currentNonce] in | ||
|
|
||
| /// 중간에 로그인을 취소하거나, 애플 로그인 인증 방식이 아닌 경우는 빈 액션 반환 | ||
| /// (에러 상황은 아니고, 어떠한 액션을 던질 필요가 없음) | ||
| /// (에러 상황은 아니기 때문에 어떠한 액션을 던질 필요가 없음) | ||
| guard let result = try? await authController.performRequest(request), | ||
| case let .appleID(idCredential) = result else { return .empty } | ||
|
|
||
| /// 애플 로그인 정보에 필요한 정보들이 누락되는 경우 | ||
| guard let nonce, | ||
| let appleIDToken = idCredential.identityToken, | ||
| let idTokenString = String(data: appleIDToken, encoding: .utf8) else { | ||
| return .signInError(.invalid) | ||
| return .signInError(.missingData) | ||
| } | ||
|
|
||
| /// Firebase 인증 요청을 위한 AuthCredential 생성 | ||
|
|
@@ -69,11 +71,39 @@ final class LoginViewModel: Reducer { | |
| return .firebaseAuthRequest(credential) | ||
| } | ||
|
|
||
| // TODO: 에러 처리 필요 | ||
| case .googleLoginButtonTapped: | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메서드 분리하면 좋을 것 같아요 |
||
| guard let windowScene = NSApplication.shared.windows.first else { | ||
| return .none | ||
| } | ||
|
|
||
| return .run { | ||
| do { | ||
| /// 구글 로그인 요청 | ||
| let result = try await GIDSignIn.sharedInstance.signIn(withPresenting: windowScene) | ||
|
|
||
| /// 로그인에 필요한 정보(IDToken)가 누락된 경우 | ||
| guard let idToken = result.user.idToken?.tokenString else { | ||
| return .signInError(.missingData) | ||
| } | ||
|
|
||
| /// Firebase 인증 요청을 위한 AuthCredential 생성 | ||
| let credential = GoogleAuthProvider.credential( | ||
| withIDToken: idToken, | ||
| accessToken: result.user.accessToken.tokenString | ||
| ) | ||
|
|
||
| return .firebaseAuthRequest(credential) | ||
| } catch { | ||
| return .signInError(.invalid) | ||
| } | ||
| } | ||
|
|
||
| // TODO: 에러 처리 필요 | ||
| case .signInError(_): | ||
| return .none | ||
|
|
||
| // TODO: 현재는 러프하고 구현된 상태. 구글 로그인까지 구현 후 디테일 수정 | ||
| // TODO: 구글 로그인까지 구현 후 디테일 수정 | ||
| case .firebaseAuthRequest(let credential): | ||
| return .run { | ||
| do { | ||
|
|
@@ -109,14 +139,15 @@ final class LoginViewModel: Reducer { | |
| case .run(let action): | ||
| Task { | ||
| let newAction = await action() | ||
| send(newAction) | ||
| await send(newAction) | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| extension LoginViewModel { | ||
| enum SignInError: Error { | ||
| case missingData | ||
| case invalid | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2개 이상일 때 체크