Публикация Паруса в Kongregate, 403 Запрещено
Итак, наконец, моя игра MMORTS, основанная на Sails, собирается в Kongregate. Было немного препятствий, таких как подключение веб-сокетов, но теперь они решены. Вероятно, последним препятствием является сохранение аутентифицированного сеанса. Я везде использовал фреймворки, и я понятия не имею, как сеансы аутентификации работают под капотом.
Основная проблема, вероятно, в CSRF или CORS.
Я использую Sails v1.0. Итак, я начинаю с HTML, который я загружаю в kongregate. Я беру самый простой пример:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<script src="jquery.js"></script>
<script src='https://cdn1.kongregate.com/javascripts/kongregate_api.js'></script>
<script src="sails.io.js"
autoConnect="false"
environment="production"
headers='{ "x-csrf-token": "" }'
></script>
<script type="text/javascript">
io.sails.url = 'https://my-secret-game.com'; // or where you want
</script>
</head>
<script src="main.js"></script>
</html>
И это main.js, который я также загружаю в kongregate
kongregateAPI.loadAPI(function(){
window.kongregate = kongregateAPI.getAPI();
var username = kongregate.services.getUsername();
var id = kongregate.services.getUserId();
var token = kongregate.services.getGameAuthToken();
$.get("https://my-secret-game.com/csrfToken", function (data, jwres) {
var params = {
username: username,
id: id,
token: token,
_csrf: data._csrf
};
$.post("https://my-secret-game.com/kong", params, function(data, jwr, xhr){
// cant set the cookie - because of chrome. this doesnt work
document.cookie = document.cookie + ';authenticated=true;sails.sid=' + data.id;
$.get("https://my-secret-game.com/csrfToken", function (data, jwres) {
var msg = {
testing_authentication: true,
_csrf: data._csrf
};
$.post("https://my-secret-game.com/test", msg, function(data, status){
// getting the 403 Forbidden, CSRF mismatch. trying to access
// the play/test route, which is protected by sessionAUTH
console.log('data.response', data.response)
});
});
});
});
});
Проблема в том, что я получаю 403 Запрещено всякий раз, когда я пытаюсь отправить свой бэкэнд Sails с sessionAUTH. Я также не могу установить куки - вероятно, из-за Chrome. Что я могу сделать? Когда я получаю токен CSRF, на следующий запрос мое приложение Sails отвечает о несоответствии CSRF. Это становится неправильным.
И это контроллер на моем внутреннем сервере Sails
module.exports = {
kong: function (req, res, next) {
var url = 'https://api.kongregate.com/api/authenticate.json';
var kong_api_key = 'my-secred-api-key';
var params = req.allParams();
var request = require('request');
var req_form = {
"api_key": kong_api_key,
"user_id": params.id,
"game_auth_token": params.token
};
request({
url: url,
method: "POST",
json: true,
body: req_form,
timeout: 5000
}, function (err, response, body){
if(err) { console.log(err, 'ERR43'); return res.ok(); }
else {
if(!response.body.success) {
console.log('unsuccessful login from kongregate')
return res.ok();
}
// trying to use a existing user and authenticate to it
User.find({username: 'admin-user'}).exec(function(err, users) {
var user = users[0];
req.session.authenticated = true;
req.session.user = { id: user.id };
// trying to send session_id, so that i could hold it on kongregates cookies as `sid`
return res.send({ user: user, id: req.session.id });
});
}
});
},
Может ли somoene помочь исправить аутентификацию и CSRF моего приложения?
Если вам нужна дополнительная информация о моих конфигах, это config/session.js
var prefixes = 'dev';
module.exports.session = {
secret: 'my-secret',
cookie: {
secure: false
},
adapter: 'redis',
host: 'localhost',
port: 6379,
ttl: 3000000,
db: 0,
prefix: prefixes + 'sess:',
};
Config/policies.js
module.exports.policies = {
user: {
'new': 'flash',
'create': 'flash',
'edit': 'rightUser',
'update': 'rightUser',
'*': 'sessionAuth'
},
play: {
'*': 'sessionAuth'
}
};
API / политика / sessionAuth.js
module.exports = function(req, res, next) {
if (req.session.authenticated) {
return next();
} else {
var requireLoginErr = [
{ name: 'requireLogin', message: 'You must be signed in' }
];
req.session.flash = {
err: requireLoginErr
};
res.redirect('/');
return;
}
};
конфиг / security.js
module.exports.security = {
csrf: true,
cors: {
allowRequestMethods: 'GET,PUT,POST,OPTIONS,HEAD',
allowRequestHeaders: 'content-type,Access-Token',
allowResponseHeaders: '*',
allRoutes: true,
allowOrigins: '*',
allowCredentials: false,
},
};
0 ответов
Окей, так как у меня не было ответов (очевидно - вопрос был плохой), я отвечал своим решением, которое я решил сам - так что в следующий раз я смогу прочитать себя. Не уверен, насколько это хорошо, но, по крайней мере, это работает.
Sails CORS взят из Express.js и позволяет подключать сокеты к kongregate, если я разрешаю это внутри конфигов. Но это не позволяет проходить аутентификацию обычным способом, отправляя sails.sid (токен аутентификации) через куки.
Chrome вообще не позволяет устанавливать куки с javascript (у меня нет бэкэнда в Kongregate) для заголовков из-за безопасности. Поэтому, если я не могу отправить куки с заголовками, Sails не может аутентифицировать запросы обычным способом. Даже если я разрешаю CORS принимать заголовок cookie - браузеры не могут устанавливать заголовки cookie с помощью javascript.
Я могу создать уникальный заголовок, такой как "аутентификация", и установить sails.sid, расширить некоторые основные функции Sails, чтобы использовать этот новый заголовок вместо заголовка cookie. Но проблема в том, что при поддержке Sails я не смог получить этот sails.sid и отправить его на мой внешний интерфейс. Где он создан? Как я могу получить sails.sid на бэкэнде Sails? Не уверен - не могу погуглить.
Итак, я просто выполнил аутентификацию самым простым способом - при входе в систему / регистрации я просто создаю сеансовый ключ самостоятельно - с помощью хэширования bcrypt user_id+secret_token (взят из секретов конфигурации паруса). и отправка на веб-интерфейс { user_id: 'abcd', secret_token: 'a2dw412515...' }
Я сделал свои политики в Sails для проверки подлинности при каждом запросе POST/GET - возьмите параметры session_id и user_id и сравните, используя bcrypt, совпадает ли session_id с зашифрованным user_id+secret_token. Я надеюсь, что это достаточно безопасно.
Итак, это сработало. Я просто должен был отключить CSRF. Может быть, когда-нибудь я снова это осуществлю, я просто должен написать это по-своему, а не оставить настройки Sails по умолчанию.