0

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!

0

1 Answer 1

0

That default_web_client_id might be wrong.

Whatever app.globe.com.youtubeplaylist.R.string.default_web_client_id might be.

see GoogleSignInOptions.Builder.requestIdToken (String serverClientId):

Specifies that an ID token for authenticated users is requested.

Requesting an ID token requires that the server client ID be specified.

serverClientId The client ID of the server that will verify the integrity of the token.


Goto console.firebase.google.com, select the project, then click

Authentication > Sign-In method > Google > Web SDK configuration.

There you find the "Web client ID" and "Web client secret" to use.

Also on the Google Cloud API credentials page, as "Client ID for Web application ".


Scope https://www.googleapis.com/auth/youtube.force-ssl might require scope https://www.googleapis.com/auth/youtube (these both are for managing the YouTube account). For viewing the content, scope https://www.googleapis.com/auth/youtube.readonly suffices.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.