I spent several days on how to implement a "simple" Google sign-in through Google api console and Firebase api. As I don't have a server, I would like to have access to user's account only when he uses the application. My goal is to be able to get user's channels id's so I could load all of his uploaded videos.
In order to do that I created a new project in the google console api, linked it to Firebase and used this tutorial link to integrate it in my app. I got to the point where a user can choose a Gmail account and login, the app also prompt series of YouTube permissions that the user need to permit. After that I get accountUid of the user (the same one that is shown in the Firebase console).
From this point I got confused because some of the tutorials were mentioning token access, refresh tokens, client id, client secret which I don't have and not sure if those credentials are necessary for my application.
After the user sign in successfully I'm using this API call to obtain his channels of his YouTube account:
@GET("channels")
fun getChannelsList(@Query("part") part :String = "contentDetails,snippet",@Query("mine") mine : Boolean = true, @Header("Authorization") accessToken : String) : Single<ChannelResponse>
But I'm getting this error:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
from this link I also tried to put "Bearer " as part of the header value with the same result.
I also tried googleSignInAccount.idToken but it did not help either.
This is the code of my LoginActivity:
class LoginActivity : BaseActivity(), View.OnClickListener,OnCompleteListener<AuthResult>{
var idTokenString = ""
val TAG = "LoginActivity"
val mAuth = FirebaseAuth.getInstance()
private var mAuthListener: FirebaseAuth.AuthStateListener? = null
var googleAccount : GoogleSignInAccount?=null
override fun layoutRes(): Int {
return app.globe.com.youtubeplaylist.R.layout.activity_login
}
override fun initUI() {
login.setOnClickListener(this)
logout.setOnClickListener(this)
}
companion object {
const val RC_SIGN_IN = 1000
}
private var googleSignInClient : GoogleSignInClient?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(app.globe.com.youtubeplaylist.R.string.default_web_client_id))
.requestEmail()
.requestScopes(Scope("https://www.googleapis.com/auth/youtube.readonly"),
Scope("https://www.googleapis.com/auth/youtube.force-ssl"))
.build()
googleSignInClient = GoogleSignIn.getClient(this,gso)
googleSignInClient!!.signInIntent
}
override fun onStart() {
super.onStart()
val currentUser = mAuth.currentUser
checkAccount(currentUser)
}
override fun onClick(v: View) {
when (v.id) {
app.globe.com.youtubeplaylist.R.id.login -> {
signIn()
}
app.globe.com.youtubeplaylist.R.id.logout ->{
signOut()
}
}
}
private fun signOut()
{
FirebaseAuth.getInstance().signOut()
checkAccount(null)
}
private fun signIn() {
val signInIntent = googleSignInClient!!.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
public override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
// The Task returned from this call is always completed, no need to attach
// a listener.
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
// Google Sign In was successful, authenticate with Firebase
googleAccount = task.getResult(ApiException::class.java)
firebaseAuthWithGoogle(googleAccount!!)
} catch (e: ApiException) {
// Google Sign In failed, update UI appropriately
Log.w(TAG, "Google sign in failed", e)
// ...
}
}
}
private fun firebaseAuthWithGoogle(acct : GoogleSignInAccount)
{
Log.d(TAG, "firebaseAuthWithGoogle:" + acct.id)
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, this)
}
override fun onComplete(task: Task<AuthResult>) {
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "signInWithCredential:success")
var user = mAuth.currentUser
checkAccount(user)
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "signInWithCredential:failure", task.exception)
Snackbar.make(main_layout, "Authentication Failed.", Snackbar.LENGTH_SHORT).show()
checkAccount(null)
}
}
private fun checkAccount(account : FirebaseUser?)
{
if(account!=null)
{
val mainIntent = Intent(this,MainActivity::class.java)
startActivity(mainIntent)
}
else
{
login.visibility = View.VISIBLE
logout.visibility = View.GONE
}
}
}
Thank you!