Я хочу, чтобы пользователи могли войти в Discord и сохранить их в сеансе с express-session
. Когда я запускаю фронтенд и бэкэнд локально, он отлично работает, но когда я разверну его на моем сервере Digitalocean с NGINX, сеанс не будет продолжаться. Клиент никогда не получает cookie, необходимый для сохранения сеанса.
Это настройка для входа в сеанс с использованием express-session
, passport
и MySQL для хранения сеанса.
import express, { Request, NextFunction, Response } from 'express';
import cors from 'cors';
import session, { SessionOptions } from 'express-session';
import DiscordStrategy from 'passport-discord';
import passport from 'passport';
import mysqlSession from 'express-mysql-session';
import secretConfig from 'config/secret';
import discordConfig from 'config/discord';
import apiConfig from 'config/apiconfig';
import { RESPONSE_CODE } from './helpers';
const isProd = process.env.NODE_ENV === 'production';
const app = express();
if (isProd) {
app.set('trust proxy', 1); // Trust first proxy
app.disable('x-powered-by'); // Hide information about the server
}
// Enable CORS
app.use(cors({
credentials: true,
origin: (origin, callback) => {
const sameServer = !origin;
if (sameServer || apiConfig.CORSWhitelist.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
}));
passport.serializeUser((user, done) => {
done(null, user);
});
passport.deserializeUser((user, done) => {
done(null, user);
});
passport.use(new DiscordStrategy(
{
clientID: secretConfig.discord.publicKey,
clientSecret: secretConfig.discord.privateKey,
callbackURL: discordConfig.callbackUrl,
scope: discordConfig.scopes,
},
(accessToken, refreshToken, user, done) => {
process.nextTick(() => {
return done(null, user);
});
}
));
const MysqlStore = mysqlSession(session);
const mysqlCfg = {
host: 'localhost',
port: 3306,
user: 'user',
password: 'password',
database: 'database',
};
const sessionCfg: SessionOptions = {
secret: secretConfig.sessionSecret,
name: 'plan-b-auth',
resave: false,
saveUninitialized: false,
proxy: isProd,
cookie: {
secure: isProd,
},
store: new MysqlStore(mysqlCfg),
};
app.use(session(sessionCfg));
app.use(passport.initialize());
app.use(passport.session());
const checkAuth = (req: Request, res: Response, next: NextFunction) => {
if (req.isAuthenticated()) return next();
res.status(RESPONSE_CODE.UNAUTHORIZED).json('Unauthorized');
};
app.get(
'/discord/auth',
passport.authenticate('discord', { scope: discordConfig.scopes }),
);
app.get(
'/discord/auth/callback',
passport.authenticate('discord', { failureRedirect: apiConfig.websiteDomain }),
(req, res) => {
res.redirect(apiConfig.websiteDomain);
}
);
app.get(
'/discord/auth/logout',
(req, res) => {
req.logout();
res.redirect('/');
}
);
app.get(
'/discord/auth/me',
checkAuth,
(req, res) => {
res.json(req.user);
}
);
app.listen(apiConfig.port, (err) => {
if (err) return console.info(err);
console.info('Listening at http://localhost:8080/');
});
На веб-интерфейсе (используя Next.js) я получаю пользовательские данные с помощью этой выборки
fetch('https://myapi.com/discord/auth/me', {
headers: {
cookie: req.headers.cookie,
},
credentials: 'include',
})
Это мой серверный блок для API (и клиента, они похожи)
server {
server_name myapi.com;
location / {
proxy_pass http://127.0.0.1:3002;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Опять же: когда я запускаю код локально и выполняю вход, он работает. Когда я развертываю его на моем сервере Digitalocean, он больше не работает. На развернутом веб-сайте на клиенте не хранятся файлы cookie, но при локальном запуске они присутствуют. Однако при развертывании сеансы хранятся в моей базе данных MySQL.