解码 Firebase ID 令牌失败。确保您传递了代表 ID 令牌的整个字符串 JWT
Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token
我最初并没有遇到这个错误,但它后来神秘地出现在我的代码中。我尝试遵循 firebase 文档并使用 auth.getAuth() 方法,但随后出现以下错误:
** : TypeError: auth.getAuth(...).verifyIdToken 不是函数 **
这是我的授权码:
//const { auth } = require('firebase-admin');
const { admin, db } = require('./admin');
//1. ******************
//const auth = require('firebase/auth');
module.exports = (req, res, next) => {
let idToken;
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer ')){
idToken = req.headers.authorization.split('Bearer')[1]
//returns an array of 2 strings --> 2nd element is the token
}
else{
console.error("NO TOKEN FOUND");
return res.status(403).json({error: "Unauthorized"});
}
admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
req.user = decodedToken;
console.log(decodedToken);
return db.collection('users')
.where('userId', '==', req.user.uid)
.limit(1)
.get();
})
.then(data => {
req.user.handle = data.docs[0].data().handle;
return next();
})
.catch(err => {
console.error('Error while verifying token', err);
return res.status(403).json(err);
})
}
** 其中需要管理员('firebase-admin');
我尝试在文档中应用 auth.getAuth() 方法,但我的邮递员回复说它不是函数。我现在很迷茫,非常感谢任何帮助。
这是完整的错误:
{ "code": "auth/argument-error",
"message": "Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token."
}
这是我的 users.js,id 令牌到达:
const { admin, db } = require("../util/admin");
const config = require('../util/config')
const firebase = require('firebase/app')
firebase.initializeApp(config)
const { validateSignUpData, validateLoginData, reduceUserDetails} = require('../util/validators')
const auth = require('firebase/auth');
// const { user } = require("firebase-functions/v1/auth");
exports.signup = (req,res) => {
const newUser = {
email:req.body.email,
password:req.body.password,
confirmPassword:req.body.confirmPassword,
handle:req.body.handle,
};
const { valid, errors } = validateSignUpData(newUser);
if(!valid) return res.status(400).json(errors);
//when a user signs up give them a blank image
const noImg = 'blankpic.png';
//declare an errors object as an empty object
let token, userId;
db.doc(`/users/${newUser.handle}`).get()
.then((doc) => {
if(doc.exists){
return res.status(400).json({ handle: 'this handle is already taken'})
} else{
return auth.createUserWithEmailAndPassword(auth.getAuth(), newUser.email,newUser.password)
}
})
.then((data) => {
//return access token for user to req more data
//return data.user.getIdToken();
userId = data.user.uid;
return data.user.getIdToken();
})
.then((idToken) => {
token = idToken;
//create user document
const userCredentials = {
handle: newUser.handle,
email: newUser.email,
createdAt: new Date().toISOString(),
imageUrl: `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${noImg}?alt=media`,
userId
};
//persist document into users cllection
return db.doc(`/users/${newUser.handle}`).set(userCredentials);
//return res.status(201).json( { token } );
})
.then(() => {
return res.status(201).json({ token })
})
.catch((err) => {
console.error(err);
if (err.code == 'auth/email-already-in-use') {
return res.status(400).json({ email: 'Email is already in use'})
}
return res.status(500).json({ general: "Something went wrong with server; please try again"});
});
}
exports.login = (req,res) => {
const user = {
email: req.body.email,
password: req.body.password
};
const { valid, errors } = validateLoginData(user);
if(!valid) return res.status(400).json(errors);
auth.signInWithEmailAndPassword(auth.getAuth(), user.email, user.password)
.then(data => {
return data.user.getIdToken();
})
.then(token => {
return res.json({ token });
})
.catch((err) => {
console.error(err);
return res
.status(403).json({general: 'Wrong credentials, please try again'});
});
}
exports.addUserDetails = (req,res) => {
let userDetails = reduceUserDetails(req.body);
db.doc(`/users/${req.user.handle}`).update(userDetails)
.then(() => {
return res.json({ message: 'Details add successfully'});
})
.catch(err => {
console.error(err);
return res.status(500).json({error: err.code});
})
}
exports.getAuthenticatedUser = (req,res) => {
let userData = {};
db.doc(`/users/${req.user.handle}`).get()
.then(doc => {
if(doc.exists){
userData.credentials = doc.data();
return db.collection('likes').where('userHandle', '==', req.user.handle).get()
}
})
.then(data => {
userData.likes = [];
data.forEach(doc => {
userData.likes.push(doc.data());
});
//return res.json(userData);
return db.collection('notifications').where('recipient', '=='. req.user.handle).get();
// .orderBy('createdAt').limit(10).get();
})
.then(data => {
userData.notifications = [];
data.forEach(doc => {
userData.notifications.push({
//recipient: doc.data().recipient,
sender: doc.data().sender,
createdAt: doc.data().createdAt,
screamId: doc.data().screamId,
type: doc.data().type,
read: doc.data().read,
notificationId: doc.id
});
});
return res.json(userData);
})
.catch(err => {
console.error(err);
return res.status(500).json({ error: err.code });
})
}
exports.getUserDetails = (req, res) => {
let userData = {};
db.doc(`/users/${req.params.handle}`)
.get()
.then((doc) => {
if (doc.exists) {
userData.user = doc.data();
return db
.collection("critech")
.where("userHandle", "==", req.params.handle)
//.orderBy("createdAt", "desc")
.get();
} else {
return res.status(404).json({ errror: "User not found" });
}
})
.then((data) => {
userData.posts = [];
data.forEach((doc) => {
userData.posts.push({
body: doc.data().body,
createdAt: doc.data().createdAt,
userHandle: doc.data().userHandle,
userImage: doc.data().userImage,
likeCount: doc.data().likeCount,
commentCount: doc.data().commentCount,
screamId: doc.id,
});
});
return res.json(userData);
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
exports.uploadImage = (req, res) => {
const busboyCons = require("busboy");
const path = require("path");
const os = require("os");
const fs = require("fs");
var busboy = busboyCons({ headers: req.headers });
let imageToBeUploaded = {};
let imageFileName;
// String for image token
//let generatedToken = uuid();
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
console.log(fieldname, filename, mimetype);
// if (mimetype !== "image/jpeg" && mimetype !== "image/png") {
// return res.status(400).json({ error: "Wrong file type submitted" });
// }
// my.image.png => ['my', 'image', 'png']
filename = filename.toString();
const imageExtension = filename.split(".")[filename.split(".").length - 1];
// 32756238461724837.png
imageFileName = `${Math.round(
Math.random() * 1000000000000
).toString()}.${imageExtension}`;
//tmdir() --> temporarydirectory
const filepath = path.join(os.tmpdir(), imageFileName);
imageToBeUploaded = { filepath, mimetype };
//use file system lib to create the file object using the node js function file.pipe
file.pipe(fs.createWriteStream(filepath));
});
busboy.on("finish", () => {
admin
.storage()
.bucket()
.upload(imageToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype,
//Generate token to be appended to imageUrl
// firebaseStorageDownloadTokens: generatedToken,
},
},
})
.then(() => {
//construct image url to add to our user
// Append token to url
const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}`;
return db.doc(`/users/${req.user.handle}`).update({ imageUrl });
})
.then(() => {
return res.json({ message: "image uploaded successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: "something went wrong" });
});
});
busboy.end(req.rawBody);
};
exports.markNotificationsRead = (req, res) => {
let batch = db.batch();
req.body.forEach((notificationId) => {
const notification = db.doc(`/notifications/${notificationId}`);
batch.update(notification, { read: true });
});
batch
.commit()
.then(() => {
return res.json({ message: "Notifications marked read" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
这是我登录时取回的令牌2
当我在 Postman 1
的授权 header 中使用令牌时得到的响应
授权 header 的格式为 Bearer <Token>
,中间有一个 space。但是,您在 split()
中传递 'Bearer'
,这将导致 ['', ' <token>']
(请注意实际标记前的附加白色 space)。您必须使用 .split(" ")
并且这应该可以解决它。尝试重构代码,如下所示:
if( req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
idToken = req.headers.authorization.split(' ')[1]
}
const r1 = "Bearer token".split("Bearer")
const r2 = "Bearer token".split(" ")
console.log(`Token 1: '${r1[1]}'`)
console.log(`Token 2: '${r2[1]}'`)
我最初并没有遇到这个错误,但它后来神秘地出现在我的代码中。我尝试遵循 firebase 文档并使用 auth.getAuth() 方法,但随后出现以下错误:
** : TypeError: auth.getAuth(...).verifyIdToken 不是函数 **
这是我的授权码:
//const { auth } = require('firebase-admin');
const { admin, db } = require('./admin');
//1. ******************
//const auth = require('firebase/auth');
module.exports = (req, res, next) => {
let idToken;
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer ')){
idToken = req.headers.authorization.split('Bearer')[1]
//returns an array of 2 strings --> 2nd element is the token
}
else{
console.error("NO TOKEN FOUND");
return res.status(403).json({error: "Unauthorized"});
}
admin.auth().verifyIdToken(idToken)
.then(decodedToken => {
req.user = decodedToken;
console.log(decodedToken);
return db.collection('users')
.where('userId', '==', req.user.uid)
.limit(1)
.get();
})
.then(data => {
req.user.handle = data.docs[0].data().handle;
return next();
})
.catch(err => {
console.error('Error while verifying token', err);
return res.status(403).json(err);
})
}
** 其中需要管理员('firebase-admin');
我尝试在文档中应用 auth.getAuth() 方法,但我的邮递员回复说它不是函数。我现在很迷茫,非常感谢任何帮助。
这是完整的错误:
{ "code": "auth/argument-error",
"message": "Decoding Firebase ID token failed. Make sure you passed the entire string JWT which represents an ID token. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token."
}
这是我的 users.js,id 令牌到达:
const { admin, db } = require("../util/admin");
const config = require('../util/config')
const firebase = require('firebase/app')
firebase.initializeApp(config)
const { validateSignUpData, validateLoginData, reduceUserDetails} = require('../util/validators')
const auth = require('firebase/auth');
// const { user } = require("firebase-functions/v1/auth");
exports.signup = (req,res) => {
const newUser = {
email:req.body.email,
password:req.body.password,
confirmPassword:req.body.confirmPassword,
handle:req.body.handle,
};
const { valid, errors } = validateSignUpData(newUser);
if(!valid) return res.status(400).json(errors);
//when a user signs up give them a blank image
const noImg = 'blankpic.png';
//declare an errors object as an empty object
let token, userId;
db.doc(`/users/${newUser.handle}`).get()
.then((doc) => {
if(doc.exists){
return res.status(400).json({ handle: 'this handle is already taken'})
} else{
return auth.createUserWithEmailAndPassword(auth.getAuth(), newUser.email,newUser.password)
}
})
.then((data) => {
//return access token for user to req more data
//return data.user.getIdToken();
userId = data.user.uid;
return data.user.getIdToken();
})
.then((idToken) => {
token = idToken;
//create user document
const userCredentials = {
handle: newUser.handle,
email: newUser.email,
createdAt: new Date().toISOString(),
imageUrl: `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${noImg}?alt=media`,
userId
};
//persist document into users cllection
return db.doc(`/users/${newUser.handle}`).set(userCredentials);
//return res.status(201).json( { token } );
})
.then(() => {
return res.status(201).json({ token })
})
.catch((err) => {
console.error(err);
if (err.code == 'auth/email-already-in-use') {
return res.status(400).json({ email: 'Email is already in use'})
}
return res.status(500).json({ general: "Something went wrong with server; please try again"});
});
}
exports.login = (req,res) => {
const user = {
email: req.body.email,
password: req.body.password
};
const { valid, errors } = validateLoginData(user);
if(!valid) return res.status(400).json(errors);
auth.signInWithEmailAndPassword(auth.getAuth(), user.email, user.password)
.then(data => {
return data.user.getIdToken();
})
.then(token => {
return res.json({ token });
})
.catch((err) => {
console.error(err);
return res
.status(403).json({general: 'Wrong credentials, please try again'});
});
}
exports.addUserDetails = (req,res) => {
let userDetails = reduceUserDetails(req.body);
db.doc(`/users/${req.user.handle}`).update(userDetails)
.then(() => {
return res.json({ message: 'Details add successfully'});
})
.catch(err => {
console.error(err);
return res.status(500).json({error: err.code});
})
}
exports.getAuthenticatedUser = (req,res) => {
let userData = {};
db.doc(`/users/${req.user.handle}`).get()
.then(doc => {
if(doc.exists){
userData.credentials = doc.data();
return db.collection('likes').where('userHandle', '==', req.user.handle).get()
}
})
.then(data => {
userData.likes = [];
data.forEach(doc => {
userData.likes.push(doc.data());
});
//return res.json(userData);
return db.collection('notifications').where('recipient', '=='. req.user.handle).get();
// .orderBy('createdAt').limit(10).get();
})
.then(data => {
userData.notifications = [];
data.forEach(doc => {
userData.notifications.push({
//recipient: doc.data().recipient,
sender: doc.data().sender,
createdAt: doc.data().createdAt,
screamId: doc.data().screamId,
type: doc.data().type,
read: doc.data().read,
notificationId: doc.id
});
});
return res.json(userData);
})
.catch(err => {
console.error(err);
return res.status(500).json({ error: err.code });
})
}
exports.getUserDetails = (req, res) => {
let userData = {};
db.doc(`/users/${req.params.handle}`)
.get()
.then((doc) => {
if (doc.exists) {
userData.user = doc.data();
return db
.collection("critech")
.where("userHandle", "==", req.params.handle)
//.orderBy("createdAt", "desc")
.get();
} else {
return res.status(404).json({ errror: "User not found" });
}
})
.then((data) => {
userData.posts = [];
data.forEach((doc) => {
userData.posts.push({
body: doc.data().body,
createdAt: doc.data().createdAt,
userHandle: doc.data().userHandle,
userImage: doc.data().userImage,
likeCount: doc.data().likeCount,
commentCount: doc.data().commentCount,
screamId: doc.id,
});
});
return res.json(userData);
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
exports.uploadImage = (req, res) => {
const busboyCons = require("busboy");
const path = require("path");
const os = require("os");
const fs = require("fs");
var busboy = busboyCons({ headers: req.headers });
let imageToBeUploaded = {};
let imageFileName;
// String for image token
//let generatedToken = uuid();
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
console.log(fieldname, filename, mimetype);
// if (mimetype !== "image/jpeg" && mimetype !== "image/png") {
// return res.status(400).json({ error: "Wrong file type submitted" });
// }
// my.image.png => ['my', 'image', 'png']
filename = filename.toString();
const imageExtension = filename.split(".")[filename.split(".").length - 1];
// 32756238461724837.png
imageFileName = `${Math.round(
Math.random() * 1000000000000
).toString()}.${imageExtension}`;
//tmdir() --> temporarydirectory
const filepath = path.join(os.tmpdir(), imageFileName);
imageToBeUploaded = { filepath, mimetype };
//use file system lib to create the file object using the node js function file.pipe
file.pipe(fs.createWriteStream(filepath));
});
busboy.on("finish", () => {
admin
.storage()
.bucket()
.upload(imageToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype,
//Generate token to be appended to imageUrl
// firebaseStorageDownloadTokens: generatedToken,
},
},
})
.then(() => {
//construct image url to add to our user
// Append token to url
const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}`;
return db.doc(`/users/${req.user.handle}`).update({ imageUrl });
})
.then(() => {
return res.json({ message: "image uploaded successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: "something went wrong" });
});
});
busboy.end(req.rawBody);
};
exports.markNotificationsRead = (req, res) => {
let batch = db.batch();
req.body.forEach((notificationId) => {
const notification = db.doc(`/notifications/${notificationId}`);
batch.update(notification, { read: true });
});
batch
.commit()
.then(() => {
return res.json({ message: "Notifications marked read" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
};
这是我登录时取回的令牌2 当我在 Postman 1
的授权 header 中使用令牌时得到的响应授权 header 的格式为 Bearer <Token>
,中间有一个 space。但是,您在 split()
中传递 'Bearer'
,这将导致 ['', ' <token>']
(请注意实际标记前的附加白色 space)。您必须使用 .split(" ")
并且这应该可以解决它。尝试重构代码,如下所示:
if( req.headers.authorization && req.headers.authorization.startsWith('Bearer ')) {
idToken = req.headers.authorization.split(' ')[1]
}
const r1 = "Bearer token".split("Bearer")
const r2 = "Bearer token".split(" ")
console.log(`Token 1: '${r1[1]}'`)
console.log(`Token 2: '${r2[1]}'`)