Executando verificação de segurança...
1

Problemas com sessões e cookies

Olá, estou estudando sobre desenvolvimento web e para colocar o meu conhecimento em prática estou fazendo um projeto que é basicamente um administrador financeiro, onde o usuário colocará seus dados e o sistema definirá algumas dicas e orientações baseado nas despesas e investimentos do usuário.

Até aí tudo bem, o problema começa na parte do login, mais precisamente na autenticação do passport, e eu não sei mais o que fazer!

O que deu errado?

O projeto estava caminhando bem, e mesmo sem ter finalizado, decidi hospedá-lo na vercel. Porém ai que tá o problema, no meu computador o projeto funciona normalmente, mas na hospedagem da vercel a session, criada na autenticação do passport, é perdida e eu não tenho ideia do porque!

Informações sobre o projeto

O front e o back estão separados e hospedados em dois sites diferentes na vercel.

Tecnologias

Front

  1. React
  2. Next.js
  3. Axios

back

  1. Node.js
  2. passport
  3. cors

Há outras tecnologias que utilizei, mas não me aparenta estar interferindo no problema.

Como o código está atualmente:

index.js

const app = express();
const session = require("express-session");
const bodyParser = require("body-parser");
const path = require("path");
const cors = require("cors");
const mongoose = require("mongoose");
const MongoStore = require("connect-mongo");
const passport = require("passport");
require("./config/auth")(passport);

require('dotenv').config();


//sessions

app.use(cors({
    origin: process.env.CLIENT.split(','),
    credentials: true
}));

app.use(session({
    secret: process.env.SESSION,
    resave: false,
    saveUninitialized: false,
    store: MongoStore.create({
        mongoUrl: process.env.DATABASE,
        ttl: 24 * 60 * 60
    }),
    cookie: { 
        maxAge: 24 * 60 * 60 * 1000,
        httpOnly: true,
        sameSite: "none",
        secure: true,
        domain: process.env.DOMAIN
    }

}));

app.use(passport.initialize());
app.use(passport.session());

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());


//mongoose

mongoose.Promise = global.Promise;
mongoose.connect(process.env.DATABASE).then(() => {
    console.log("conectado ao mongo...");
}).catch((err) => {
    console.error("Erro ao se conectar ao mongo...");
    console.error(err);
});


//public

app.use(express.static(path.join(__dirname, "public")));


//Routes

const loginRoutes = require('./routes/login');
const logoutRoutes = require('./routes/logout');
const registerRoutes = require('./routes/register');
const userRoutes = require('./routes/user');
const dataRoutes = require('./routes/data');
const editRoutes = require('./routes/edit');
const deleteRoutes = require('./routes/delete');


app.get("/", (req, res) => {
    res.json("Página inicial da api do administrador financeiro!");
});

app.use('/login', loginRoutes);
app.use('/logout', logoutRoutes);
app.use('/register', registerRoutes);
app.use('/user', userRoutes);
app.use('/data', dataRoutes);
app.use('/edit', editRoutes);
app.use('/delete', deleteRoutes);


app.listen(process.env.PORT, () => console.log("Servidor online"));

rota de login

const router = express.Router();
const passport = require("passport");
require("../config/auth")(passport);

const Response = require("../helper/Response");

router.post("/", (req, res, next) => {
    passport.authenticate("local", (err, user, info) => {
        if (err) { return next(err) };
        if (!user) { res.json(Response("error", info.message, "/")) };

        req.logIn(user, function(err) {
            if (err) { return next(err) };
            next();
        });
    })(req, res, next);

}, (req, res) => {
    res.json(Response("success", "Usuário logado com sucesso!", "/home"));
});

module.exports = router;

auth do passport

const mongoose = require("mongoose");
const bcrypt = require("bcryptjs");

require("../model/User");
const User = mongoose.model("users");


module.exports = function(passport) {

    passport.use(new localStrategy({usernameField: "email"}, (email, password, done) => {
        User.findOne({email: email}).then((user) => {
            if(!user){
                return done(null, false, {message: "Esta conta não exite!"});
            };
            bcrypt.compare(password, user.password, (err, match) => {
                if(match){
                    return done(null, user);
                }else{
                    return done(null, false, {message: "Senha incorreta"});
                };
            });

        }).catch((err) => {
            return done(null, false, {message: "Erro ao carregar o usuário!"});
        });
    }));

    passport.serializeUser((user, done) => {
        done(null, user.id);
    });

    passport.deserializeUser((id, done) => {
        User.findById(id).then(user => done(null, user)).catch(err => done(err, null));
    });
};

Middleware que confirma a autenticação do usuário


module.exports = function UserAuthenticated(req, res, next) {
    if (req.isAuthenticated()) {
        return next();
    };
    res.json(Response("error", "Usuário não autenticado!", "/"));
};

Axios no front


const apiLocal = "http://localhost:8081/";
const apiURL = "https://api-administrador-financeiro.vercel.app/";

export default axios.create({
    baseURL: apiURL || apiLocal,
    withCredentials: true
});

Sobre o problema

Coloquei alguns console.log() no código e descobri que a sessão na rota de login está normal, armazenando o id do usuário, porém no middleware a sessão era outra e não estava mas com o id do usuário, além de que req.isAuthenticated() retorna false.

Pontos importantes

  • Não sei se o tabnews é o local mais indicado para este tipo de postagem, pelo que entendi, postagens com dúvidas muito simples é para se evitar, então me desculpem se errei nisso, é que para mim este problema parece bem complexo kkkk.
  • Sei que a configuração do passport.authenticate("local") não é a usada normalmente, e que usar req.login() é redundante já que o passport faz isso automaticamente, porém já testei diversas configurações diferentes e nenhuma adiantou.
  • É a primeira vez que utilizo sessões e cookies e não sei se as configurações estão certas.

Desde já agradeço a ajuda de todos, espero que tenham a resposta para este problema kkkk

Para quem quiser ver o código completo

Carregando publicação patrocinada...
2

Acho que deve ser devido aos 2 estarem em subdomínios diferentes. O cookie está sendo gerado para um subdomínio e o outro nao tem acesso.
Localmente tudo fica em localhost mas quand você sobe, ele fica em locais diferentes.
Você pode colocar essa API juntamente com o front. Você esta usando Next e ele permite isso perfeitamente. Você resolveria 2 problemas de uma vez.

1

Realmente, vou migrar a api para o projeto em next. Pelo que consegui entender realmente o problema é por estarem em subdomínios diferentes, o navegador acaba bloqueando o cookie, mesmo configurando o cors para aceitar. Muito obrigado pela resposta kkkkk

1

Mas nao tem nada a ver com CORS, não. Um cookie precisa pertencer a um domínio específico. É uma regra do cookie. Você até consegue definir cookie que abarque todos os subdomínios re um domínio. Mas imagine o problema de você definir um cookie que todos os sites da vercel estariam aptos a ler. Isso poderia gerar erro no seu e nos demais sistemas da hospedagem. Agora quando você comprar um domínio e fizer a separação, por exemplo, api.seunome.com e seunome.com, aí vai funcionar de boa.
Mas você precisa alterar seu código pois você está especificamente criando um cookie usando o subdomínio da api.

-6

pega a url deste post joga no gpt 4 usando o plugin webPilot que analisa url ele vai te ajudar a entender o problema

ai aos poucos vai passando mais logs dentro do chat, até encontrar algo errado

1

Obrigado pela resposta, fiz isso e acabei descobrindo que o problema está na configuração do cookie, o navegador considera o cookie da api como de terceiros e acaba bloqueando, o único que funcionou foi o firefox.