-
Notifications
You must be signed in to change notification settings - Fork 1
Feature/#155 google login #159
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
7140ecb
acee84e
64504f4
c67b7af
50d9c7e
efabe67
57804bb
a3a96c3
d18d30d
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 | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,88 @@ | ||||||||||||||||||||||||||
| package com.teamsolply.solply.oauth | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| import android.content.Context | ||||||||||||||||||||||||||
| import android.util.Log | ||||||||||||||||||||||||||
| import androidx.credentials.CredentialManager | ||||||||||||||||||||||||||
| import androidx.credentials.CustomCredential | ||||||||||||||||||||||||||
| import androidx.credentials.GetCredentialRequest | ||||||||||||||||||||||||||
| import androidx.credentials.GetCredentialResponse | ||||||||||||||||||||||||||
| import androidx.credentials.exceptions.GetCredentialException | ||||||||||||||||||||||||||
| import com.google.android.libraries.identity.googleid.GetGoogleIdOption | ||||||||||||||||||||||||||
| import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential | ||||||||||||||||||||||||||
| import com.google.android.libraries.identity.googleid.GoogleIdTokenParsingException | ||||||||||||||||||||||||||
| import kotlinx.coroutines.CoroutineScope | ||||||||||||||||||||||||||
| import kotlinx.coroutines.Dispatchers | ||||||||||||||||||||||||||
| import kotlinx.coroutines.launch | ||||||||||||||||||||||||||
| import java.util.UUID | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| class GoogleLoginHelper( | ||||||||||||||||||||||||||
| private val context: Context | ||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| companion object { | ||||||||||||||||||||||||||
| const val TAG = "GoogleLogin" | ||||||||||||||||||||||||||
| const val WEB_CLIENT_ID = com.teamsolply.solply.buildconfig.BuildConfig.GOOGLE_WEB_CLIENT_ID | ||||||||||||||||||||||||||
| // const val SERVER_URL = "" | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| private val credentialManager: CredentialManager = CredentialManager.create(context) | ||||||||||||||||||||||||||
| private val nonce = UUID.randomUUID().toString() | ||||||||||||||||||||||||||
| private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() | ||||||||||||||||||||||||||
| .setServerClientId(WEB_CLIENT_ID) // ์น ํด๋ผ์ด์ธํธ ID | ||||||||||||||||||||||||||
| .setFilterByAuthorizedAccounts(false) | ||||||||||||||||||||||||||
| // .setNonce(nonce) | ||||||||||||||||||||||||||
| .build() | ||||||||||||||||||||||||||
|
Comment on lines
+29
to
+34
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. ๐งฉ Analysis chainNonce ์ฌ์ฉ์ด ๊ถ์ฅ๋ฉ๋๋ค. Line 33์์ Nonce๋ฅผ ํ์ฑํํ์ธ์: private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID) // ์น ํด๋ผ์ด์ธํธ ID
.setFilterByAuthorizedAccounts(false)
-// .setNonce(nonce)
+ .setNonce(nonce)
.build()์๋ฒ ์ธก์์๋ ์ด nonce๋ฅผ ๊ฒ์ฆํ๋๋ก ๊ตฌํํด์ผ ํฉ๋๋ค. ์ด ๋ฆฌ๋ทฐ ์ฝ๋ฉํธ๋ฅผ ๊ฒ์ฆํ๊ธฐ ์ํด ์ ์ฅ์๋ฅผ ๋ถ์ํ๊ณ ์์ต๋๋ค. ์คํฌ๋ฆฝํธ๋ฅผ ์คํ ์ค์ ๋๋ค. ๐ Script executed: #!/bin/bash
# Search for the GoogleLoginHelper file and examine its content
find . -name "GoogleLoginHelper.kt" -type f 2>/dev/null | head -5Length of output: 78 ๐ Script executed: #!/bin/bash
# Search for GetGoogleIdOption imports and usage patterns
rg -n "GetGoogleIdOption" --type kotlin -B3 -A3Length of output: 1907 ๐ Script executed: #!/bin/bash
# Search for nonce-related code and comments in the OAuth module
rg -n "nonce" --type kotlin -i -B2 -A2Length of output: 1167 ๐ Script executed: #!/bin/bash
# Search for server-side validation of nonce
rg -n "nonce" --type java --type kotlin -B2 -A2Length of output: 1167 ๐ Script executed: #!/bin/bash
# Check for build.gradle or pom.xml to identify Google Sign-In library version
find . -name "build.gradle*" -o -name "pom.xml" | xargs grep -l "google\|gms" 2>/dev/null | head -5Length of output: 96 ๐ Script executed: #!/bin/bash
# Search for any comments or documentation explaining why nonce was commented out
rg -n "replay\|setNonce" --type kotlin --type java -B5 -A5Length of output: 0 ๐ Script executed: #!/bin/bash
# Look for server-side token validation logic
rg -n "verify|validate" --type kotlin --type java -i | grep -i "token\|nonce\|jwt\|google" | head -10Length of output: 0 ๐ Script executed: #!/bin/bash
# Check Google Play Services dependency version
find . -name "build.gradle*" | xargs cat 2>/dev/null | grep -A2 -B2 "play.*services.*auth"Length of output: 0 ๐ Script executed: #!/bin/bash
# Search for any authentication verification controller or service
fd -e "\.kt$" -e "\.java$" | xargs grep -l "GoogleIdToken\|idToken\|verify" | head -10Length of output: 0 ๐ Script executed: #!/bin/bash
# Look at the full GoogleLoginHelper.kt file
find . -name "GoogleLoginHelper.kt" -type f 2>/dev/null -exec cat {} \;Length of output: 3518 ๐ Script executed: #!/bin/bash
# Search for server endpoint that might validate Google tokens
rg -n "google.*token\|id.*token" --type kotlin --type java -i | head -15Length of output: 0 ๐ Script executed: #!/bin/bash
# Check if there's documentation or configuration about security settings
find . -name "*.md" -o -name "*.txt" | xargs grep -l "nonce\|security" 2>/dev/null | head -5Length of output: 0 ๐ Script executed: #!/bin/bash
# Search for any existing issue tracker references or TODOs related to nonce
rg -n "TODO|FIXME|XXX" --type kotlin | grep -i "nonce\|security\|replay"Length of output: 0 ๐ Script executed: #!/bin/bash
# Look for Google Sign-In implementation details
rg -n "credentialResponse\|credential" --type kotlin -B3 -A3 | head -30Length of output: 0 ๐ Script executed: #!/bin/bash
# Check for any security-related tests or validation logic
fd -e "Test.kt" -e "Test.java" | xargs grep -l "nonce\|GoogleLogin" 2>/dev/nullLength of output: 0 ๐ Script executed: #!/bin/bash
# Look for the server-side implementation that receives the token
rg -n "id_token\|idToken" --type kotlin --type java | head -15Length of output: 0 ๐ Script executed: #!/bin/bash
# Search for GoogleIdTokenVerifier or similar verification
rg -n "Verifier\|Verify" --type java --type kotlin | grep -i googleLength of output: 0 ๐ Script executed: #!/bin/bash
# Check application properties or configuration for security settings
find . -name "application*.yml" -o -name "application*.properties" | xargs cat 2>/dev/null | grep -i nonceLength of output: 0 ๐ Script executed: #!/bin/bash
# Look at git history to see if nonce was commented intentionally
git log --oneline feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt 2>/dev/null | head -10Length of output: 104 ๐ Script executed: #!/bin/bash
# Check for any existing nonce validation on the backend
rg -n "setNonce\|getNonce\|validateNonce" --type java --type kotlinLength of output: 0 ๐ Script executed: #!/bin/bash
# Look for any comments or documentation files
find . -path "*oauth*" -name "*.md" -o -path "*oauth*" -name "README*" 2>/dev/nullLength of output: 0 ๐ Script executed: #!/bin/bash
# Get broader context about the OAuth implementation
find . -path "*oauth*" -type f \( -name "*.kt" -o -name "*.java" \) | head -20Length of output: 1603 ๐ Script executed: #!/bin/bash
# Check for ID token validation on server
rg -n "verify.*IdToken\|validateIdToken" --type java --type kotlinLength of output: 0 ๐ Script executed: #!/bin/bash
# Search for Google API client library usage
rg -n "GoogleIdTokenVerifier\|TokenVerifier" --type javaLength of output: 0 ๐ Script executed: #!/bin/bash
# Check if there's any exception handling related to nonce
rg -n "NonceException\|InvalidNonce" --type java --type kotlinLength of output: 0 ๐ Script executed: #!/bin/bash
# Look for the complete token exchange process
rg -n "exchange\|credential.*token" --type kotlin -B2 -A2 | head -30Length of output: 0 ๐ Script executed: #!/bin/bash
# Search for server endpoint path that handles token verification
rg -n "@PostMapping\|@GetMapping\|@PutMapping" --type kotlin | grep -i "token\|auth\|google\|login"Length of output: 0 ๐ Script executed: #!/bin/bash
# Check if nonce is being used elsewhere in the codebase
find . -type f \( -name "*.kt" -o -name "*.java" \) -exec grep -l "nonce" {} \;Length of output: 78 ๐ Script executed: #!/bin/bash
# Look for documentation on Google Sign-In requirements
find . -name "*.md" -o -name "*.txt" -o -name "*.adoc" 2>/dev/null | xargs grep -l "Google\|OAuth\|Sign-In" 2>/dev/null | head -5Length of output: 0 ๐ Script executed: #!/bin/bash
# Check for any vulnerability scanning or security audit files
find . -name "*.json" -o -name "*.yaml" | xargs grep -l "security\|vulnerability\|nonce" 2>/dev/null | head -5Length of output: 0 ๐ Script executed: #!/bin/bash
# Get imports from GoogleLoginHelper to understand the library version
rg -n "^import" feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt 2>/dev/null || rg -n "^import" . --type kotlin | grep -i google | head -10Length of output: 709 ๐ Script executed: #!/bin/bash
# Check the Google Sign-In Android library documentation reference
cat build.gradle.kts 2>/dev/null || cat build.gradle 2>/dev/null || find . -name "build.gradle*" -type f | head -1 | xargs catLength of output: 637 ๐ Script executed: #!/bin/bash
# Look for any recent commit messages about nonce
git log --all --grep="nonce" --oneline 2>/dev/null || echo "No git history available"Length of output: 0 ๐ Script executed: #!/bin/bash
# Final check: get the exact structure of the GoogleLoginHelper.kt file around the nonce area
find . -name "GoogleLoginHelper.kt" -type f 2>/dev/null -exec head -50 {} \;Length of output: 1954 ๐ Script executed: #!/bin/bash
# Look for server-side Google token verification configuration
find . -name "*.properties" -o -name "*.yml" -o -name "*.yaml" 2>/dev/null | xargs grep -i "google\|client.*id\|secret" 2>/dev/null | head -15Length of output: 0 ๐ Script executed: #!/bin/bash
# Check for Spring Security or other security framework configuration
rg -n "@EnableWebSecurity\|@Configuration\|securityFilterChain" --type java -B2 -A10 | head -40Length of output: 0 ๐ Script executed: #!/bin/bash
# Search for JWT or token parsing logic
rg -n "JwtDecoder\|verifyIdToken\|parseToken" --type java -B2 -A5Length of output: 0 ๐ Script executed: #!/bin/bash
# Look for Google client library initialization
rg -n "GoogleCredential\|GoogleAuthorizationCodeFlow\|GoogleClientSecrets" --type javaLength of output: 0 ๐ Script executed: #!/bin/bash
# Check if nonce validation happens in a filter or interceptor
rg -n "OncePerRequestFilter\|HandlerInterceptor" --type java -B2 -A10Length of output: 0 ๐ Script executed: #!/bin/bash
# Get comprehensive view of OAuth module structure
find feature/oauth -type f 2>/dev/null | head -30Length of output: 525 ๐ Script executed: #!/bin/bash
# Look at documentation or SECURITY.md files
find . -iname "*security*" -type f 2>/dev/null | head -10Length of output: 0 ๐ Script executed: #!/bin/bash
# Check for any architecture decision records or ADRs
find . -iname "*adr*" -o -iname "*decision*" -type f 2>/dev/null | head -10Length of output: 94 ๐ Script executed: #!/bin/bash
# Final comprehensive search for nonce implementation
rg -rn "nonce" --type-list 2>/dev/null | head -5
rg -rn "nonce" . 2>/dev/null | head -20Length of output: 229 ๐ Script executed: #!/bin/bash
# Check if setNonce is available in the GetGoogleIdOption API
rg -n "GetGoogleIdOption" . --type kotlin -A20 2>/dev/null | head -40Length of output: 4825 ๐ Script executed: #!/bin/bash
# Look for version constraints or documentation
cat README.md 2>/dev/null | grep -i "google\|oauth\|security" || echo "No README or no matches"Length of output: 71 ๐ Script executed: #!/bin/bash
# Check all files in the OAuth feature module
ls -la feature/oauth/ 2>/dev/null || find . -path "*oauth*" -type d | head -5Length of output: 289 ๐ Script executed: #!/bin/bash
# Last attempt - find the exact file and show context
find . -name "GoogleLoginHelper.kt" 2>/dev/null -exec echo "=== File: {} ===" \; -exec cat {} \;Length of output: 3611 ๐ Script executed: #!/bin/bash
# Check for Google Play Services version in dependencies
rg -n "com\.google\.android\.gms" . --type kotlin --type java | head -10Length of output: 306 ๐ Script executed: #!/bin/bash
# Look for version strings
rg -n "gms:play-services.*auth" . | head -5Length of output: 0 ๐ Script executed: #!/bin/bash
# Check if there's a docs folder
find . -type d -name "docs" -o -type d -name "documentation" 2>/dev/nullLength of output: 0 ๐ Script executed: #!/bin/bash
# Search for any CHANGELOG or release notes
find . -iname "CHANGELOG*" -o -iname "RELEASE*" 2>/dev/null | xargs grep -i nonce 2>/dev/nullLength of output: 0 ๐ Script executed: #!/bin/bash
# Verify the exact lines mentioned in the review
sed -n '29,34p' feature/oauth/src/main/java/com/teamsolply/solply/oauth/GoogleLoginHelper.kt 2>/dev/null || echo "File path may differ"Length of output: 278 ๐ Web query: ๐ก Result: setNonce is a method on GetGoogleIdOption.Builder that sets the nonce used when generating a Google ID token. Use it when you build GetGoogleIdOption to have the ID token include the provided nonce. Example (Kotlin): Docs: GetGoogleIdOption.Builder (method: setNonce). [1][2] Sources ๐ Web query: ๐ก Result: Yes โ GetGoogleIdOption.Builder has a setNonce(...) method. It accepts a String nonce and sets the nonce used when generating the Google ID token. Signatures / usage examples:
Example (Kotlin): Sources: ๐ Web query: ๐ก Result: Short answer โ use Googleโs nonce support + server-side single-use verification and device attestation: Key points and recommended implementation
Quick checklist
Sources Nonce ํ์ฑํ ๋ฐ ์๋ฒ ์ธก ๊ฒ์ฆ ๊ตฌํ ํ์ ํด๋ผ์ด์ธํธ: ์๋ฒ: ์ ์ฅ์ ๊ฒ์ ๊ฒฐ๊ณผ nonce ๊ฒ์ฆ ๋ก์ง์ด ์กด์ฌํ์ง ์์ต๋๋ค. Google ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด ์๋ฒ๋ ID ํ ํฐ์ nonce ํด๋ ์์ ๋ฐ๊ธ๋ nonce์ ๋น๊ตํ์ฌ ๊ฒ์ฆํด์ผ ํ๋ฉฐ, ๊ฐ nonce๋ ๋จ์ผ ์ฌ์ฉ ์ฉ๋๋ก ์ทจ๊ธ๋์ด์ผ ํฉ๋๋ค. private val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder()
.setServerClientId(WEB_CLIENT_ID) // ์น ํด๋ผ์ด์ธํธ ID
.setFilterByAuthorizedAccounts(false)
-// .setNonce(nonce)
+ .setNonce(nonce)
.build()์๋ฒ ์ธก์์ ์ด nonce๋ฅผ ID ํ ํฐ์ nonce ํด๋ ์๊ณผ ๋์กฐํ์ฌ ๊ฒ์ฆํ๋ ๋ก์ง์ ๊ตฌํํด์ผ ํฉ๋๋ค. ๐ Committable suggestion
Suggested change
๐ค Prompt for AI Agents |
||||||||||||||||||||||||||
| private val request: GetCredentialRequest = GetCredentialRequest.Builder() | ||||||||||||||||||||||||||
| .addCredentialOption(googleIdOption) | ||||||||||||||||||||||||||
| .build() | ||||||||||||||||||||||||||
| private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Main) | ||||||||||||||||||||||||||
|
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. ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ณ ๋ คํ์ง ์์ CoroutineScope๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค.
๋ค์ ์ค ํ๋๋ฅผ ์ ์ฉํ์ธ์:
class GoogleLoginHelper(
private val context: Context,
private val scope: CoroutineScope
)
// Usage: GoogleLoginHelper(context, lifecycleScope)
private val job = SupervisorJob()
private val coroutineScope = CoroutineScope(Dispatchers.Main + job)
fun dispose() {
job.cancel()
}๐ค Prompt for AI Agents |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| fun requestGoogleLogin( | ||||||||||||||||||||||||||
| onSuccess: (String) -> Unit, | ||||||||||||||||||||||||||
| onFailure: (String) -> Unit | ||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||
| coroutineScope.launch { | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| val result = credentialManager.getCredential( | ||||||||||||||||||||||||||
| request = request, | ||||||||||||||||||||||||||
| context = context | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| handleSignInResult(result, onSuccess, onFailure) | ||||||||||||||||||||||||||
| } catch (e: GetCredentialException) { | ||||||||||||||||||||||||||
| Log.e("Google Sign-in failed", " ${e.localizedMessage}") | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+51
to
+54
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. ์๋ฌ ๋ฐ์ ์ onFailure ์ฝ๋ฐฑ์ด ํธ์ถ๋์ง ์์ต๋๋ค.
๋ค์๊ณผ ๊ฐ์ด ์์ ํ์ธ์: } catch (e: GetCredentialException) {
Log.e("Google Sign-in failed", " ${e.localizedMessage}")
+ onFailure(e.localizedMessage ?: "๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ์คํจํ์์ต๋๋ค.")
}๐ Committable suggestion
Suggested change
๐ค Prompt for AI Agents |
||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| private fun handleSignInResult( | ||||||||||||||||||||||||||
| result: GetCredentialResponse, | ||||||||||||||||||||||||||
| onSuccess: (String) -> Unit, | ||||||||||||||||||||||||||
| onFailure: (String) -> Unit | ||||||||||||||||||||||||||
| ) { | ||||||||||||||||||||||||||
| when (val credential = result.credential) { | ||||||||||||||||||||||||||
| is CustomCredential -> { | ||||||||||||||||||||||||||
| if (credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| val googleIdTokenCredential = | ||||||||||||||||||||||||||
| GoogleIdTokenCredential.createFrom(credential.data) | ||||||||||||||||||||||||||
| val idToken = googleIdTokenCredential.idToken | ||||||||||||||||||||||||||
| // Log.d(TAG, idToken) //ํ ํฐ | ||||||||||||||||||||||||||
| // Log.d(TAG, googleIdTokenCredential.id) //์ด๋ฉ์ผ | ||||||||||||||||||||||||||
| // googleIdTokenCredential.displayName?.let { Log.d(TAG, it) } //์ด๋ฆ | ||||||||||||||||||||||||||
| onSuccess(idToken) // ์ฑ๊ณต ์ ์ฒ๋ฆฌ ํจ์, ์๋ฒ ์๋ต ํ ์คํ, ์ฌ๊ธฐ์๋ ํ ์คํธ๋ฅผ ์ํด ์ด๊ณณ์์ ์คํ | ||||||||||||||||||||||||||
| } catch (e: GoogleIdTokenParsingException) { | ||||||||||||||||||||||||||
| // Log.e(TAG, "Received an invalid google id token response", e) | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
Comment on lines
+73
to
+75
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. ์์ธ๊ฐ ์ผ์ผ์ง๊ณ ์์ต๋๋ค.
์์ธ ๋ฐ์ ์ ์คํจ ์ฝ๋ฐฑ์ ํธ์ถํ์ธ์: } catch (e: GoogleIdTokenParsingException) {
-// Log.e(TAG, "Received an invalid google id token response", e)
+ Log.e(TAG, "Received an invalid google id token response", e)
+ onFailure("๊ตฌ๊ธ ๋ก๊ทธ์ธ ํ ํฐ ํ์ฑ์ ์คํจํ์์ต๋๋ค.")
}๐ Committable suggestion
Suggested change
๐งฐ Tools๐ช detekt (1.23.8)[warning] 73-73: The caught exception is swallowed. The original exception could be lost. (detekt.exceptions.SwallowedException) ๐ค Prompt for AI Agents |
||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||
| // Log.e(TAG, "Unexpected type of credential") | ||||||||||||||||||||||||||
| onFailure("๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ์คํจํ์์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.") | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| else -> { | ||||||||||||||||||||||||||
| // Log.e(TAG, "Unexpected type of credential") | ||||||||||||||||||||||||||
| onFailure("๊ตฌ๊ธ ๋ก๊ทธ์ธ์ ์คํจํ์์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์.") | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ import androidx.compose.material3.Icon | |
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.getValue | ||
| import androidx.compose.runtime.remember | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.Color | ||
|
|
@@ -46,6 +47,7 @@ fun OauthRoute( | |
| viewModel: OauthViewModel = hiltViewModel() | ||
| ) { | ||
| val context = LocalContext.current | ||
| val googleLoginHelper = remember { GoogleLoginHelper(context = context) } | ||
| val uiState by viewModel.uiState.collectAsStateWithLifecycle() | ||
|
|
||
| LaunchedEffectWithLifecycle { | ||
|
|
@@ -63,20 +65,46 @@ fun OauthRoute( | |
| } | ||
| ) | ||
|
|
||
| OauthSideEffect.StartGoogleLogin -> googleLoginHelper.requestGoogleLogin( | ||
| onSuccess = { accessToken -> | ||
| viewModel.sendIntent( | ||
| OauthIntent.GoogleLoginSuccess( | ||
| provider = "GOOGLE", | ||
| accessToken = accessToken | ||
| ) | ||
| ) | ||
| }, | ||
| onFailure = {} | ||
|
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. ์๋ฌ ์ฒ๋ฆฌ๊ฐ ๋๋ฝ๋์์ต๋๋ค.
์์: onFailure = { errorMessage ->
Log.e("OauthScreen", "Google login failed: $errorMessage")
// TODO: Show error message to user
}Also applies to: 98-98 ๐ค Prompt for AI Agents |
||
| ) | ||
|
|
||
|
Comment on lines
+68
to
+79
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. ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๋ก์ง์ด ์ค๋ณต๋์ด ์์ต๋๋ค. ๊ตฌ๊ธ ๋ก๊ทธ์ธ ๋ก์ง์ด ๋ ๊ณณ์ ์ค๋ณต ๊ตฌํ๋์ด ์์ต๋๋ค:
์ด๋ ์๋ํ์ง ์์ ๋์์ ์ ๋ฐํ ์ ์์ต๋๋ค. ์นด์นด์ค ๋ก๊ทธ์ธ๊ณผ ๋์ผํ๊ฒ ViewModel์ ํตํ ๋จ์ผ ํ๋ก์ฐ๋ง ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค. ๋ค์๊ณผ ๊ฐ์ด ์์ ํ์ฌ ์นด์นด์ค ๋ก๊ทธ์ธ๊ณผ ์ผ๊ด๋ ํจํด์ ์ ์งํ์ธ์: OauthScreen(
kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) },
- googleLoginClick = {
- googleLoginHelper.requestGoogleLogin(
- onSuccess = { accessToken ->
- viewModel.sendIntent(
- OauthIntent.GoogleLoginSuccess(
- provider = "GOOGLE",
- accessToken = accessToken
- )
- )
- },
- onFailure = {}
- )
- }
+ googleLoginClick = { viewModel.sendIntent(OauthIntent.GoogleLoginClick) }
)Also applies to: 88-100 ๐ค Prompt for AI Agents |
||
| OauthSideEffect.NavigateToOnBoarding -> navigateToOnBoarding() | ||
| OauthSideEffect.NavigateToPlace -> navigateToPlace() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| OauthScreen( | ||
| kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) } | ||
| kakaoLoginClick = { viewModel.sendIntent(OauthIntent.KakaoLoginClick) }, | ||
| googleLoginClick = { | ||
| googleLoginHelper.requestGoogleLogin( | ||
| onSuccess = { accessToken -> | ||
| viewModel.sendIntent( | ||
| OauthIntent.GoogleLoginSuccess( | ||
| provider = "GOOGLE", | ||
| accessToken = accessToken | ||
| ) | ||
| ) | ||
| }, | ||
| onFailure = {} | ||
| ) | ||
| } | ||
| ) | ||
| } | ||
|
|
||
| @Composable | ||
| fun OauthScreen( | ||
| kakaoLoginClick: () -> Unit, | ||
| googleLoginClick: () -> Unit, | ||
| modifier: Modifier = Modifier | ||
| ) { | ||
| Column( | ||
|
|
@@ -157,7 +185,7 @@ fun OauthScreen( | |
| .customClickable( | ||
| rippleEnabled = false | ||
| ) { | ||
| kakaoLoginClick() | ||
| googleLoginClick() | ||
| }, | ||
| verticalAlignment = Alignment.CenterVertically, | ||
| horizontalArrangement = Arrangement.Start | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,17 @@ class OauthViewModel @Inject constructor( | |
| TODO() | ||
| } | ||
|
|
||
| OauthIntent.GoogleLoginClick -> postSideEffect(OauthSideEffect.StartGoogleLogin) | ||
|
|
||
| is OauthIntent.GoogleLoginSuccess -> postSocialLogin( | ||
| provider = intent.provider, | ||
| oauthAccessToken = intent.accessToken | ||
| ) | ||
|
|
||
| is OauthIntent.GoogleLoginFailure -> { | ||
| TODO() | ||
| } | ||
|
Comment on lines
+27
to
+36
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. Google ๋ก๊ทธ์ธ ์คํจ ์ฒ๋ฆฌ๋ฅผ ๊ตฌํํด์ผ ํฉ๋๋ค. Google ๋ก๊ทธ์ธ ํ๋ฆ์ด ์ถ๊ฐ๋์์ผ๋ ์ฌ์ฉ์์๊ฒ ์ ์ ํ ์๋ฌ ๋ฉ์์ง๋ฅผ ํ์ํ๊ฑฐ๋ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ๋ฑ์ ์๋ฌ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค. Kakao ๋ก๊ทธ์ธ ์คํจ ์ฒ๋ฆฌ๋ ๋์ผํ๊ฒ ๐ค Prompt for AI Agents |
||
|
|
||
| is OauthIntent.SaveJwtToken -> { | ||
| viewModelScope.launch { | ||
| oauthRepository.saveJwtToken( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -90,6 +90,8 @@ coil = "2.7.0" | |
| lottie = "6.4.1" | ||
| jsoup = "1.17.2" | ||
| kakao-login = "2.19.0" | ||
| credentials = "1.6.0-beta03" | ||
| googleid = "1.1.1" | ||
|
Comment on lines
+93
to
+94
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. ๐งฉ Analysis chain๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฒ์ ํ์ธ์ด ํ์ํฉ๋๋ค.
๋ค์ ๋ช ๋ น์ผ๋ก ์ต์ ์์ ๋ฒ์ ์ ํ์ธํ์ธ์: ๐ Web query: ๐ก Result: The latest stable release is androidx.credentials:credentials version 1.5.0 (released March 12, 2025). [1] Sources ์ต์ ์ ๋ณด๋ฅผ ํ์ธํ๊ธฐ ์ํด ์ถ๊ฐ ๊ฒ์์ด ํ์ํฉ๋๋ค. ํ๋ก๋์
ํ๊ฒฝ์์๋ ์์ ๋ฒ์ ( ์ฝ๋๊ฐ ์์ง ๋ฒ ํ ๋จ๊ณ์ธ
๐ค Prompt for AI Agents |
||
| process-pheonix = "3.0.0" | ||
| preference = "1.2.1" | ||
| collapsing-toolbar = "2.3.5" | ||
|
|
@@ -253,6 +255,11 @@ lottie = { group = "com.airbnb.android", name = "lottie", version.ref = "lottie" | |
| lottie-compose = { group = "com.airbnb.android", name = "lottie-compose", version.ref = "lottie" } | ||
| jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoup" } | ||
| kakao-login = { group = "com.kakao.sdk", name = "v2-user", version.ref = "kakao-login" } | ||
|
|
||
| credentials = { module = "androidx.credentials:credentials", version.ref = "credentials" } | ||
| credentials-play-auth = { module = "androidx.credentials:credentials-play-services-auth", version.ref = "credentials" } | ||
| google-id = { module = "com.google.android.libraries.identity.googleid:googleid", version.ref = "googleid" } | ||
|
|
||
| process-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "process-pheonix" } | ||
| collapsing-toolbar = { group = "me.onebone", name = "toolbar-compose", version.ref = "collapsing-toolbar" } | ||
| androidx-runtime-android = { group = "androidx.compose.runtime", name = "runtime-android", version.ref = "runtimeAndroid" } | ||
|
|
||
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.
๐งฉ Analysis chain
ProGuard ๊ท์น์ด ์ง๋์น๊ฒ ๊ด๋ฒ์ํ ์ ์์ต๋๋ค.
ํ์ฌ ๊ท์น์ด ๋งค์ฐ ๋์ ๋ฒ์๋ฅผ ์ ์งํ๊ณ ์์ต๋๋ค:
* extends TypeAdapter: ๋ชจ๋ TypeAdapter ์๋ธํด๋์ค ์ ์งcom.google.googlesignin.** { *; }: ๋ชจ๋ Google Sign-In ํด๋์ค์ ๋ฉค๋ฒ ์ ์ง์ด๋ ๋๋ ํ๋ฅผ ๋ฐฉํดํ๊ณ APK ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ์ํฌ ์ ์์ต๋๋ค. Google Sign-In Credential Manager API๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ๋ ๊ตฌ์ฒด์ ์ธ ๊ท์น์ผ๋ก ์ถฉ๋ถํ ์ ์์ต๋๋ค.
๋ค์ ์คํฌ๋ฆฝํธ๋ก ์ค์ ์ฌ์ฉ๋๋ Google Sign-In ํด๋์ค๋ฅผ ํ์ธํ์ธ์:
๐ Script executed:
Length of output: 1223
๐ Script executed:
Length of output: 0
๐ Script executed:
Length of output: 0
๐ Script executed:
Length of output: 847
๐ Script executed:
Length of output: 0
๐ Script executed:
Length of output: 52
๐ Script executed:
Length of output: 0
์ฌ์ฉ๋์ง ์๋ ProGuard ๊ท์น์ ์ ๊ฑฐํ์ธ์.
๊ฒ์ฆ ๊ฒฐ๊ณผ, ์ฝ๋๋ฒ ์ด์ค ์ด๋์์๋ ๋ค์์ด ์ฌ์ฉ๋์ง ์์ต๋๋ค:
com.google.googlesigninํจํค์ง (๊ฒ์ ๊ฒฐ๊ณผ: 0๊ฑด)TypeAdapterํด๋์ค (๊ฒ์ ๊ฒฐ๊ณผ: 0๊ฑด)ํ์ฌ ๊ตฌํ์
com.google.android.libraries.identity.googleid(Credential Manager API)๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๋ผ์ธ 23-24์ ๊ท์น์ ๋ ์ด์ ํ์ํ์ง ์์ ๋ ๊ฑฐ์ Google Sign-In SDK ๊ด๋ จ ๊ท์น์ ๋๋ค.์ด ๊ท์น๋ค์ ์ ๊ฑฐํ๋ฉด APK ํฌ๊ธฐ๋ฅผ ์ค์ด๊ณ ์ ์ ํ ๋๋ ํ๊ฐ ๊ฐ๋ฅํฉ๋๋ค:
๐ค Prompt for AI Agents