«Ошибка: jwt неправильно сформирован», когда я выполняю вызов post на маршрут, для которого требуется авторизация промежуточного программного обеспечения

#reactjs #express #jwt #mern #bearer-token

Вопрос:

Я разрабатываю электронную коммерцию как упражнение для полного набора, и у меня возникла эта проблема. Особенность в том, что ошибка возникает только в этом случае: если я запускаю приложение, не входя в систему, а затем вхожу в систему (если я делаю консоль.журнал токена, сохраненный в файлах cookie, возвращает значение null). Если я обновлю страницу, все снова будет работать и в этом случае.

Я попытался проверить токены на jwt.io и они правы.

Это код части входа и входа в систему с помощью контроллера Google, в которой я создаю токен:

 import validator from 'validator';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import {OAuth2Client} from 'google-auth-library';
import sgMail from '@sendgrid/mail';
import dotenv from 'dotenv';
import {User} from '../models/User.js';

//LOADING ENVIRONMENT VARIABLE
dotenv.config();

const JWT_CONFIRM_ACCOUNT = process.env.JWT_CONFIRM_ACCOUNT;
const JWT_SECRET = process.env.JWT_SECRET;
const JWT_EXPIRE = process.env.JWT_EXPIRE;
const CLIENT_URL = process.env.CLIENT_URL;
const SGMAIL_API_KEY = process.env.SGMAIL_API_KEY;
const JWT_RESET_PASSWORD = process.env.JWT_RESET_PASSWORD;
const JWT_EMAIL_FROM = process.env.JWT_EMAIL_FROM;

//SETTING SGMAIL APIKEY
sgMail.setApiKey(SGMAIL_API_KEY);

//SIGN-IN
export const signIn = async (req, res) => {
    const { email, password } = req.body;

    try {
        const user = await User.findOne({email});

        if(!user){
            return res.status(400).json({errorMessage : 'Invalid credentials'})
        }

        if(!email || !password){
            return  res.status(400).json({errorMessage: 'All fields are required'})
         }
        
         if(!validator.isEmail(email)){
            return res.status(400).json({errorMessage : 'Invalid email'})
        }

           
        //JWT
        const payload = {
            user : {
                _id : user._id
            }
        }

        const isMatch = await bcrypt.compare(password, user.password);
        if(!isMatch){
            return res.status(400).json({errorMessage: 'Invalid credentials'})
        }
        else{
            jwt.sign(
                payload, 
                JWT_SECRET,
                {expiresIn: JWT_EXPIRE},
                (err, token) => {
                    if(err) console.log ('Jwt error: ', err);
    
                    const {_id, username, email, role} = user;
    
                    res.json({
                        token,
                        user : {_id, username, email, role}
                    })
                }
            )

        }
  
    } catch (error) {
       return  res.status(500).json({errorMessage : `${error}`})
    }
}

//GOOGLE LOGIN

export const googleLogin =  (req, res) => {

    const {token} = req.body;

    const client = new OAuth2Client('203822999175-ic2e949ccriqa983otoa5949dodi7iif.apps.googleusercontent.com');
    client.verifyIdToken({idToken: token, audience: '203822999175-ic2e949ccriqa983otoa5949dodi7iif.apps.googleusercontent.com'})
    .then(response => {
        const{email_verified, name, email, picture: userImage, given_name: firstName, family_name: lastName} = response.payload;
    

        if(email_verified){
            User.findOne({email}).exec((err, user) => {
                if(user){
                    user.image = userImage;
                    const payload =  {user : {
                        _id : user._id
                    }}
                    const token = jwt.sign( payload, JWT_SECRET, {expiresIn: JWT_EXPIRE});
                    const {_id, email, username, role} = user;
                    return res.json({
                        token,
                        user: {_id, email, username, role, userImage, firstName, lastName}
                    })
                }else{
                    let password = email   JWT_SECRET;
                    user = new User({
                        username: firstName, email, password, image: userImage
                    });
                    user.save((err, save) => {
                        if(err){
                            return res.status(400).json({errorMessage: `${err}` })
                        }
                        const token = jwt.sign({_id: user._id}, JWT_SECRET, {expiresIn: JWT_EXPIRE});
                        const {_id, email, username, role} = user;

                        const emailData = {
                            from: JWT_EMAIL_FROM,
                            to: email,
                            subject: "Account created - Tea Store",
                            html: `
                                <h1>Hi ${user.username}! Your account has been created</h1>
                                <p style = {{fontWeight : 'bold'}}>Thanks for logging in with google. 
                                To access the site via our custom sign-in form, choose a password for your account at the following link:</p>
                                <hr/>
                                <p>${CLIENT_URL}</p>
                            `
                        }

                        sgMail.send(emailData, (err, sent) => {
                            if(err){
                                return res.json({errorMessage: `${err}`})
                            }
                        })

                        return res.status(200).json({
                            token, 
                            user: {_id, email, username, role, userImage, firstName, lastName},
                            successMessage: 'Account successfully created! Check your mailbox'
                        })
                    })
                }
            })
        }else{
            return res.status(400).json({errorMessage: 'Google login failed'})
        }
    }).catch(err => {
        return res.status(500).json({errorMessage: 'Server Error'})
    })

}
 

Код входа и входа в систему с помощью части маршрута Google:

 import express from 'express';
import {signUp, signIn, googleLogin, forgotPassword, resetPassword, accountAuth} from '../controllers/auth.js';


const router = express.Router();

router.route('/sign-up').post(signUp);
router.route('/account-authentication/:token').post(accountAuth);
router.route('/sign-in').post(signIn);
router.route('/google-login').post(googleLogin);
router.route('/forgot-password').post(forgotPassword);
router.route('/reset-password/:token').post(resetPassword);

export default router;
 

Файл сервера:

 import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
import dotenv from 'dotenv';
import authRouter from './routes/auth.js';
import categoryRouter from './routes/category.js';
import productRouter from './routes/product.js';


//DOTENV CONFIG
dotenv.config();
const MONGODB_CONNECTION = process.env.MONGO_URI;

//INITIALIZE APP
const app = express()

//MIDDLEWARES
/*app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "http://localhost:3000");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
  });*/
  
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.use(cors({
    origin: 'http://localhost:3000',
    methods: ['GET','POST','DELETE','UPDATE','PUT','PATCH']
}));



//ROUTES
app.use('/api/auth', authRouter);
app.use('/api/categories', categoryRouter);
app.use('/api/products', productRouter)


//PORT
const PORT = process.env.PORT || 5020


//CONNECT MONGODB
const connectDB = () => {
    mongoose.connect(MONGODB_CONNECTION, {
        useNewUrlParser: true,
        useFindAndModify: true,
        useUnifiedTopology: true,
        useCreateIndex: true
    } )
        .then(() => console.log('MONGODB is connected'))
        .catch(err => console.log('MONGODB connection error:', err ))
}

connectDB();

//INITIALIZE SERVER
app.listen(PORT, () => console.log (`Connection is established and running on port ${PORT}`)
)
 

Authorization middlewares:

 import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';
import {User} from '../models/User.js';

dotenv.config();
const JWT_SECRET = process.env.JWT_SECRET;


export const authMiddleware = async (req, res, next) => {

    try {

        let token;
        if(req.headers.authorization amp;amp; req.headers.authorization.startsWith('Bearer')){
            token = req.headers.authorization.split(" ")[1]
        }

        if(!token){
            return res.status(401).json({errorMessage : "Invalid Authentication"})
        }

        try {
            const decoded = jwt.verify(token, JWT_SECRET);
            console.log(decoded)
            const user = await User.findById(decoded._id || decoded.user._id);
    
            if(!user){
                return res.status(404).json({errorMessage: "No user found"})
            }
    
            req.user = user;
    
            next()
            
        } catch (error) {
            return res.status(500).json({errorMessage: error.message})

            
        }
   
     
        
    }catch (error) {
        return res.status(500).json({errorMessage: "Not authorized"})
        
    }
    
}


export const authAdminMiddleware = async (req, res, next) => {
    try {
        const user = await User.findOne({
            _id: req.user.id
        })
        if(req.user.role === 0){
            return res.status(400).json({errorMessage: "Not Authorized. Admin private route."})
        }
        next()
                
    } catch (error) {
        return res.status(401).json({errorMessage: 'Not Authorized. Admin private route.'})
    }
}

 

General frontend configuration of API calls:

 import axios from 'axios';
import { getCookies } from '../helpers/storageamp;cookies/storageamp;cookies';

const config = {
    headers : {
        'Content-Type' : 'application/json',
        'Authorization' : 'Bearer '   getCookies('token')
    }
}



export const signup = async (data) => {

    const response = await axios.post('http://localhost:5020/api/auth/sign-up', data, config);
    return response;
};

export const accountAuth = async (data) => {
    const response = await axios.post('http://localhost:5020/api/auth/account-authentication/:token', data, config);
    return response;
}


export const signin = async (data) => {

    const response = await axios.post('http://localhost:5020/api/auth/sign-in', data, config);
    return response;
};


export const googleLogin = async (data) => {

    const response = await axios.post('http://localhost:5020/api/auth/google-login', data, config);
    return response;

}


export const forgotPassword = async (data) => {

    const response = await axios.post('http://localhost:5020/api/auth/forgot-password', data, config);
    return response;

}


export const resetPassword = async (data) => {

    const response = await axios.post('http://localhost:5020/api/auth/reset-password/:token', data, config);
    return response;

}

 
 import axios from 'axios';
import { getCookies } from '../helpers/storageamp;cookies/storageamp;cookies';


console.log(getCookies('token'))


const config = {
    headers : {
        'Content-Type' : 'application/json',
        'Authorization' : 'Bearer '   getCookies('token')
    }
}


export const fetchProducts = async () => {

    const response = await axios.get('http://localhost:5020/api/products/get-products');
    return response;
    
};

export const postProduct = async (data) => {
    const response = await axios.post('http://localhost:5020/api/products/create-product', data, config);
    return response;

}
 

Предполагая, что регистрация и вход работают идеально, сталкивался ли кто-нибудь с этой проблемой раньше?