NodeJS:服务器在尝试引用 ID 令牌服务器端时返回 "There is no current user."
NodeJS: Server returning "There is no current user." when trying to reference ID token server-side
每当我尝试从服务器端引用用户的 idToken 时,我都会收到一条消息,说没有用户登录。我已经坚持了一段时间,所以任何帮助都会很棒
这是 start.js 文件:
const cookieParser = require("cookie-parser");
const csrf = require("csurf");
const bodyParser = require("body-parser");
const path = require('path');
const express = require('express');
const admin = require("firebase-admin");
// const fbAuth = require('./routes/fbAuth');
const serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "",
});
app.get("/view", function (req, res) {
const sessionCookie = req.cookies.session || "";
admin
.auth()
.verifySessionCookie(sessionCookie, true /** checkRevoked */)
.then(() => {
res.render("view.html");
})
.catch((error) => {
res.redirect("/login");
});
});
app.post("/sessionLogin", (req, res) => {
const idToken = req.body.idToken.toString();
const expiresIn = 60 * 60 * 24 * 5 * 1000;
admin
.auth()
.createSessionCookie(idToken, { expiresIn })
.then(
(sessionCookie) => {
const options = { maxAge: expiresIn, httpOnly: true };
res.cookie("session", sessionCookie, options);
res.end(JSON.stringify({ status: "success" }));
},
(error) => {
res.status(401).send("UNAUTHORIZED REQUEST!");
}
);
});
app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); });
这是客户端登录:
window.addEventListener("DOMContentLoaded", () =>
{
const firebaseConfig = {
config stuff goes here...
};
firebase.initializeApp(firebaseConfig);
firebase.analytics();
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION);
document
.getElementById("login")
.addEventListener("submit", (event) =>
{
event.preventDefault();
const login = event.target.login.value;
const password = event.target.password.value;
firebase
.auth()
.signInWithEmailAndPassword(login, password)
.then((
{
user
}) =>
{
return user.getIdToken().then((idToken) =>
{
return fetch("/sessionLogin",
{
method: "POST",
headers:
{
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
body: JSON.stringify(
{
idToken
}),
});
});
})
.then(() =>
{
console.log(firebase.auth().currentUser);
window.location.assign("/view");
});
return false;
});
});
这里是我尝试在名为 oss.js 的路由文件之一中引用令牌的地方(第 9 行是确定问题的地方):
axios(config)
.then(function(response)
{
response = response.data;
console.log(response.progress, response.status);
if (response.progress === "complete")
{
if (response.status === "success")
{
console.log("JOB COMPLETE");
// upload to firebase here
var user = firebase.auth().currentUser;
if (user)
{
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
console.log("uid ->", uid);
return uid;
}).catch(function(error)
{
//Handle error
});
}
else
{
console.log("There is no current user.");
}
}
}
})
});
好吧,这个问题有点冗长,但这是我在一些帮助下得到的答案。
首先,为了从客户端引用 uid,我需要能够使用 'localStorage.setItem' 将其存储在浏览器中。用户登录后,我将其存储在客户端脚本中,如下所示(请注意第 12 行):
firebase
.auth()
.signInWithEmailAndPassword(login, password)
.then((
{
user
}) =>
{
localStorage.setItem('uid', user.uid);
return user.getIdToken().then((idToken) =>
{
localStorage.setItem('token', idToken);
return fetch("/sessionLogin",
{
method: "POST",
headers:
{
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
body: JSON.stringify(
{
idToken
}),
});
});
})
设置完成后,我需要在其他页面上引用它(我现在没有使用任何前端框架),这是使用嵌套在脚本文件中的以下代码完成的html 文件。这附加到一个函数,该函数启动一个允许我引用它的函数(请注意第 11 和 12 行):
$('#hiddenUploadField').change(function () {
var node = $('#appBuckets').jstree(true).get_selected(true)[0];
var _this = this;
if (_this.files.length == 0) return;
var file = _this.files[0];
switch (node.type) {
case 'bucket':
var formData = new FormData();
formData.append('fileToUpload', file);
formData.append('bucketKey', node.id);
let uid = localStorage.getItem('uid');
let token = localStorage.getItem('token');
$.ajax({
url: `/api/forge/oss/objects?uid=${uid}&token=${token}`,
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
$('#appBuckets').jstree(true).refresh_node(node);
_this.value = '';
}
});
break;
}
});
});
从那里我可以使用以下命令(第 14 和 15 行)从浏览器调用 uid 和令牌到后端中的所需位置:
router.post('/objects', multer(
{
dest: 'uploads/'
}).single('fileToUpload'), async (req, res, next) =>
{
fs.readFile(req.file.path, async (err, data) =>
{
if (err)
{
next(err);
}
try
{
let uid = req.query.uid;
let token =req.query.token;
此时我可以使用以下代码在上面的代码中引用 UID 和令牌:
var user = firebase.auth();
const customToken = admin.auth().createCustomToken(uid)
firebase.auth().onAuthStateChanged(function()
{
if (user)
{
admin.auth().verifyIdToken(token)
.then(function(decodedToken)
{
var uid = decodedToken.uid;
console.log("uid ->", uid);
return uid;
}).catch(function(error)
{
//Handle error
});
}
else
{
console.log("There is no current user.");
}
});
每当我尝试从服务器端引用用户的 idToken 时,我都会收到一条消息,说没有用户登录。我已经坚持了一段时间,所以任何帮助都会很棒
这是 start.js 文件:
const cookieParser = require("cookie-parser");
const csrf = require("csurf");
const bodyParser = require("body-parser");
const path = require('path');
const express = require('express');
const admin = require("firebase-admin");
// const fbAuth = require('./routes/fbAuth');
const serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "",
});
app.get("/view", function (req, res) {
const sessionCookie = req.cookies.session || "";
admin
.auth()
.verifySessionCookie(sessionCookie, true /** checkRevoked */)
.then(() => {
res.render("view.html");
})
.catch((error) => {
res.redirect("/login");
});
});
app.post("/sessionLogin", (req, res) => {
const idToken = req.body.idToken.toString();
const expiresIn = 60 * 60 * 24 * 5 * 1000;
admin
.auth()
.createSessionCookie(idToken, { expiresIn })
.then(
(sessionCookie) => {
const options = { maxAge: expiresIn, httpOnly: true };
res.cookie("session", sessionCookie, options);
res.end(JSON.stringify({ status: "success" }));
},
(error) => {
res.status(401).send("UNAUTHORIZED REQUEST!");
}
);
});
app.listen(PORT, () => { console.log(`Server listening on port ${PORT}`); });
这是客户端登录:
window.addEventListener("DOMContentLoaded", () =>
{
const firebaseConfig = {
config stuff goes here...
};
firebase.initializeApp(firebaseConfig);
firebase.analytics();
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION);
document
.getElementById("login")
.addEventListener("submit", (event) =>
{
event.preventDefault();
const login = event.target.login.value;
const password = event.target.password.value;
firebase
.auth()
.signInWithEmailAndPassword(login, password)
.then((
{
user
}) =>
{
return user.getIdToken().then((idToken) =>
{
return fetch("/sessionLogin",
{
method: "POST",
headers:
{
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
body: JSON.stringify(
{
idToken
}),
});
});
})
.then(() =>
{
console.log(firebase.auth().currentUser);
window.location.assign("/view");
});
return false;
});
});
这里是我尝试在名为 oss.js 的路由文件之一中引用令牌的地方(第 9 行是确定问题的地方):
axios(config)
.then(function(response)
{
response = response.data;
console.log(response.progress, response.status);
if (response.progress === "complete")
{
if (response.status === "success")
{
console.log("JOB COMPLETE");
// upload to firebase here
var user = firebase.auth().currentUser;
if (user)
{
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
console.log("uid ->", uid);
return uid;
}).catch(function(error)
{
//Handle error
});
}
else
{
console.log("There is no current user.");
}
}
}
})
});
好吧,这个问题有点冗长,但这是我在一些帮助下得到的答案。
首先,为了从客户端引用 uid,我需要能够使用 'localStorage.setItem' 将其存储在浏览器中。用户登录后,我将其存储在客户端脚本中,如下所示(请注意第 12 行):
firebase
.auth()
.signInWithEmailAndPassword(login, password)
.then((
{
user
}) =>
{
localStorage.setItem('uid', user.uid);
return user.getIdToken().then((idToken) =>
{
localStorage.setItem('token', idToken);
return fetch("/sessionLogin",
{
method: "POST",
headers:
{
Accept: "application/json",
"Content-Type": "application/json",
"CSRF-Token": Cookies.get("XSRF-TOKEN"),
},
body: JSON.stringify(
{
idToken
}),
});
});
})
设置完成后,我需要在其他页面上引用它(我现在没有使用任何前端框架),这是使用嵌套在脚本文件中的以下代码完成的html 文件。这附加到一个函数,该函数启动一个允许我引用它的函数(请注意第 11 和 12 行):
$('#hiddenUploadField').change(function () {
var node = $('#appBuckets').jstree(true).get_selected(true)[0];
var _this = this;
if (_this.files.length == 0) return;
var file = _this.files[0];
switch (node.type) {
case 'bucket':
var formData = new FormData();
formData.append('fileToUpload', file);
formData.append('bucketKey', node.id);
let uid = localStorage.getItem('uid');
let token = localStorage.getItem('token');
$.ajax({
url: `/api/forge/oss/objects?uid=${uid}&token=${token}`,
data: formData,
processData: false,
contentType: false,
type: 'POST',
success: function (data) {
$('#appBuckets').jstree(true).refresh_node(node);
_this.value = '';
}
});
break;
}
});
});
从那里我可以使用以下命令(第 14 和 15 行)从浏览器调用 uid 和令牌到后端中的所需位置:
router.post('/objects', multer(
{
dest: 'uploads/'
}).single('fileToUpload'), async (req, res, next) =>
{
fs.readFile(req.file.path, async (err, data) =>
{
if (err)
{
next(err);
}
try
{
let uid = req.query.uid;
let token =req.query.token;
此时我可以使用以下代码在上面的代码中引用 UID 和令牌:
var user = firebase.auth();
const customToken = admin.auth().createCustomToken(uid)
firebase.auth().onAuthStateChanged(function()
{
if (user)
{
admin.auth().verifyIdToken(token)
.then(function(decodedToken)
{
var uid = decodedToken.uid;
console.log("uid ->", uid);
return uid;
}).catch(function(error)
{
//Handle error
});
}
else
{
console.log("There is no current user.");
}
});