在服务器端使用nodejs express服务器通过openid协议处理googleoauth,我试图让回调函数在google将用户重定向到带有auth code+in query string的api之后运行这个清单。
只允许与学校的特殊领域的电子邮件通过(这是一个学校的项目)。
交换包含身份验证令牌、刷新令牌等的令牌对象。
通过cookie存储身份验证令牌
将整个令牌对象通过redis缓存存储在json对象中。。。这就是我被抓的地方(使用redis模块rejson。因为可以将数据库中的用户数据添加到内存中的对象以缓存用户数据…)
接下来的逻辑步骤包括检查用户是否存在于mongodb中,如果不存在则在mongodb中创建用户,重定向到浏览器,携带cookie,使用auth token检查redis缓存以维护持久会话。。。最终将通过hash、httponly、https等实现安全。。。
希望这能让您了解我的逻辑,但这似乎是一个redis或redis相关模块的问题。
为了使用redis rejson模块,我正在运行一个redis redisjson docker映像,它暴露在端口6379上,而express服务器(在端口4000上运行)将成为redis缓存服务器的客户机。。。
节点模块redis rejson允许redisjson命令Map到javascript友好名称。节点模块redis是节点的redis客户端库。
//This is a minimalist web-framework for NodeJS
var express = require("express");
//axios - handles HTTP requests
const axios = require("axios");
//redis - use for caching
//rejson - store JSON via redis
const redis = require("redis"),
rejson = require("redis-rejson");
rejson(redis);
//set ports
const PORT = process.env.PORT || 4000;
const REDIS_PORT = process.env.PORT || 6379;
const client = redis.createClient(REDIS_PORT);
// Init Express app
var app = express();
//callback route from google
app.get("/signin/callback", (req, res, next) => {
//declare vars from query string api return for later use
//console.log(req.query);
let hd = req.query.hd;
let authCode = req.query.code;
//Only allow GUHSD email domains
if(hd !== 'guhsd.net') {
console.log('you are shall not pass')
// The return is for stopping execution of controller
return res.redirect(301, 'http://localhost:3000/?error=invalid_domain');
}
//GET client_id and client_secret FROM JSON
//Make POST REQ to exchange AuthCode for JSON token object
axios.post('https://oauth2.googleapis.com/token', {
client_id: '<taken out as to not expose>',
client_secret: '<taken out as to not expose>',
code: authCode,
grant_type: 'authorization_code',
redirect_uri: 'http://localhost:4000/signin/callback'
})
.then((response) => {
console.log('Your token must to be here');
// Logic after exchange
//1. Start Sessions - Client HTTP only Cookie & Server Redis Cache
//2. Check if ACC exists - if so redirect client :)
//3. if ACC DOES NOT exist, create new acc!! then redirect client :)
async function passOver() {
console.log(response.data);
// example:
// {
// access_token: 'ya29.a0AfH6SMBSm3D99XAhmlxHtYOVVm7gZT9h8Bd8I9RgpYPhK0qXQwGT4fuMWhDsqDpcTfQuIg6bvY-tFUISX4Wm2Is-jprW2sstjmD4hjc2cQh5uIYODg1Re6v80FKENDdEAinTm9kid0QaKiaRxJQHt1deap-Ik1mcy2s',
// expires_in: 3599,
// refresh_token: '1//06qroj95zjugXCgYIARAAGAYSNwF-L9IrzWEi6q0wDpeUVKmnPZYZjZpsMS-KVT4fY9NzHgZCUxgY8fg2J_Nil2vJpMz52y-2pyY',
// scope: 'openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email',
// token_type: 'Bearer',
// id_token: 'eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk2MGE3ZThlODM0MWVkNzUyZjEyYjE4NmZhMTI5NzMxZmUwYjA0YzAiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiIyNDM1NjY4NDcxMDItdTRkazg1Y21qcjEybWgya25ycHYzaW5zMnRjcnBzOHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiIyNDM1NjY4NDcxMDItdTRkazg1Y21qcjEybWgya25ycHYzaW5zMnRjcnBzOHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTA1MzUzMTYxMjcxODg4Mjg5NjYiLCJoZCI6Imd1aHNkLm5ldCIsImVtYWlsIjoiMzMwMjk0QGd1aHNkLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhdF9oYXNoIjoidEhoVEl6eWp3MHcyRFpVaVpUMmxCQSIsIm5hbWUiOiJERVZJTiBQUk9WRU5DRSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vLVhTaV9oU2JsVWo0L0FBQUFBQUFBQUFJL0FBQUFBQUFBQUFBL0FNWnV1Y25HXzBwS3N0eVo3cEI0Wk0yZlpMQkNIUEU3UkEvczk2LWMvcGhvdG8uanBnIiwiZ2l2ZW5fbmFtZSI6IkRFVklOIiwiZmFtaWx5X25hbWUiOiJQUk9WRU5DRSIsImxvY2FsZSI6ImVuIiwiaWF0IjoxNTkwNjEwODE4LCJleHAiOjE1OTA2MTQ0MTh9.Nt2eGzCsKrUmyztqYWiZ16-1S7OCRcUFlSFvhVAy9HusYfLqp0nz3diUkuP-D_27BCtBsZCQ0JC1evPISwLX9H1hJs_GKYSD12s-ovJ8S0AzghY0M-AOuYxhGvKautusmXYfHvhfcPj7IKhPo_IXBl3x-ryOtRRrpJR6c30QPl1JUae74sAcLk8H1stLgqptrrRTgJWYdTXxJHSrZcR8RsLw2aY4GwuPGEX-AD6h51IZlNTl_6qNpaIt_7mFSUV-iF1PECAotfhKHdAryZCFRBq4XE6uJnYq3WnOVAMAEYwqT543pxarXOmLuAwhDqqewyuCXsjlbyhBys-4iEhYAg'
// }
//expires_in is in seconds... cookie takes milliseconds as expires arg.
//send to client, store in cookie(browser's session starts)
res.cookie(
"tokenResponse", `${response.data.access_token}`, {
maxAge: `${response.data.expires_in}`
}
)
var keyObject = JSON.stringify(response.data);
//set redis key to user
var user = 'user';
//store response.data in redis cache(server's session starts)
client.json_set(user, '.', keyObject, function (err) {
if (err) { throw err; }
console.log('Set JSON at key ' + user + '.');
client.json_get(user, '.access_token', function (err, value) {
if (err) { throw err; }
console.log('value of .', value); //outputs JSON
client.quit();
});
});
res.json(keyObject);
//redirect from server to frontend
// await res.redirect('http://localhost:3000');
}
//call passover
passOver();
})
//if err, log & redirect user to client
.catch((error) => {
console.log(error.request);
console.log(error.response.data);
return res.redirect(301, 'http://localhost:3000/?error=google_failed_exchange');
});
});
//start the express server
app.listen(4000, () =>
console.log(`App started on port ${PORT}`)
);
module.exports = app;
我犯的错误是
if (err) { throw err; }
^
ReplyError: ERR unknown command 'json.set'
at parseError (E:\docker-node-react-nginx\backend\node_modules\redis-parser\lib\parser.js:179:12)
at parseType (E:\docker-node-react-nginx\backend\node_modules\redis-parser\lib\parser.js:302:14) {
command: 'JSON.SET',
args: [
'user',
'.',
'{"access_token":"ya29.a0AfH6SMCSN3_0fXFexXYUqrkfhlJ5FmdkO-eqKeiXeSnRzlwD5aBDpBF7y-pXMDBY1YFqXLf-JU0mc5FXVo8nZER-6wB-hAm7qW_0w4Z3TcfoQfOT7ZXg8ZqK2DPyW8TnsZELWe9eDBYvFqM0lTWyWe3Z9ZqUXgv6Kz4","expires_in":3599,"refresh_token":"1//06FRrH2GkKtP2CgYIARAAGAYSNwF-L9IrnL1ZpMhxaiYWYuSnI7p6DG0uFIO3Vu2qt40Scio5SAlGT0mvBZ8hWvaPcJEEnjaunDw","scope":"https://www.googleapis.com/auth/userinfo.email openid https://www.googleapis.com/auth/userinfo.profile","token_type":"Bearer","id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6ImZiOGNhNWI3ZDhkOWE1YzZjNjc4ODA3MWU4NjZjNmM0MGYzZmMxZjkiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhenAiOiIyNDM1NjY4NDcxMDItdTRkazg1Y21qcjEybWgya25ycHYzaW5zMnRjcnBzOHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJhdWQiOiIyNDM1NjY4NDcxMDItdTRkazg1Y21qcjEybWgya25ycHYzaW5zMnRjcnBzOHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJzdWIiOiIxMTA1MzUzMTYxMjcxODg4Mjg5NjYiLCJoZCI6Imd1aHNkLm5ldCIsImVtYWlsIjoiMzMwMjk0QGd1aHNkLm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhdF9oYXNoIjoiV2kwRVdlSl9fQmVsaGV1RF9SVEl6USIsIm5hbWUiOiJERVZJTiBQUk9WRU5DRSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vLVhTaV9oU2JsVWo0L0FBQUFBQUFBQUFJL0FBQUFBQUFBQUFBL0FNWnV1Y25HXzBwS3N0eVo3cEI0Wk0yZlpMQkNIUEU3UkEvczk2LWMvcGhvdG8uanBnIiwiZ2l2ZW5fbmFtZSI6IkRFVklOIiwiZmFtaWx5X25hbWUiOiJQUk9WRU5DRSIsImxvY2FsZSI6ImVuIiwiaWF0IjoxNTkwNjI0NDIyLCJleHAiOjE1OTA2MjgwMjJ9.IyF5uB2ldLBQLu3CVMDpXf8szEK_BbR8SPrtdpJR_Y3bHklJ8e3JYGQT9AWjkcSy0I4DNUhkXiFk25HvZ06u2ekGd_adSknUVNwZe_N1IQTlMF1m-oqWbaRtnr4oxerQg_YunZDD4z_Lh5ecSDVz4X8H39uO7jrAvY1CdnZfZ4D2Je8aV1Zns5JahKhOTopPcy5sE1dSBNPqqGvUiY9h0MQHne9byUz9jMvog3YI-8-uexjC_JWsbzMFjE65ze5_cUpApYB5tUrNTjqvhiYgcimIPOXoto_VIHHEEoho5uHOkUQw_UVXleUa9vI77W1j7U7HnH-h_3C5ylx7UEDm6Q"}'
],
code: 'ERR'
}
[nodemon] app crashed - waiting for file changes before starting...
1条答案
按热度按时间qnzebej01#