带有护照 jwt 的非对称密钥。始终验证 returns 未经授权
Asymmetric keys with passport jwt. Verify always returns Unauthorized
正在开发一个应用程序,我希望从一开始就安全,所以我创建了一个 private/public 密钥对,并且我正在设置 passport-jwt
如下:(key
是密钥对的 public 部分)
(passport, key) => {
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: key
};
passport.use(
new JwtStrategy(opts, (payload, done) => {
log.info({message: 'verifying the token', payload});
User.findById(payload.id)
.then(user => {
if (user) {
return done(null, {
id: user._id,
name: user.userName,
email: user.emailAddress
});
}
log.info(payload);
return done(null, false);
})
.catch(err => {
log.error(err)
return done('Unauthorized', false, payload);
});
})
);
};
当用户登录时,我使用私钥对令牌进行签名,如下所示:
router.post('/login', (req, res) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email }).then(user => {
if (!user) {
errors.email = 'No Account Found';
return res.status(404).json(errors);
}
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = {
id: user._id,
name: user.userName,
email: user.emailAddress
};
log.info(payload);
jwt.sign(payload, private, { expiresIn: 30000000 }, (err, token) => {
if (err)
res.status(500).json({ error: 'Error signing token', raw: err });
// const refresh = uuid.v4();
res.json({ success: true, token: `Bearer ${token}` });
});
} else {
errors.password = 'Password is incorrect';
res.status(400).json(errors);
}
});
});
});
我想我可能遗漏了什么,但不确定是什么。
此外,我还在应用程序内部使用以下代码在初始化时生成密钥。
const ensureKeys = () => {
return new Promise((resolve, reject) => {
ensureFolder('./keys').then(() => {
/**
* Ensure that both the private and public keys
* are created, and if not create them both.
* Never generate just a single key.
*/
try {
if (
!fs.existsSync('./keys/private.key') &&
!fs.existsSync('./keys/public.key')
) {
log.info('Keys do not exist. Creating them.');
diffHell.generateKeys('base64');
const public = diffHell.getPublicKey('base64');
const private = diffHell.getPrivateKey('base64');
fs.writeFileSync('./keys/public.key', public);
fs.writeFileSync('./keys/private.key', private);
log.info('keys created and being served to the app.');
resolve({ private, public });
} else {
log.info('keys are already generated. Loading from key files.');
const public = fs.readFileSync('./keys/public.key');
const private = fs.readFileSync('./keys/private.key');
log.info('keys loaded from files. Serving to the rest of the app.');
resolve({ private, public });
}
} catch (e) {
log.error('issue loading or generating keys. Sorry.', e);
reject(e);
}
});
});
};
好的,所以问题有两个方面。首先,我为护照生成的密钥不正确。根据 passport-jwt
、documentation, keys must be encoded in PEM format, and according to this post on Medium 的文档,护照和 JWT 需要更多配置。
最终解决方案包括使用 npm 上提供的 keypair
库。
以下是用于生成工作结果代码的修改。
const keypair = require('keypair');
const ensureKeys = () => {
return new Promise((resolve, reject) => {
ensureFolder('./keys').then(() => {
/**
* Ensure that both the private and public keys
* are created, and if not create them both.
* Never generate just a single key.
*/
try {
if (
!fs.existsSync('./keys/private.key') &&
!fs.existsSync('./keys/public.key')
) {
log.info('Keys do not exist. Creating them.');
const pair = keypair();
fs.writeFileSync('./keys/public.key', pair.public);
fs.writeFileSync('./keys/private.key', pair.private);
log.info('keys created and being served to the app.');
resolve({ private: pair.private,public: pair.public });
} else {
log.info('keys are already generated. Loading from key files.');
const public = fs.readFileSync('./keys/public.key', 'utf8');
const private = fs.readFileSync('./keys/private.key', 'utf8');
log.info('keys loaded from files. Serving to the rest of the app.');
resolve({ private, public });
}
} catch (e) {
log.error('issue loading or generating keys. Sorry.', e);
reject(e);
}
});
});
};
密钥使用私钥签名,私钥永远不会共享。
router.post('/login', (req, res) => {
const { errors, isValid } = require('../validation/user').loginUser(
req.body
);
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
User.findOne({ email }).then(user => {
if (!user) {
errors.email = 'No Account Found';
return res.status(404).json(errors);
}
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = {
id: user._id,
name: user.userName,
email: user.emailAddress
};
log.info(payload);
jwt.sign(payload, private, {
expiresIn: 30000000,
subject: user.emailAddress,
algorithm: 'RS256'
}, (err, token) => {
if (err)
res.status(500).json({ error: 'Error signing token', raw: err });
res.json({ success: true, token: `Bearer ${token}` });
});
} else {
errors.password = 'Password is incorrect';
res.status(400).json(errors);
}
});
});
以及验证函数:
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
secretOrKey: key,
algorithm: ["RS256"]
};
passport.use(
new JwtStrategy(opts, (payload, done) => {
log.info({message: 'verifying the token', payload});
User.findById(payload.id)
.then(user => {
if (user) {
return done(null, {
id: user._id,
name: user.userName,
email: user.emailAddress
});
}
log.info(payload);
return done(null, false);
})
.catch(err => {
log.error(err)
return done('Unauthorized', false, payload);
});
})
);
我希望这对将来希望使用非对称密钥的任何人有所帮助。
不错,对我有帮助,谢谢。
如果它对其他人有帮助,我不必使用该库 - 找到了一个 link 解释了如何将 public 密钥转换为 PEM 格式,这似乎有效(私有密钥已经是正确的格式)
ssh-keygen -f id_rsa.pub -m 'PEM' -e > id_rsa.pem
My question
正在开发一个应用程序,我希望从一开始就安全,所以我创建了一个 private/public 密钥对,并且我正在设置 passport-jwt
如下:(key
是密钥对的 public 部分)
(passport, key) => {
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: key
};
passport.use(
new JwtStrategy(opts, (payload, done) => {
log.info({message: 'verifying the token', payload});
User.findById(payload.id)
.then(user => {
if (user) {
return done(null, {
id: user._id,
name: user.userName,
email: user.emailAddress
});
}
log.info(payload);
return done(null, false);
})
.catch(err => {
log.error(err)
return done('Unauthorized', false, payload);
});
})
);
};
当用户登录时,我使用私钥对令牌进行签名,如下所示:
router.post('/login', (req, res) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email }).then(user => {
if (!user) {
errors.email = 'No Account Found';
return res.status(404).json(errors);
}
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = {
id: user._id,
name: user.userName,
email: user.emailAddress
};
log.info(payload);
jwt.sign(payload, private, { expiresIn: 30000000 }, (err, token) => {
if (err)
res.status(500).json({ error: 'Error signing token', raw: err });
// const refresh = uuid.v4();
res.json({ success: true, token: `Bearer ${token}` });
});
} else {
errors.password = 'Password is incorrect';
res.status(400).json(errors);
}
});
});
});
我想我可能遗漏了什么,但不确定是什么。
此外,我还在应用程序内部使用以下代码在初始化时生成密钥。
const ensureKeys = () => {
return new Promise((resolve, reject) => {
ensureFolder('./keys').then(() => {
/**
* Ensure that both the private and public keys
* are created, and if not create them both.
* Never generate just a single key.
*/
try {
if (
!fs.existsSync('./keys/private.key') &&
!fs.existsSync('./keys/public.key')
) {
log.info('Keys do not exist. Creating them.');
diffHell.generateKeys('base64');
const public = diffHell.getPublicKey('base64');
const private = diffHell.getPrivateKey('base64');
fs.writeFileSync('./keys/public.key', public);
fs.writeFileSync('./keys/private.key', private);
log.info('keys created and being served to the app.');
resolve({ private, public });
} else {
log.info('keys are already generated. Loading from key files.');
const public = fs.readFileSync('./keys/public.key');
const private = fs.readFileSync('./keys/private.key');
log.info('keys loaded from files. Serving to the rest of the app.');
resolve({ private, public });
}
} catch (e) {
log.error('issue loading or generating keys. Sorry.', e);
reject(e);
}
});
});
};
好的,所以问题有两个方面。首先,我为护照生成的密钥不正确。根据 passport-jwt
、documentation, keys must be encoded in PEM format, and according to this post on Medium 的文档,护照和 JWT 需要更多配置。
最终解决方案包括使用 npm 上提供的 keypair
库。
以下是用于生成工作结果代码的修改。
const keypair = require('keypair');
const ensureKeys = () => {
return new Promise((resolve, reject) => {
ensureFolder('./keys').then(() => {
/**
* Ensure that both the private and public keys
* are created, and if not create them both.
* Never generate just a single key.
*/
try {
if (
!fs.existsSync('./keys/private.key') &&
!fs.existsSync('./keys/public.key')
) {
log.info('Keys do not exist. Creating them.');
const pair = keypair();
fs.writeFileSync('./keys/public.key', pair.public);
fs.writeFileSync('./keys/private.key', pair.private);
log.info('keys created and being served to the app.');
resolve({ private: pair.private,public: pair.public });
} else {
log.info('keys are already generated. Loading from key files.');
const public = fs.readFileSync('./keys/public.key', 'utf8');
const private = fs.readFileSync('./keys/private.key', 'utf8');
log.info('keys loaded from files. Serving to the rest of the app.');
resolve({ private, public });
}
} catch (e) {
log.error('issue loading or generating keys. Sorry.', e);
reject(e);
}
});
});
};
密钥使用私钥签名,私钥永远不会共享。
router.post('/login', (req, res) => {
const { errors, isValid } = require('../validation/user').loginUser(
req.body
);
if (!isValid) {
return res.status(400).json(errors);
}
const email = req.body.email;
const password = req.body.password;
User.findOne({ email }).then(user => {
if (!user) {
errors.email = 'No Account Found';
return res.status(404).json(errors);
}
bcrypt.compare(password, user.password).then(isMatch => {
if (isMatch) {
const payload = {
id: user._id,
name: user.userName,
email: user.emailAddress
};
log.info(payload);
jwt.sign(payload, private, {
expiresIn: 30000000,
subject: user.emailAddress,
algorithm: 'RS256'
}, (err, token) => {
if (err)
res.status(500).json({ error: 'Error signing token', raw: err });
res.json({ success: true, token: `Bearer ${token}` });
});
} else {
errors.password = 'Password is incorrect';
res.status(400).json(errors);
}
});
});
以及验证函数:
const opts = {
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('Bearer'),
secretOrKey: key,
algorithm: ["RS256"]
};
passport.use(
new JwtStrategy(opts, (payload, done) => {
log.info({message: 'verifying the token', payload});
User.findById(payload.id)
.then(user => {
if (user) {
return done(null, {
id: user._id,
name: user.userName,
email: user.emailAddress
});
}
log.info(payload);
return done(null, false);
})
.catch(err => {
log.error(err)
return done('Unauthorized', false, payload);
});
})
);
我希望这对将来希望使用非对称密钥的任何人有所帮助。
不错,对我有帮助,谢谢。
如果它对其他人有帮助,我不必使用该库 - 找到了一个 link 解释了如何将 public 密钥转换为 PEM 格式,这似乎有效(私有密钥已经是正确的格式)
ssh-keygen -f id_rsa.pub -m 'PEM' -e > id_rsa.pem
My question