Passport.js 인증 실패시 JSON 응답을 다시 보내기
내가 사용하고 Node.js
아이폰 클라이언트를위한 백엔드 API 서버로. 을 사용 Passport.js
하여 인증하는 데 사용하고 local strategy
있습니다. 관련 코드는 다음과 같습니다.
// This is in user.js, my user model
UserSchema.static('authenticate', function(username, password, callback) {
this.findOne({ username: username }, function(err, user) {
if (err){
console.log('findOne error occurred');
return callback(err);
}
if (!user){
return callback(null, false);
}
user.verifyPassword(password, function(err, passwordCorrect){
if (err){
console.log('verifyPassword error occurred');
return callback(err);
}
if (!passwordCorrect){
console.log('Wrong password');
return callback(err, false);
}
console.log('User Found, returning user');
return callback(null, user);
});
});
});
과
// This is in app.js
app.get('/loginfail', function(req, res){
res.json(403, {message: 'Invalid username/password'});
});
app.post('/login',
passport.authenticate('local', { failureRedirect: '/loginfail', failureFlash: false }),
function(req, res) {
res.redirect('/');
});
지금은 실패한 로그인을 / loginfail로 리디렉션하여 일부 JSON을 iPhone 클라이언트에 다시 보냅니다. 그러나 이것은 세분성이 충분하지 않습니다. "사용자를 찾을 수 없음"또는 "암호가 잘못되었습니다"와 같은 적절한 오류를 iPhone 클라이언트에 다시 보낼 수 있기를 원합니다. 내 기존 코드로는 이것이 어떻게 이루어질 수 있는지 알 수 없습니다.
passport.js 사이트의 사용자 정의 콜백에 대한 예제를 따르려고했지만 노드 이해가 부족하여 작동하지 않습니다. 적절한 오류 코드 / 메시지와 함께 res.json을 다시 보낼 수 있도록 코드를 수정하려면 어떻게해야합니까?
편집 : 나는 지금 이와 같은 것을 시도하고있다 :
// In app.js
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err) }
if (!user) {
console.log(info);
// *** Display message without using flash option
// re-render the login form with a message
return res.redirect('/login');
}
console.log('got user');
return res.json(200, {user_id: user._id});
})(req, res, next);
});
// In user.js
UserSchema.static('authenticate', function(username, password, callback) {
this.findOne({ username: username }, function(err, user) {
if (err){
console.log('findOne error occurred');
return callback(err);
}
if (!user){
return callback(null, false);
}
user.verifyPassword(password, function(err, passwordCorrect){
if (err){
return callback(err);
}
if (!passwordCorrect){
return callback(err, false, {message: 'bad password'});
}
console.log('User Found, returning user');
return callback(null, user);
});
});
});
그러나 console.log (info)를 시도하면 undefined라고 표시됩니다. 이 사용자 지정 콜백을 작동시키는 방법을 모르겠습니다 ... 어떤 도움을 주시면 감사하겠습니다!
정적 호출을 '인증'하는 콜백 함수 (코드에서 '콜백'이라고 함)는 코드에서 제공 할 수있는 세 번째 매개 변수 인 "info"를 허용합니다. 그런 다음 {failureRedirect : ...} 객체를 전달하는 대신 err, user 및 info의 3 개 인수를받는 함수를 전달합니다. 인증 방법에 제공 한 "정보"가이 콜백으로 전달됩니다.
Passport는이 시나리오를 "사용자 지정 콜백"이라고합니다. http://passportjs.org/guide/authenticate/ 에서 문서를 참조하십시오.
비슷한 문제가 Passport
있었고 로그인 응답이 실패했습니다. API를 구축하고 있었고 모든 응답이 JSON
. Passport는 상태 : 401
및 본문 :으로 잘못된 암호에 응답합니다 Unauthorized
. 그것은 JSON이 아닌 본문의 텍스트 문자열이므로 모든 JSON을 예상 한 내 클라이언트가 손상되었습니다.
결과적으로 Passport가 응답 자체를 보내려고하는 대신 프레임 워크에 오류를 반환하도록하는 방법이 있습니다.
대답은 failWithError
인증을 위해 전달 된 옵션 을 설정하는 것입니다 . https://github.com/jaredhanson/passport/issues/126#issuecomment-32333163
문제에 대한 jaredhanson의 의견에서 :
app.post('/login',
passport.authenticate('local', { failWithError: true }),
function(req, res, next) {
// handle success
if (req.xhr) { return res.json({ id: req.user.id }); }
return res.redirect('/');
},
function(err, req, res, next) {
// handle error
if (req.xhr) { return res.json(err); }
return res.redirect('/login');
}
);
Passport 호출 후 오류 처리기가 호출됩니다 next(err)
. 내 앱의 경우 JSON 오류를 제공하는 사용 사례에 특정한 일반 오류 처리기를 작성했습니다.
// Middleware error handler for json response
function handleError(err,req,res,next){
var output = {
error: {
name: err.name,
message: err.message,
text: err.toString()
}
};
var statusCode = err.status || 500;
res.status(statusCode).json(output);
}
그런 다음 모든 API 경로에 사용했습니다.
var api = express.Router();
...
//set up some routes here, attached to api
...
// error handling middleware last
api.use( [
handleError
] );
failWithError
문서 에서 옵션을 찾지 못했습니다 . 디버거에서 코드를 추적하는 동안 우연히 발견했습니다.
또한 이것을 알아 내기 전에 @Kevin_Dente 답변에 언급 된 "사용자 지정 콜백"을 시도했지만 작동하지 않았습니다. 이전 버전의 Passport 용인지 또는 내가 잘못한 것인지 잘 모르겠습니다.
Custom Callback에 대한 공식 문서가 있습니다 .
app.get('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
https://github.com/passport/www.passportjs.org/blob/master/views/docs/authenticate.md
passReqToCallback
전략 정의에서 속성 을 사용하여 사용자 지정 콜백없이이를 수행 할 수 있습니다 .
passport.use(new LocalStrategy({passReqToCallback: true}, validateUserPassword));
그런 다음 전략 코드의 요청에 사용자 지정 인증 오류 코드를 추가 할 수 있습니다.
var validateUserPassword = function (req, username, password, done) {
userService.findUser(username)
.then(user => {
if (!user) {
req.authError = "UserNotFound";
return done(null, false);
}
마지막으로 경로에서 이러한 사용자 지정 오류를 처리 할 수 있습니다.
app.post('/login', passport.authenticate('local', { failWithError: true })
function (req, res) {
....
}, function(err, req, res, next) {
if(req.autherror) {
res.status(401).send(req.autherror)
} else {
....
}
}
);
의 공식 문서에 따라 Passport
사용 할 수 있습니다 사용자 정의 콜백 승인 실패의 경우를 처리하고 기본 메시지를 무시하는 기능.
REST API를 개발하는 경우 아래와 같이 예쁜 JSON 응답을 보내고 싶을 것입니다.
{
"error": {
"name": "JsonWebTokenError",
"message": "invalid signature"
},
"message": "You are not authorized to access this protected resource",
"statusCode": 401,
"data": [],
"success": false
}
Passport JWT
내 경로 중 일부를 보호하기 위해 인증을 사용 authMiddleware
했으며 다음 과 같이 적용 되었습니다.
app / middlewares / authMiddleware.js
const express = require('express');
const router = express.Router();
const passport = require('passport');
const _ = require('lodash');
router.all('*', function (req, res, next) {
passport.authenticate('local', function(err, user, info) {
// If authentication failed, `user` will be set to false. If an exception occurred, `err` will be set.
if (err || !user || _.isEmpty(user)) {
// PASS THE ERROR OBJECT TO THE NEXT ROUTE i.e THE APP'S COMMON ERROR HANDLING MIDDLEWARE
return next(info);
} else {
return next();
}
})(req, res, next);
});
module.exports = router;
app / routes / approutes.js
const authMiddleware = require('../middlewares/authMiddleware');
module.exports = function (app) {
// secure the route by applying authentication middleware
app.use('/users', authMiddleware);
.....
...
..
// ERROR-HANDLING MIDDLEWARE FOR SENDING ERROR RESPONSES TO MAINTAIN A CONSISTENT FORMAT
app.use((err, req, res, next) => {
let responseStatusCode = 500;
let responseObj = {
success: false,
data: [],
error: err,
message: 'There was some internal server error',
};
// IF THERE WAS SOME ERROR THROWN BY PREVIOUS REQUEST
if (!_.isNil(err)) {
// IF THE ERROR IS REALTED TO JWT AUTHENTICATE, SET STATUS CODE TO 401 AND SET A CUSTOM MESSAGE FOR UNAUTHORIZED
if (err.name === 'JsonWebTokenError') {
responseStatusCode = 401;
responseObj.message = 'You are not authorized to access this protected resource';
}
}
if (!res.headersSent) {
res.status(responseStatusCode).json(responseObj);
}
});
};
ReferenceURL : https://stackoverflow.com/questions/15388206/sending-back-a-json-response-when-failing-passport-js-authentication
'IT이야기' 카테고리의 다른 글
빈 Seq에 대한 Option [T]의 최소 / 최대? (0) | 2021.04.15 |
---|---|
첫 번째 열이 문자열이고 나머지 열이 숫자 일 때 numpy.genfromtxt를 사용하는 방법은 무엇입니까? (0) | 2021.04.15 |
Spring @Value가 속성 파일의 값으로 확인되지 않을 경우 (0) | 2021.04.15 |
Spring JUnit : autowired component에서 autowired component를 모의하는 방법 (0) | 2021.04.14 |
나머지 세로 공간 채우기-CSS (0) | 2021.04.14 |