Migrate to google credential to authenticate
This commit is contained in:
parent
b21ecd5449
commit
51ffc9a303
3 changed files with 54 additions and 80 deletions
|
|
@ -123,6 +123,11 @@ dependencies {
|
|||
// Splash Screen support prior to Android 12
|
||||
implementation("androidx.core:core-splashscreen:1.0.1")
|
||||
|
||||
// Google Auth
|
||||
implementation("androidx.credentials:credentials:1.2.2")
|
||||
implementation("androidx.credentials:credentials-play-services-auth:1.2.2")
|
||||
implementation("com.google.android.libraries.identity.googleid:googleid:1.1.0")
|
||||
|
||||
// Google service
|
||||
implementation("com.google.android.gms:play-services-auth:21.2.0")
|
||||
implementation(
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.credentials.exceptions.GetCredentialCancellationException
|
||||
import androidx.credentials.exceptions.GetCredentialProviderConfigurationException
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.rplexicon.LocalActivity
|
||||
import com.pixelized.rplexicon.LocalSnack
|
||||
|
|
@ -85,10 +87,9 @@ fun AuthenticationScreen(
|
|||
versionVM: VersionViewModel = hiltViewModel(),
|
||||
onSignIn: CoroutineScope.() -> Unit,
|
||||
) {
|
||||
val snack = LocalSnack.current
|
||||
val context = LocalContext.current
|
||||
val snack = LocalSnack.current
|
||||
val activity = LocalActivity.current
|
||||
val state = authenticationVM.rememberAuthenticationState()
|
||||
|
||||
Surface {
|
||||
PartyBackground()
|
||||
|
|
@ -105,17 +106,22 @@ fun AuthenticationScreen(
|
|||
)
|
||||
|
||||
HandleAuthenticationState(
|
||||
state = state,
|
||||
state = authenticationVM.authenticationState,
|
||||
onProgress = {
|
||||
Dialog(onDismissRequest = { }) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
},
|
||||
onSignIn = onSignIn,
|
||||
onSignInError = {
|
||||
snack.showSnackbar(
|
||||
message = it?.message ?: context.getString(R.string.error__generic)
|
||||
)
|
||||
onSignInError = { exception ->
|
||||
when (exception) {
|
||||
// Ignore user cancellation.
|
||||
is GetCredentialCancellationException -> Unit
|
||||
|
||||
else -> snack.showSnackbar(
|
||||
message = exception?.message ?: context.getString(R.string.error__generic)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,96 +1,59 @@
|
|||
package com.pixelized.rplexicon.ui.screens.authentication
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.IntentSender.SendIntentException
|
||||
import androidx.activity.compose.ManagedActivityResultLauncher
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.IntentSenderRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.credentials.Credential
|
||||
import androidx.credentials.CredentialManager
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import com.google.android.gms.auth.api.identity.GetSignInIntentRequest
|
||||
import com.google.android.gms.auth.api.identity.Identity
|
||||
import com.google.android.gms.auth.api.identity.SignInCredential
|
||||
import com.google.firebase.auth.GoogleAuthProvider
|
||||
import com.google.firebase.auth.ktx.auth
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import androidx.credentials.GetCredentialRequest
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption
|
||||
import com.pixelized.rplexicon.R
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* https://developer.android.com/identity/sign-in/credential-manager-siwg
|
||||
*/
|
||||
@HiltViewModel
|
||||
class AuthenticationViewModel @Inject constructor(
|
||||
application: Application,
|
||||
) : AndroidViewModel(application) {
|
||||
class AuthenticationViewModel @Inject constructor() : ViewModel() {
|
||||
|
||||
private val context: Context get() = getApplication()
|
||||
private var launcher: ManagedActivityResultLauncher<IntentSenderRequest, ActivityResult>? = null
|
||||
|
||||
private val state = mutableStateOf<AuthenticationStateUio>(
|
||||
val authenticationState = mutableStateOf<AuthenticationStateUio>(
|
||||
AuthenticationStateUio.Initial
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun rememberAuthenticationState(): State<AuthenticationStateUio> {
|
||||
launcher = rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartIntentSenderForResult(),
|
||||
onResult = {
|
||||
if (it.resultCode == Activity.RESULT_OK) {
|
||||
state.value = AuthenticationStateUio.Progress
|
||||
// sign in request succeed. retrieve google credential
|
||||
val googleCredential: SignInCredential = Identity
|
||||
.getSignInClient(context)
|
||||
.getSignInCredentialFromIntent(it.data)
|
||||
// build firebase credential
|
||||
val firebaseCredential = GoogleAuthProvider
|
||||
.getCredential(googleCredential.googleIdToken, null)
|
||||
// sign in to Firebase
|
||||
Firebase.auth
|
||||
.signInWithCredential(firebaseCredential)
|
||||
.addOnCompleteListener { task ->
|
||||
if (task.isSuccessful) {
|
||||
state.value = AuthenticationStateUio.Success
|
||||
} else {
|
||||
state.value = AuthenticationStateUio.Failure(task.exception)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.value = AuthenticationStateUio.Initial
|
||||
}
|
||||
},
|
||||
)
|
||||
return state
|
||||
}
|
||||
|
||||
fun signIn(activity: Activity) {
|
||||
state.value = AuthenticationStateUio.Initial
|
||||
val credentialManager = CredentialManager.create(context = activity)
|
||||
|
||||
// build a request to sign in with google credential.
|
||||
// At that point we do only use google sign in service
|
||||
val request: GetSignInIntentRequest = GetSignInIntentRequest.builder()
|
||||
.setServerClientId(context.getString(R.string.google_sign_in_id))
|
||||
val signInWithGoogleOption: GetSignInWithGoogleOption = GetSignInWithGoogleOption
|
||||
.Builder(serverClientId = activity.getString(R.string.google_sign_in_id))
|
||||
.build()
|
||||
|
||||
// use the pre register launcher to start the sign in request intent.
|
||||
Identity.getSignInClient(activity).getSignInIntent(request)
|
||||
.addOnSuccessListener { result ->
|
||||
try {
|
||||
launcher?.launch(
|
||||
IntentSenderRequest.Builder(result.intentSender).build()
|
||||
val request: GetCredentialRequest = GetCredentialRequest.Builder()
|
||||
.addCredentialOption(credentialOption = signInWithGoogleOption)
|
||||
.build()
|
||||
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
withContext(Dispatchers.Main) {
|
||||
authenticationState.value = AuthenticationStateUio.Initial
|
||||
}
|
||||
try {
|
||||
credentialManager.getCredential(
|
||||
request = request,
|
||||
context = activity,
|
||||
)
|
||||
withContext(Dispatchers.Main) {
|
||||
authenticationState.value = AuthenticationStateUio.Success
|
||||
}
|
||||
} catch (exception: Exception) {
|
||||
withContext(Dispatchers.Main) {
|
||||
authenticationState.value = AuthenticationStateUio.Failure(
|
||||
exception = exception,
|
||||
)
|
||||
} catch (exception: SendIntentException) {
|
||||
state.value = AuthenticationStateUio.Failure(exception = exception)
|
||||
}
|
||||
}
|
||||
.addOnFailureListener { exception ->
|
||||
state.value = AuthenticationStateUio.Failure(exception = exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue