이번 포스팅에서는 json web token을 이용한 토큰 기반 user 인증을 구현해보겠습니다.
회원가입 성공시 json web token 받기
다음과 같이 회원가입을 담당하는 router 가 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
router.post(
"/",
async (req, res) => {
const { name, email, password } = req.body;
try {
// check user exists
let user = await User.findOne({ email });
if (user) {
return res
.status(400)
.json({ errors: [{ msg: "User already exists" }] });
}
user = new User({
name,
email,
password,
});
// Encrpyt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
res.send("Register Success");
} catch (error) {
console.error(error.message);
res.status(500).send("Server Error");
}
}
);
User의 회원가입에 성공하면 user 정보를 mongoDB에 저장 후 응답으로 Register Success 를 보내주는 api 입니다.
저는 json web token 을 client에게 응답으로 보내주고 싶습니다.
1. jsonwebtoken 패키지 설치
npm 으로 jsonwebtoken 패키지를 설치해줍니다.
1
$ npm i jsonwebtoken
2. jsonwebtoken 사용하기
우선 패키지를 불러와야겠죠.
1
const jwt = require("jsonwebtoken");
이제 user의 id 정보를 jsonwebtoken 으로 변환하여 client에게 response로 보내주겠습니다.
다음의 코드를 위의 회원가입 router에 추가합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const payload = { // json web token 으로 변환할 데이터 정보
user: {
id: user.id,
},
};
// json web token 생성하여 send 해주기
jwt.sign(
payload, // 변환할 데이터
"jwtSecret", // secret key 값
{ expiresIn: "1h" }, // token의 유효시간
(err, token) => {
if (err) throw err;
res.send({ token }); // token 값 response 해주기
}
);
회원가입 성공시 json web token을 응답해주는 api를 완성했습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
const express = require("express");
const bcrypt = require("bcryptjs");
const User = require("../../models/User");
const router = express.Router();
const jwt = require("jsonwebtoken");
// @route POST api/register
// @desc Register user
// @access Public
router.post(
"/",
async (req, res) => {
const { name, email, password } = req.body;
try {
let user = await User.findOne({ email });
// check user exists
if (user) {
return res
.status(400)
.json({ errors: [{ msg: "User already exists" }] });
}
user = new User({
name,
email,
password,
});
// Encrpyt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
// db에 user 저장
await user.save();
// json web token 생성 및 response
const payload = {
user: {
id: user.id,
},
};
jwt.sign(
payload, // token으로 변환할 데이터
"jwtSecret", // secret key 값
{ expiresIn: "1h" },// token의 유효시간을 1시간으로 설정
(err, token) => {
if (err) throw err;
res.send({ token });
}
);
} catch (error) {
console.error(error.message);
res.status(500).send("Server Error");
}
}
);
module.exports = router;
3. Postman으로 token 받기
이제 postman을 사용하여 회원가입 시 token을 잘 보내주는지 확인해보겠습니다.
다음과 같이 Header에서 content type을 json으로 설정해주시고 회원 가입 정보를 json 형태로 입력후 send 해주면 서버가 성공적으로 token을 보내주는 것을 확인할 수 있습니다.
Token으로 User 정보 받아오기
이제 이 받아온 token을 사용하여 DB에 저장된 user 정보를 받아와 보겠습니다.
우선 middleware를 만들어줘야 합니다. 이 middleware를 통해 client가 보내는 token이 유효한지 검사한 후 req에 user 정보를 할당합니다. 다음은 auth middleware의 코드입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const jwt = require("jsonwebtoken");
module.exports = function (req, res, next) {
// Get token from header
// header에서 x-auth-token 은 token의 key 값
const token = req.header("x-auth-token");
// Check if not token
if (!token) {
return res.status(401).json({ msg: "No token, authorization denied" });
}
// Verify token
try {
// token 해독, token을 만들 때 설정한 secret key 값 : jwtSecret
const decoded = jwt.verify(token, "jwtSecret");
// req에 해독한 user 정보 생성
req.user = decoded.user;
next();
} catch (error) {
res.status(401).json({ msg: "Token is not valid" });
}
};
이제 이 미들웨어를 사용하여 user 정보를 받아보겠습니다. 다음은 token을 사용하여 user 정보를 받아오는 router입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const express = require("express");
const router = express.Router();
const auth = require("../../middleware/auth"); // middleware 불러오기
const User = require("../../models/User");
const jwt = require("jsonwebtoken");
// @route GET api/auth
// @desc Auth
// @access Public
router.get("/", auth, async (req, res) => {
try {
// auth 미들웨어에서 생성해준 req.user를 사용하여 DB에서 user 탐색
const user = await User.findById(req.user.id).select("-password");
res.json(user);
} catch (error) {
console.error(error.message);
res.status(500).send("Server error");
}
});
get 안에 중간에 middleware auth를 넣어준 것을 확인할 수 있습니다.
Postman으로 확인하기
이제 postman에서 token을 request로 보내서 user 정보를 받아보도록 하겠습니다. Header에 위에서 받은 token을 넣어주고 Send를 누르면 다음과 같이 성공적으로 user 정보를 받아오는 것을 확인할 수 있습니다.