解码 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]}'`)