有没有办法解决错误:从插件获取元数据失败,错误:invalid_grant:无效的JWT

时间:2019-06-10 20:08:25

标签: express google-cloud-firestore google-cloud-functions firebase-admin

我设置了Firebase云功能以使用Express,还使用firebase SDK auth属性进行注册。我注意到,使用firebase-admin在firestore中创建新用户文档的管理员在部署后不会执行。

我使用邮递员尝试注册一个新用户,并从firebase收到此错误:

Error: Getting metadata from plugin failed with error: invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values and use a clock with skew to account for clock differences between systems.

我该如何解决?

我创建了一个登录路由,该路由可以正常工作并返回令牌,因为它仅调用firebase SDK auth属性进行登录

这是我的项目代码:

初始化firebase-admin


const admin = require("firebase-admin");

const serviceAccount = require("./would-you-rather-app-c5895-firebase-adminsdk-lndjl-f7793c362b.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount),
  databaseURL: `https://${serviceAccount.project_id}.firebaseio.com`
});

const db = admin.firestore(); 
module.exports = { admin, db };

表达设置


const functions = require('firebase-functions');
const app = require("express")();

// const cors = require("cors");
// app.use(cors());

const { signup, login } = require("./handlers/users");

// users routes
app.post("/signup", signup);
app.post("/login", login);

app.get("/", (request, response) => {
  response.send("Hello from Firebase!");
});

exports.api = functions.https.onRequest(app);

用户注册和登录处理程序


const { admin, db } = require("../util/admin");
const config = require("../util/config");

const client = require("firebase");
client.initializeApp(config);

// Sign user up
exports.signup = (req, res) => {
  const newUser = {
    email: req.body.email,
    password: req.body.password,
    confirmPassword: req.body.confirmPassword,
    firstName: req.body.firstName,
    lastName: req.body.lastName,
    fullname: `${req.body.firstName} ${req.body.lastName}`
  };

  // TODO: validation

  const noImg = "no-img.png";
  let userId, token;

  client
    .auth()
    .createUserWithEmailAndPassword(newUser.email, newUser.password)
    .then(data => {
      userId = data.user.uid;
      return data.user.getIdToken();
    })
    .then(idToken => {
      token = idToken;
       const userCredentials = {
        fullname: newUser.fullname,
        createdAt: new Date().toISOString(),
        imageUrl: `https://firebasestorage.googleapis.com/v0/b/${
      config.storageBucket
    }/o/${noImg}?alt=media`,
        score: 0,
        questions: [],
        votes: [],
        userId: userId
      };
      return admin
        .firestore()
        .doc(`users/${userId}`)
        .set(userCredentials);
     })
    .then(() => {
      return res.status(201).json({ token });
    })
    .catch(err => {
      console.log("Signup error: ", err);
      if (err.code === "auth/email-already-in-use") {
        return res.status(400).json({ email: "Email already in use" });
      } else {
        return res
          .status(500)
          .json({ general: "Something went wrong, please try agin" });
      }
    });
};

// Log user in
exports.login = (req, res) => {
  const user = {
    email: req.body.email,
    password: req.body.password
  };

  client
    .auth()
    .signInWithEmailAndPassword(user.email, user.password)
    .then(data => {
      return data.user.getIdToken();
    })
    .then(token => {
      return res.json({ token });
    })
    .catch(err => {
      return res
        .status(403)
        .json({ general: "Wrong credentials, please try again" });
    });
};

正在运行的注册会返回验证成功的错误,但用户凭据未添加到Firestore中...

Firebase-debug-log


[info] i  functions: Beginning execution of "api"
[debug] [2019-06-10T17:40:33.997Z] Disabled runtime features: {"functions_config_helper":true,"network_filtering":true,"timeout":true,"memory_limiting":true,"protect_env":true,"admin_stubs":true}
[debug] [2019-06-10T17:40:35.600Z] firebase-admin has been stubbed.
[info] i  Your code has been provided a "firebase-admin" instance.
[debug] [2019-06-10T17:40:36.599Z] Trigger "api" has been found, beginning invocation!
[debug] [2019-06-10T17:40:36.600Z] 
[debug] [2019-06-10T17:40:36.600Z] Running api in mode HTTPS
[debug] [2019-06-10T17:40:36.612Z] {"socketPath":"\\\\?\\pipe\\C:\\Users\\ismail\\Documents\\Archive\\tutorial-codes\\NanoRD\\proj3\\proj3\\functions\\9796"}
[debug] [2019-06-10T17:40:36.617Z] [functions] Runtime ready! Sending request! {"socketPath":"\\\\?\\pipe\\C:\\Users\\ismail\\Documents\\Archive\\tutorial-codes\\NanoRD\\proj3\\proj3\\functions\\9796"}
[debug] [2019-06-10T17:40:36.660Z] Ephemeral server used!
[debug] [2019-06-10T17:40:36.717Z] Ephemeral server survived.
[info] >  Signup error:  Error: Getting metadata from plugin failed with error: invalid_grant: Invalid JWT: Token must be a short-lived token (60 minutes) and in a reasonable timeframe. Check your iat and exp values and use a clock with skew to account for clock differences between systems.
[info] >      at Http2CallStream.<anonymous> (C:\Users\ismail\Documents\Archive\tutorial-codes\NanoRD\proj3\proj3\functions\node_modules\@grpc\grpc-js\build\src\client.js:101:45)
[info] >      at Http2CallStream.emit (events.js:201:15)
[info] >      at C:\Users\ismail\Documents\Archive\tutorial-codes\NanoRD\proj3\proj3\functions\node_modules\@grpc\grpc-js\build\src\call-stream.js:71:22
[info] >      at processTicksAndRejections (internal/process/task_queues.js:81:9) {
[info] >    code: '400',
[info] >    details: 'Getting metadata from plugin failed with error: invalid_grant: ' +
[info] >      'Invalid JWT: Token must be a short-lived token (60 minutes) and ' +
[info] >      'in a reasonable timeframe. Check your iat and exp values and use ' +
[info] >      'a clock with skew to account for clock differences between ' +
[info] >      'systems.',
[info] >    metadata: Metadata { options: undefined, internalRepr: Map {} }
[info] >  }
[info] i  functions: Finished "api" in ~2s

我希望注册时返回一个令牌,并在firestore中存储一个新的用户凭证

2 个答案:

答案 0 :(得分:1)

我遇到了这个问题,但这是由我的本地主机设置的无效时间引起的。

答案 1 :(得分:0)

我终于找到了一种同步计算机时钟的方法。这篇文章很有帮助:4 Ways to Automatically Synchronize Computer Clock on Windows Startup