Android OAuth2.0在使用YouTube v3 api身份验证时使用无效凭据

Android OAuth2.0在使用YouTube v3 api身份验证时使用无效凭据,android,firebase,google-play-services,Android,Firebase,Google Play Services,我花了几天时间研究如何通过GoogleAPI控制台和Firebase api实现“简单”的Google登录。由于我没有服务器,我希望只有在用户使用应用程序时才能访问他的帐户。我的目标是能够获得用户的频道id,这样我就可以加载他上传的所有视频 为此,我在谷歌控制台api中创建了一个新项目,将其链接到Firebase,并使用本教程将其集成到我的应用程序中。我已经到了用户可以选择Gmail帐户并登录的地步,该应用程序还提示用户需要允许的一系列YouTube权限。 之后,我获取用户的accountUid

我花了几天时间研究如何通过GoogleAPI控制台和Firebase api实现“简单”的Google登录。由于我没有服务器,我希望只有在用户使用应用程序时才能访问他的帐户。我的目标是能够获得用户的频道id,这样我就可以加载他上传的所有视频

为此,我在谷歌控制台api中创建了一个新项目,将其链接到Firebase,并使用本教程将其集成到我的应用程序中。我已经到了用户可以选择Gmail帐户并登录的地步,该应用程序还提示用户需要允许的一系列YouTube权限。 之后,我获取用户的accountUid(与Firebase控制台中显示的相同)

从这一点上,我感到困惑,因为一些教程提到了令牌访问、刷新令牌、客户机id、客户机机密,而我没有这些,并且不确定这些凭据是否是我的应用程序所必需的

用户成功登录后,我将使用此API调用获取其YouTube帐户的频道:

 @GET("channels")
    fun getChannelsList(@Query("part") part :String = "contentDetails,snippet",@Query("mine") mine : Boolean = true, @Header("Authorization") accessToken : String) : Single<ChannelResponse>
因此,我还尝试将“Bearer”作为标题值的一部分,并得到相同的结果

我也试过googleSignInAccount.idToken,但也没用

这是我的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
        }
    }    
}
class LoginActivity:BaseActivity(),View.OnClickListener,OnCompleteListener{
var idTokenString=“”
val TAG=“LoginActivity”
val mAuth=FirebaseAuth.getInstance()
私有变量mAuthListener:FirebaseAuth.AuthStateListener?=null
var googleAccount:GOOGLESIGNANCCOUNT?=null
覆盖有趣的布局():Int{
返回app.globe.com.youtubeplaylist.R.layout.activity\u登录
}
重写函数initUI(){
login.setOnClickListener(此)
logout.setOnClickListener(此)
}
伴星{
const val RC_SIGN_IN=1000
}
私有变量googleSignInClient:googleSignInClient?=null
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
val gso=GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT\u SIGN\u-IN)
.requestIdToken(getString(app.globe.com.youtubeplaylist.R.string.default\u web\u client\u id))
.requestEmail()
.requestScopes(范围(“https://www.googleapis.com/auth/youtube.readonly"),
范围(”https://www.googleapis.com/auth/youtube.force-ssl"))
.build()
googleSignInClient=GoogleSignIn.getClient(这个,gso)
googleSignInClient!!.Signinclient
}
覆盖有趣的onStart(){
super.onStart()
val currentUser=mAuth.currentUser
支票帐户(当前用户)
}
覆盖趣味onClick(v:视图){
何时(v.id){
app.globe.com.youtubeplaylist.R.id.login->{
签名()
}
app.globe.com.youtubeplaylist.R.id.logout->{
签出()
}
}
}
私人娱乐签到()
{
FirebaseAuth.getInstance().signOut()
支票帐户(空)
}
私人娱乐签到{
val signingent=googleSignInClient!!.signingent
startActivityForResult(签名、注册)
}
在ActivityResult上的公共覆盖乐趣(请求代码:Int,结果代码:Int,数据:Intent?){
super.onActivityResult(请求代码、结果代码、数据)
//从GoogleSignInClient.GetSignInent(…)启动Intent返回的结果;
if(requestCode==RC\u登录){
//此调用返回的任务始终已完成,无需附加
//听众。
val task=GoogleSignIn.GetSignedAccountFromIntent(数据)
试一试{
//Google登录成功,通过Firebase验证
googleAccount=task.getResult(ApiException::class.java)
firebaseAuthWithGoogle(googleAccount!!)
}捕获(e:异常){
//Google登录失败,请适当更新UI
Log.w(标签“Google登录失败”,e)
// ...
}
}
}
私人娱乐firebaseAuthWithGoogle(账户:谷歌签名账号)
{
Log.d(标签“firebaseAuthWithGoogle:+acct.id”)
val credential=GoogleAuthProvider.getCredential(acct.idToken,null)
mAuth.SIGNWITH凭证(凭证)
.addOnCompleteListener(这个,这个)
}
覆盖未完成的乐趣(任务:任务){
如果(任务成功){
//登录成功,使用登录用户的信息更新UI
Log.d(标记“signInWithCredential:success”)
var user=mAuth.currentUser
支票帐户(用户)
}否则{
//如果登录失败,则向用户显示消息。
Log.w(标记“signInWithCredential:failure”,task.exception)
Snackbar.make(主布局,“身份验证失败”),Snackbar.LENGTH\u SHORT.show()
支票帐户(空)
}
}
私人趣味支票帐户(帐户:FirebaseUser?)
{
如果(帐户!=null)
{
val maintent=Intent(这是MainActivity::class.java)
startActivity(主要目的)
}
其他的
{
login.visibility=View.VISIBLE
logout.visibility=View.GONE
}
}    
}

谢谢大家!

默认的web客户端id可能是错误的

无论app.globe.com.youtubeplaylist.R.string.default\u web\u client\u id是什么

请参阅。
requestIdToken(字符串serverClientId)

指定请求经过身份验证的用户的ID令牌

请求ID令牌需要指定服务器客户端ID

serverClientId
将验证令牌完整性的服务器的客户端ID


转到,选择项目,然后单击

Aut
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
        }
    }    
}