Skip to content

Commit

Permalink
Merge pull request #360 from PeriodPals/fix/authentication/remove-goo…
Browse files Browse the repository at this point in the history
…gle-auth

Fix/authentication/remove google auth
  • Loading branch information
Harrish92 authored Dec 20, 2024
2 parents 4ec5870 + afa51e5 commit 167b348
Show file tree
Hide file tree
Showing 9 changed files with 0 additions and 317 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,4 @@ interface AuthenticationModel {
onSuccess: (UserInfo) -> Unit,
onFailure: (Exception) -> Unit,
)

/**
* Logs in a user using Google authentication.
*
* This function uses the Google Sign-In SDK to authenticate the user with their Google account.
* It retrieves the user's Google ID token and uses it to sign in with Supabase.
*
* @param googleIdToken The Google ID token of the user.
* @param rawNonce The raw nonce used to sign the user in.
* @param onSuccess Callback function to be called on successful login.
* @param onFailure Callback function to be called on login failure, with the exception as a
* parameter.
*/
suspend fun loginGoogle(
googleIdToken: String,
rawNonce: String?,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import android.util.Log
import io.github.jan.supabase.SupabaseClient
import io.github.jan.supabase.auth.Auth
import io.github.jan.supabase.auth.SignOutScope
import io.github.jan.supabase.auth.providers.Google
import io.github.jan.supabase.auth.providers.builtin.Email
import io.github.jan.supabase.auth.providers.builtin.IDToken
import io.github.jan.supabase.auth.user.UserInfo

private const val TAG = "AuthenticationModelSupabase"
Expand Down Expand Up @@ -144,32 +142,4 @@ class AuthenticationModelSupabase(
onFailure(e)
}
}

/**
* Logs in a user using Google authentication.
*
* @param googleIdToken The Google ID token.
* @param rawNonce The raw nonce.
* @param onSuccess Callback function to be called on successful login.
* @param onFailure Callback function to be called on login failure, with the exception as a
* parameter.
*/
override suspend fun loginGoogle(
googleIdToken: String,
rawNonce: String?,
onSuccess: () -> Unit,
onFailure: (Exception) -> Unit
) {
try {
supabaseAuth.signInWith(IDToken) {
idToken = googleIdToken
provider = Google
nonce = rawNonce
}
onSuccess()
} catch (e: Exception) {
Log.d(TAG, "loginGoogle: failed to log in: ${e.message}")
onFailure(e)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -265,42 +265,6 @@ class AuthenticationViewModel(private val authenticationModel: AuthenticationMod
}
}

/**
* Logs in a user with the provided Google ID token.
*
* @param googleIdToken The Google ID token.
* @param rawNonce The raw nonce.
* @param onSuccess Callback to be invoked when the login is successful.
* @param onFailure Callback to be invoked when the login fails.
*/
fun loginWithGoogle(
googleIdToken: String,
rawNonce: String?,
onSuccess: () -> Unit = { Log.d(TAG, "loginWithGoogle success callback") },
onFailure: (Exception) -> Unit = { e: Exception ->
Log.d(TAG, "loginWithGoogle failure callback: $e")
},
) {
_userAuthenticationState.value = UserAuthenticationState.Loading
viewModelScope.launch {
authenticationModel.loginGoogle(
googleIdToken,
rawNonce,
onSuccess = {
Log.d(TAG, "loginWithGoogle: logged in successfully")
_userAuthenticationState.value =
UserAuthenticationState.Success("Logged in successfully")
onSuccess()
},
onFailure = { e: Exception ->
Log.d(TAG, "loginWithGoogle: failed to log in: $e")
_userAuthenticationState.value = UserAuthenticationState.Error("Error: $e")
onFailure(e)
},
)
}
}

/**
* Generates a hash code from a raw nonce.
*
Expand Down
2 changes: 0 additions & 2 deletions app/src/main/java/com/android/periodpals/resources/C.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,6 @@ object C {
const val SCREEN = "signInScreen"
const val INSTRUCTION_TEXT = "instructionText"
const val SIGN_IN_BUTTON = "signInButton"
const val CONTINUE_WITH_TEXT = "continueWith"
const val GOOGLE_BUTTON = "googleButton"
const val NOT_REGISTERED_NAV_LINK = "notRegisteredButton"
}

Expand Down
127 changes: 0 additions & 127 deletions app/src/main/java/com/android/periodpals/ui/authentication/SignIn.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,14 @@ import android.content.Context
import android.os.Handler
import android.os.Looper
import android.widget.Toast
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
Expand All @@ -25,22 +20,15 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.credentials.CredentialManager
import androidx.credentials.GetCredentialRequest
import androidx.credentials.exceptions.GetCredentialException
import com.android.periodpals.R
import com.android.periodpals.model.authentication.AuthenticationViewModel
import com.android.periodpals.resources.C.Tag.AuthenticationScreens.SignInScreen
import com.android.periodpals.resources.ComponentColor.getFilledPrimaryContainerButtonColors
import com.android.periodpals.services.PushNotificationsServiceImpl
import com.android.periodpals.ui.components.AuthenticationCard
import com.android.periodpals.ui.components.AuthenticationEmailInput
Expand All @@ -53,12 +41,6 @@ import com.android.periodpals.ui.navigation.NavigationActions
import com.android.periodpals.ui.navigation.Screen
import com.android.periodpals.ui.theme.dimens
import com.dsc.form_builder.TextFieldState
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 java.util.UUID
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

private const val DEFAULT_IS_PASSWORD_VISIBLE = false

Expand Down Expand Up @@ -138,19 +120,6 @@ fun SignInScreen(
},
testTag = SignInScreen.SIGN_IN_BUTTON,
)

Text(
modifier =
Modifier.fillMaxWidth()
.wrapContentHeight()
.testTag(SignInScreen.CONTINUE_WITH_TEXT),
text = context.getString(R.string.sign_in_continue_with_text),
color = MaterialTheme.colorScheme.onSurface,
textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyLarge,
)

AuthenticationGoogleButton(context, authenticationViewModel, navigationActions)
}

NavigateBetweenAuthScreens(
Expand All @@ -163,54 +132,6 @@ fun SignInScreen(
}
}

/**
* Composable function that displays a button for Google sign-in.
*
* @param context The context used to show Toast messages.
* @param authenticationViewModel The ViewModel that handles authentication logic.
* @param modifier The modifier to be applied to the button.
*/
@Composable
fun AuthenticationGoogleButton(
context: Context,
authenticationViewModel: AuthenticationViewModel,
navigationActions: NavigationActions,
modifier: Modifier = Modifier,
) {
val coroutineScope = rememberCoroutineScope()
Button(
modifier = modifier.wrapContentSize().testTag(SignInScreen.GOOGLE_BUTTON),
onClick = {
attemptAuthenticateWithGoogle(
context = context,
authenticationViewModel = authenticationViewModel,
navigationActions = navigationActions,
coroutineScope = coroutineScope,
)
},
colors = getFilledPrimaryContainerButtonColors(),
) {
Row(
modifier = Modifier.wrapContentSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement =
Arrangement.spacedBy(MaterialTheme.dimens.small2, Alignment.CenterHorizontally),
) {
Image(
painter = painterResource(id = R.drawable.google_logo),
contentDescription = "Google Logo",
modifier = Modifier.size(MaterialTheme.dimens.iconSize),
)
Text(
modifier = Modifier.wrapContentSize(),
text = context.getString(R.string.sign_in_sign_up_with_google),
fontWeight = FontWeight.Medium,
style = MaterialTheme.typography.bodyMedium,
)
}
}
}

/**
* Attempts to sign in the user with the provided email and password.
*
Expand Down Expand Up @@ -260,51 +181,3 @@ private fun attemptSignIn(
},
)
}

/**
* Attempts to authenticate the user with Google.
*
* @param context The context used to show Toast messages.
* @param authenticationViewModel The ViewModel that handles authentication logic.
* @param navigationActions The navigation actions to navigate between screens.
* @param coroutineScope The coroutine scope to launch the authentication process.
* @return A lambda function to be called on button click.
*/
private fun attemptAuthenticateWithGoogle(
context: Context,
authenticationViewModel: AuthenticationViewModel,
navigationActions: NavigationActions,
coroutineScope: CoroutineScope,
) {
// Create a CredentialManager instance
val credentialManager = CredentialManager.create(context)

val rawNonce = UUID.randomUUID().toString()

// Configure Google ID option
val googleIdOption: GetGoogleIdOption =
GetGoogleIdOption.Builder()
.setFilterByAuthorizedAccounts(false)
.setServerClientId(context.getString(R.string.google_client_id))
.setNonce(authenticationViewModel.generateHashCode(rawNonce))
.build()

// Create a GetCredentialRequest
val request: GetCredentialRequest =
GetCredentialRequest.Builder().addCredentialOption(googleIdOption).build()

// Retrieve the credential
coroutineScope.launch {
try {
val result = credentialManager.getCredential(request = request, context = context)
val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(result.credential.data)
authenticationViewModel.loginWithGoogle(googleIdTokenCredential.idToken, rawNonce)
navigationActions.navigateTo(Screen.EDIT_PROFILE)
Toast.makeText(context, "Successful login", Toast.LENGTH_SHORT).show()
} catch (e: GetCredentialException) {
Toast.makeText(context, "Failed to get Google ID token", Toast.LENGTH_SHORT).show()
} catch (e: GoogleIdTokenParsingException) {
Toast.makeText(context, "Failed to parse Google ID token", Toast.LENGTH_SHORT).show()
}
}
}
2 changes: 0 additions & 2 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
<!-- Sign In Screen -->
<string name="sign_in_instruction">Sign in to your account</string>
<string name="sign_in_button_text">Sign in</string>
<string name="sign_in_continue_with_text">Or continue with</string>
<string name="sign_in_sign_up_with_google">Sign in with Google</string>
<string name="sign_in_no_account_text">Not registered yet?\u00A0</string>
<string name="sign_in_sign_up_text">Sign up here!</string>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import io.github.jan.supabase.auth.Auth
import io.github.jan.supabase.auth.AuthConfig
import io.github.jan.supabase.auth.deepLinkOrNull
import io.github.jan.supabase.auth.providers.builtin.Email
import io.github.jan.supabase.auth.providers.builtin.IDToken
import io.github.jan.supabase.auth.user.UserInfo
import junit.framework.TestCase.assertEquals
import junit.framework.TestCase.fail
Expand Down Expand Up @@ -36,8 +35,6 @@ class AuthenticationModelSupabaseTest {
private val deepLink = "https://example.com"
private val aud = "test_aud"
private val id = "test_id"
private val idToken = "test_token"
private val rawNonce = "test_nonce"
}

@Before
Expand Down Expand Up @@ -175,34 +172,4 @@ class AuthenticationModelSupabaseTest {
onFailure = { assert(true) },
)
}

@Test
fun `login with google success`() = runBlocking {
`when`(auth.signInWith(IDToken)).thenReturn(Unit)

var successCalled = false
authModel.loginGoogle(
idToken,
rawNonce,
{ successCalled = true },
{ fail("Should not call onFailure") },
)
assert(successCalled)
}

@Test
fun `login with google failure`() = runBlocking {
val exception = RuntimeException("Login failed")
doThrow(exception).`when`(auth).signInWith(any<IDToken>(), anyOrNull(), any())

var failureCalled = false
authModel.loginGoogle(
idToken,
rawNonce,
{ fail("Should not call onSuccess") },
{ failureCalled = true },
)

assert(failureCalled)
}
}
Loading

0 comments on commit 167b348

Please sign in to comment.