# 🏅 Day 30 - JWT 驗證 middleware
延續前一天,我們可以將 isAuth 作為 middlware,將需要登入後才能進入、操作的頁面或功能都帶入 isAuth middlware,確認使用者身份後再繼續執行
題目
---
根據需求,補上 `...` 的部分完整程式碼
1. 優化 `isAuth`,確認 token 存在並確認是否為 Bearer 開頭字串。
若符合此條件則取出 JWT 字串,若未成功取得 JWT,表示使用者可能尚未登入,需回傳 401 錯誤與錯誤訊息 `'使用者尚未登入!'`
```javascript=
const isAuth = handleErrorAsync(async (req, res, next) => {
// 確認 token 是否存在並取出 token
let token;
if (
req.headers.authorization &&
req.headers.authorization....('...')
) {
token = req.headers.authorization.split(' ')[1];
}
// token 不存在,回傳錯誤訊息
if (!token) {
return appError(...);
}
// 驗證 token 正確性
const decoded = await new Promise((resolve,reject) => {
jwt.verify(token, process.env.JWT_SECRET, (err, payload) => {
if (err) {
reject(err)
} else {
resolve(payload)
}
});
});
// 在資料庫尋找對應 id 的使用者
const currentUser = await User.findById(decoded.id);
// 在 req 物件加入 user 欄位,並由 next() 帶到 handleErrorAsync(async(req,res,next)=>{...})
req.user = currentUser;
next();
});
```
2. 設計取得個人資料路由 `GET /users/profile`,加入 isAuth middleware,當 request 帶上的 token 驗證通過,就將取出的 user 資料回傳給 client
`routes/users.js`
```javascript=
router.get('/profile', ..., handleErrorAsync(async (req, res, next) =>{
res.status(200).json({
status: 'success',
user: ...
});
}))
```
## 回報流程
將答案寫在 CodePen 並複製 CodePen 連結貼至底下回報就算完成了喔!
解答位置請參考下圖(需打開程式碼的部分觀看)

<!-- 解答:
1. isAuth
```javascript=
const isAuth = handleErrorAsync(async (req, res, next) => {
// 確認 token 是否存在並取出 token
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
) {
token = req.headers.authorization.split(' ')[1];
}
// token 不存在,回傳錯誤訊息
if (!token) {
return appError(401, '使用者尚未登入!', next);
}
// 驗證 token 正確性
const decoded = await new Promise((resolve,reject) => {
jwt.verify(token, process.env.JWT_SECRET, (err, payload) => {
if (err) {
reject(err)
} else {
resolve(payload)
}
});
});
// 在資料庫尋找對應 id 的使用者
const currentUser = await User.findById(decoded.id);
// 在 req 物件加入 user 欄位,並由 next() 帶到 handleErrorAsync(async(req,res,next)=>{...})
req.user = currentUser;
next();
});
```
2. routes/users.js
```javascript=
router.get('/profile', isAuth, handleErrorAsync(async (req, res, next) =>{
res.status(200).json({
status: 'success',
user: req.user
});
}))
```
-->
回報區
---
<!--
將答案貼至下方表格內,格式:
| Discord 暱稱 | [CodePen](連結) |
-->
| Discord | CodePen / 答案 |
|:-------------:|:-----------------:|
| xxx | [CodePen]() |
|lobinda|[HackMD](https://hackmd.io/@Lobinda/HkRby9bX0)|
|jenny7532|[CodePen](https://codepen.io/wei-chen-wu/pen/BaeNPgL)|
|Chia Pin|[CodePen](https://codepen.io/joker-cat/pen/MWdwPPa)|
|wei|[CodePen](https://hackmd.io/@xu7yoa5cSsqaron7h9XhUw/HyRhxJzXC)|
|william_hsu|[CodePen](https://codepen.io/william8815/pen/VwOLgzM)|
|ej_chuang|[CodePen](https://codepen.io/EJChuang/pen/VwOLNVj)|
|苡安|[hackmd](https://hackmd.io/@L7K9-66lSeagS28AP0_GjQ/ByHwTRM7C)|
|william威良|[CodePen](https://codepen.io/snowman12320/pen/LYopNwO?editors=1010)|
|Hank|[CodePen](https://codepen.io/tw1720/pen/wvbvaaL)|
|Tiya|[CodePen](https://codepen.io/Tiya_blank/pen/rNbQPbY)|
| runweiting |[CodePen](https://codepen.io/weiting14/pen/eYaZoPy)|
|mei|[CodePen](https://codepen.io/l_umei/pen/QWRKZVM)|
| fabio20 | [CodePen](https://codepen.io/fabio7621/pen/pomNZPK) |