I have the following methods that I use to log in with Google -
override fun onClick(view: View?) {
when (view?.id) {
...
R.id.google_login -> {
val signInIntent: Intent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, GOOGLE_LOGIN_REQUEST_CODE)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode != Activity.RESULT_OK || requestCode != GOOGLE_LOGIN_REQUEST_CODE) return
val task: Task<GoogleSignInAccount> = GoogleSignIn.getSignedInAccountFromIntent(data)
val account = task.getResult(ApiException::class.java)
saveAccountData(account)
}
private fun saveAccountData(account: GoogleSignInAccount?) {
if (account == null) {
Toast.makeText(requireContext(), getString(R.string.login_fragment_null_account_error), Toast.LENGTH_SHORT).show()
return
}
if (account.email == null) {
Toast.makeText(requireContext(), getString(R.string.login_fragment_selected_account_has_no_email_error), Toast.LENGTH_LONG).show()
return
}
// This method saves the data in my Firestore DB
viewmodel.registerUser(account).observeOnce(requireActivity(), Observer { error ->
error?.let { message ->
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show()
return@Observer
}
saveAccountToPrefs(account)
navController.navigate(LoginFragmentDirections.actionLoginFragmentToTermsAndConditionsFragment(account.givenName!!))
})
}
private fun saveAccountToPrefs(account: GoogleSignInAccount) {
profileSharedPrefs.edit {
putString(USER_REGISTERED_ID, account.email)
putString(USER_DISPLAY_NAME, account.displayName)
putString(USER_TOKEN, account.id)
putBoolean(DID_USER_REGISTER, true)
}
}
The issue is that, I have the following bad rules for my database -
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if true
}
}
}
and I want to add simple authentication like the following -
// Allow read/write access on all documents to any user signed in to the application
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
So, when trying to configure a custom token like here when I am using the ID (which is an email of the user) I always get an error -
private fun authAndNavigate(directions : NavDirections) {
auth.signInWithCustomToken(profileSharedPrefs.getString(USER_TOKEN, "")!!)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
Toast.makeText(requireContext(), auth.currentUser.toString(), Toast.LENGTH_LONG).show()
navController.navigate(directions)
} else {
Toast.makeText(requireContext(), "Authentication failed, please restart app", Toast.LENGTH_LONG).show()
return@addOnCompleteListener
}
}
.addOnFailureListener { exception ->
exception.localizedMessage?.let { message ->
Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show()
}
}
}
The error I get is -
The custom token format is incorrect. Please check the documentation. [ Invalid assertion format. 3 dot-separated segments required. ]
I could not find any example of how to actually format my ID (which is an email) in a way that would first work and not throw an error and secondly work with the rules I want to implement into my project.
What you get back from Google sign-in is an OAuth credential, which you can use to sign in with Firebase by passing those credentials to signInWithCredential
as shown in step 4 in this documentation on signing in with Firebase with Google auth credentials.
Your code calls signInWithCustomToken
, which expects a custom JWT as minted by code you'd run on your own trusted environment as shown in the documentation on minting custom tokens.
While both types of tokens can be used to authenticate with Firebase, you can't interchange them in API calls.