I have an app that get Google credentials in order to register user into my API. I need the idToken provided by the Google flow.
Following this tutorial, I was able to sign in.
Then, I have a splash screen. I want it to verify if the user is already allowed by Google, to go to the main activity. If not, go to the login activity.
But according to the tutorial's code, it is asking Firebase using the code below, which provides me, of course, a Firebase token, not the Google one.
override fun onStart() {
super.onStart()
val user = FirebaseAuth.getInstance().currentUser
if (user != null) {
startActivity(MainActivity.getLaunchIntent(this))
finish()
}
}
So, the question is: how can I get the Google information to retrieve the token, so my API can validate if the token?
If someone else need to implements something alike, I'll share how I did it.
There is a silentSignIn from Google SDK which allows to do it.
So, this is the code:
val signInOptions = getSignInOptions(this)
val googleSignInClient = GoogleSignIn.getClient(this, signInOptions)
googleSignInClient.silentSignIn().addOnCompleteListener {
val account: GoogleSignInAccount? = it.result
if (account != null) {
// success
}
else {
// failure
}
}
Related
hi guys i'm trying to do auto login in my app but before login done i wonder if the user verified his email or no.
the problem : even if i verified my account the code doesn't see this and said false.
and here is my code.
class SignInActivity : BaseActivity<SignInViewModel, ActivitySignInBinding>(), Navigator {
private lateinit var preferenceManger: PreferenceManger
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
preferenceManger = PreferenceManger(applicationContext)
autoLogin()
binding.vm = viewModel
viewModel.navigator = this
addPrefManger()
}
private fun autoLogin() {
DataUtils.firebaseUser = Firebase.auth.currentUser
if (preferenceManger.getBoolean(Constants.KEY_IS_SIGNED_IN)) {
when {
DataUtils.firebaseUser!!.isEmailVerified -> {
startActivity(Intent(this, HomeActivity::class.java))
finish()
}
else -> {
startActivity(Intent(this, VerificationActivity::class.java))
finish()
}
}
}
}
this line is always false even if i verified my account.
DataUtils.firebaseUser!!.isEmailVerified
While the verification status of the user profile is updated on the server as soon as they've clicked the link, it may take up to an hour before that information is synchronized to the Android app.
If you want to detect the email verification in the app before it is automatically synchronized, you can:
Sign the user out and in again.
Force reloading of the user profile (after the user has clicked the link) by calling reload on the user object. You can put a button in your UI to do this, or automatically call that, for example in the onResume of the activity.
Also see:
How to verify email without the need of signing in again while using FirebaseUI-auth?
Verification email activity not refreshing
I've followed the guides on https://developers.google.com/identity/sign-in/android/sign-in and I can get the Google ID token of the signed in user after the user signed in. But token will expires in 1 hour.
How can I refresh a valid Google ID token after the old one expires, without bothering user to manually sign in again and again? I have tried using silent sign-in when token expires. But it doesn't seem to work. Is there any way to get a valid Google ID token? Thanks in advance!!
For first time signing in,
private fun handleSignInResult(completedTask: Task<GoogleSignInAccount>) {
try {
val account = completedTask.getResult(ApiException::class.java)
val idToken = account!!.idToken
CheckDB(this, db).execute()
} catch (e: ApiException) {
Log.e("TAG","signInResult:failed code=" + e.statusCode)
}
}
when token expires, I am using silent signin
override fun onStart() {
super.onStart()
val account = GoogleSignIn.getLastSignedInAccount(this)
if(account!=null) {
sign_in_button.visibility = GONE
mGoogleSignInClient!!.silentSignIn().addOnCompleteListener(this, object : OnCompleteListener<GoogleSignInAccount>{
override fun onComplete(p0: Task<GoogleSignInAccount>) {
val account = p0.getResult(ApiException::class.java)
CheckDB(this#SignInActivity, db).execute()
}
})
}
}
When your user is signed in (the first and only time), use the obtained token to authenticate to your own backend server. No need to re-signin at google's.
Details here: https://developers.google.com/identity/sign-in/android/backend-auth
I've been trying for 3 days but cant solve the problem. The application connects with Google, I can get the information of the user, but Firebase does not save. private fun
firebaseAuthWithGoogle(idtoken : String?) {
val credential = GoogleAuthProvider.getCredential(idtoken, null)
println(credential)
auth.signInWithCredential(credential)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
user = auth.currentUser!!
Toast.makeText(this,"başarılı",Toast.LENGTH_LONG).show()
updateUI(user)
} else {
// If sign in fails, display a message to the user.
// ...
Toast.makeText(this,"olmadııııııııııı",Toast.LENGTH_LONG).show()
updateUI(null)
}
}
}
I can intent to other activity but when I go Toast shows "olmadııııııııııı". So I think the problem
signinwithcredential. I also enableb the google sign-in method in firebase and entered my SHA-1 fingerprint.
What should I do ?
I get this error on auth.signInWithCredential() ->if(task.isSuccessful)
I'm trying to get the Google Refresh token, the thing is that i haven't seen my current scenario anywhere, what i'm trying to accomplish is get the refresh token from a user auth token already generated by a google sign in from a native android app, basically i request every google permission i need on the app, and the the auth code from the sign in, with that auth code i send it to my Firebase functions backend, there i try to get the refresh token but i always get invalid_grant from google, so i don't know where could i be messing up
I saw that requesting oauth offline may solve the problem, but i'm sign in in the android app, so i cannot make a sign in request offline from the backend, i need the sign in and authentication to be only on the android app and i need this to make Google assistant requests over the backend and for this, the only thing missing is the refresh token
I have my google oauth2 key from google cloud console and the client initialized
var OAuth2 = google.auth.OAuth2;
var _client_id = require('./config/secrets/omni.json').installed.client_id;
var _client_secret = require('./config/secrets/omni.json').installed.client_secret;
var redirect = require('./config/secrets/omni.json').installed.redirect_uris[1];
return new OAuth2(
_client_id,
_client_secret,
redirect
);
And finally try to get the token:
function getRefreshToken(authCode, idFBUser) {
return new Promise((resolve, reject) => {
getOAuthClient().getToken(authCode, function(err, token) {
if (!err) {
console.log(`Get Token success, token: ${token}`);
getOAuthClient().setCredentials(token);
saveRefreshFirebase(idFBUser, token)
resolve(token);
} else {
console.log("Get Token error", err);
reject(err);
}
});
});
}
the error i'm getting exactly is this one: { error: 'invalid_grant', error_description: 'Bad Request' }
The method i use in the android app to request the auth code is this one:
Creating the GoogleSignIn instance
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.requestId()
.requestIdToken(getClientId())
.requestServerAuthCode(getClientId())
.requestScopes(ASSISTANT_SCOPE)
.build()
googleSignInClient = GoogleSignIn.getClient(this, gso)
Calling the Sign in Intent:
val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, RESULT_GOOGLE_SIGNIN)
Handle the Sign in Result:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
RESULT_GOOGLE_SIGNIN -> {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
task.result?.let { account ->
val id = account.id
val idToken = account.idToken
val authCode = account.serverAuthCode
Log.d("GoogleSignIn", "ID: $id")
Log.d("GoogleSignIn", "ID Token: $idToken")
Log.d("GoogleSignIn", "Auth code: $authCode")
btnLogin.text = "Sign Out"
loggedIn = true
} ?: Log.e("GoogleSignIn", "Exception: ${task.exception}")
} catch (e: Exception) {
Log.e("GoogleSignIn", "Catch Exception: $e")
}
}
}
}
}
and the authCode is the one i used to try to get the Refresh Token in the backend
You need to call
.requestServerAuthCode(getClientId(),true)
instead of
.requestServerAuthCode(getClientId())
If you want to get a refresh token. The javascript code you posted works with refresh tokens.
This is the easiest way to authenticate your app because all other kinds of token will expire. Refresh tokens dont expire. The Google Sign in library gives you an access code which you are already using to obtain a refresh token. You need to save this refresh token and send it to Google in order to obtain access tokens. The access token can then finally be used to make API requests.
By the way, that is actually what 'offline access' refers to. Took me a while to figure this out as well.
I have an android application which uses Firebase Authentication via Facebook. A user can delete their account in the application using the following function:
override fun deleteUserAcc() {
val user = FirebaseAuth.getInstance().currentUser
val userToken = FacebookAuthProvider.getCredential(authTokenProvider.provideToken())
user?.reauthenticate(userToken)?.addOnCompleteListener { task ->
user.delete()
}
}
After this a user really gets deleted on the Firebase servers. However when they try to access the application again and log in one more time, they are not able to do this (their account with uid had been deleted and somehow they are not assigned a new one uid).
The login function and the onSuccess callback are both implemented and called.
override fun login(): Completable {
LoginManager.getInstance().logInWithReadPermissions(
activityReference.get(),
listOf("public_profile", "user_birthday", "user_location")
)
return CompletableSubject.create().apply {
loginSubject = this
}
}
override fun onSuccess(result: LoginResult) {
val credential = FacebookAuthProvider.getCredential(result.accessToken.token)
authTokenProvider.saveToken(result.accessToken.token)
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
getInfoOnFirestore(loginSubject)
} else {
loginSubject.onError(task.exception!!)
}
}
}
What can possibly be the cause of the following issue?
A little late to the party but I know what the issue is. Firebase deletes only the authentication, which means that the real-time database is still there with the same uid. In order to delete the database entry as well, you need to upgrade to the blaze program and add the extension.