首页 > 解决方案 > 如何从 Android 获取 idtoken 并发布到服务器后端 node.js

问题描述

我一直在尝试将使用 google 登录从 android 应用程序获取的 idToken 发送到服务器。但我没有得到任何结果。我已经按照文档进行操作,但无济于事。

在 logcat 我得到:Unable to POST to http://localhost:5000/auth/google

关于如何解决这个问题的解释或例子会很棒。

我将数据存储在mongodb中。

文档:添加 Google 登录

文档:使用服务器后端进行身份验证

常数:

安卓部分:

activity_auth.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.AuthActivity">

    <com.google.android.gms.common.SignInButton
        android:id="@+id/sign_in_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="60dp"
        android:layout_marginEnd="60dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.84000003" />

</androidx.constraintlayout.widget.ConstraintLayout>

验证活动.kt


class AuthActivity : AppCompatActivity() {

    private lateinit var googleSignInClient: GoogleSignInClient
    private var signIn = 9001
    private val tag = "AuthActivity"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_auth)

        val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.server_client_id))
            .requestEmail()
            .build()
        googleSignInClient = GoogleSignIn.getClient(this,gso)
        sign_in_button.setOnClickListener {
            signIn()
        }
    }

    private fun signIn(){
        val signInIntent = googleSignInClient.signInIntent
        startActivityForResult(signInIntent, signIn)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == signIn){
            val task = GoogleSignIn.getSignedInAccountFromIntent(data)
            //add silent sign in later on
            handleSignInResult(task)
        }
    }

    private fun handleSignInResult(completedTask : Task<GoogleSignInAccount>){
        try {
            val account = completedTask.getResult(ApiException::class.java)
            val idToken = account?.idToken

            //send id token to server and validate
            ConnectURLTask().execute(idToken)

            onLoggedIn(account)
        }
        catch (e : ApiException){
            Log.w(tag, "sign in failed , code : " + e. statusCode)
            onLoggedIn(null)
        }
    }

    private fun onLoggedIn(account: GoogleSignInAccount?){
        if (account != null){
            val intent = Intent(this, MainActivity::class.java)
            startActivity(intent)
            finish()
        }else{
            Toast.makeText(this@AuthActivity, "No Internet Connection", Toast.LENGTH_SHORT).show()
        }
    }

    private class ConnectURLTask : AsyncTask<String, Void, Void>() {

        val tag = "Authentication"

        override fun doInBackground(vararg strings: String?): Void? {
            val httpClient: HttpClient = DefaultHttpClient()
            val httpPost = HttpPost("http://localhost:5000/auth/google")
            try {
                val nameValuePairs: MutableList<NameValuePair> = ArrayList(1)
                nameValuePairs.add(BasicNameValuePair("idToken", strings[0]))
                httpPost.entity = UrlEncodedFormEntity(nameValuePairs)
                val response: HttpResponse = httpClient.execute(httpPost)
                val statusCode = response.statusLine.statusCode
                val responseBody = EntityUtils.toString(response.entity)
                Log.i(tag, "Signed in as: $responseBody")
            } catch (e: ClientProtocolException) {
                Log.e(tag, "Error sending ID token to backend.", e)
            } catch (e: IOException) {
                Log.e(tag, "Error sending ID token to backend.", e)
            }
            return null
        }
    }
    
}

节点

用户.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
    googleId : {
        type : String,
        required : true
    },
    name: {
        type: String,
        required: true,
    },
    email: {
        type: String,
        required: true,
        unique: true
    },
    date: {
        type: Date,
        default: Date.now
    }
});

module.exports = mongoose.model('user', userSchema);

服务器.js

const express = require('express');
const mongoose = require('mongoose');
const path = require('path');
const app = express();
require('dotenv').config();
const { OAuth2Client } = require('google-auth-library');
const User = require('./models/User');

//Connect to DB
mongoose.set('useCreateIndex', true);
mongoose.connect(
    process.env.CONNECTION, { useNewUrlParser: true, useUnifiedTopology: true },
    () => console.log('Connected!')
);

const client = new OAuth2Client(
    process.env.client_id,
    process.env.client_secret,
    process.env.redirect_url
);

app.post('/auth/google', (req, res) => {
    console.log('Evaluating  post');
    const { idToken } = req.body;
    verify(idToken).catch(console.error);
});

//Verify Token method
async function verify(token) {
    const ticket = await client.verifyIdToken({
        idToken: token,
        audience: keystore.client_id
    });
    const payload = await ticket.getPayload();
    const userid = await payload['sub'];
    console.log(userid);
    User.findOne({ googleId: userid }).then(existingUser => {
        if (!existingUser) {
            new User({ googleId: userid }).save();
        }
    });
}

//Port Listener
let PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
    console.log(`server is listening on port ${PORT}`);
});

您的帮助将不胜感激...谢谢

标签: androidnode.jsmongodbmongoosegoogle-oauth

解决方案


推荐阅读