---
# System prepended metadata

title: "\U0001F3C5 Day 27 - JWT 產生身份驗證 token"
tags: [Node.js 直播班 - 2023 春季班]

---

---
tags: Node.js 直播班 - 2023 春季班
---

# 🏅 Day 27 - JWT 產生身份驗證 token

[JWT 流程圖](https://whimsical.com/jwt-UKUY1rj1vfoN6uyic7e4Sm)

![](https://i.imgur.com/C2fj19V.png)

當使用者登入或註冊，後端經過驗證後確認資料格式正確，就會產生一組的 token 回傳至使用者（client 端），此 token 用於身份驗證，接下來 client 端造訪需權限的頁面、發送需要權限的請求，若未帶上此 token 或是 token 驗證錯誤，都會請求失敗

接下來會使用 jsonwebtoken（JWT） 套件中的 `sign()` 實作產生 token 的流程（流程圖步驟 2）
```javascript
const jwt = require('jsonwebtoken');
jwt.sign(payload, secretOrPrivateKey, \[options, callback\])
```
- payload 會是一個物件，為該使用者的相關資訊（如 id）
- secretOrPrivateKey 私鑰可以是字串、buffer 或物件，這裡會加入一段字串（如：`secret`）並設定為環境變數 `process.env.JWT_SECRET`
- options 或 callback 函式，options 為一個物件，可根據文件中有提供的選項客製化，例如：設定此 token 的到期日
```javascript
const token = jwt.sign({id:id},process.env.JWT_SECRET,{
      expiresIn: process.env.JWT_EXPIRES_DAY
    });
```
產生出的 token 會以 . 分隔，其中第一二段的 header 及 payload 都是可以透過 base64 編碼得知內容的
```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.  # header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.  # payload
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ  # signature
```
### 參考資源

- [jwt.sign()](https://github.com/auth0/node-jsonwebtoken#jwtsignpayload-secretorprivatekey-options-callback)
- [什麼是 JWT](https://5xruby.tw/posts/what-is-jwt)

## 題目
延續前一天的每日任務，優化註冊功能，當使用者的資料都通過自訂的驗證條件，並成功新增使用者資料後，使用 `jwt.sign()` 產生 JWT，並回傳給 client（回傳內容須包含 token、使用者名稱 name）


回傳範例
![](https://i.imgur.com/pvum5TA.png =600x)




## 回報流程

將答案連結貼至底下回報就算完成了喔! 
解答位置請參考下圖（需打開程式碼的部分觀看）

![](https://i.imgur.com/vftL5i0.png)

<!-- 解答：  

```javascript
範例參考 https://github.com/gonsakon/express-week4-sample/blob/week6/routes/users.js

router.post('/sign_up', handleErrorAsync(async(req, res, next) =>{
  let { email, password, confirmPassword, name } = req.body;
  // 內容不可為空
  if(!email||!password||!confirmPassword||!name){
    return next(appError("400","欄位未填寫正確！",next));
  }
  // 密碼正確
  if(password!==confirmPassword){
    return next(appError("400","密碼不一致！",next));
  }
  // 密碼 8 碼以上
  if(!validator.isLength(password,{min:8})){
    return next(appError("400","密碼字數低於 8 碼",next));
  }
  // 是否為 Email
  if(!validator.isEmail(email)){
    return next(appError("400","Email 格式不正確",next));
  }
  // 加密密碼
  password = await bcrypt.hash(password,12);
  const newUser = await User.create({
    email,
    password,
    name
  });

  // 產生 JWT
  const token = jwt.sign({id:newUser._id},process.env.JWT_SECRET,{
    expiresIn: process.env.JWT_EXPIRES_DAY
  });
  
  // 將 token 回傳至 client
  res.status(200).json({
    status: 'success',
    user:{
      token,
      name: newUser.name
    }
  });
}))
```

-->



回報區
---

| 報數 |       組別／Discord 名字       |                            Codepen／HackMD／其他回饋                             |
|:----:|:-----------------------:|:-------------------------------------------------------------------------:|
| 1 | 中 4 組 / jimkk159 | [HackMD - Day 27](https://hackmd.io/8IqjRhKNS0SY75Ne3Fevfw) |
| 2 | 北 16 組 / 文文 | [HackMD - Day 27](https://github.com/chiawen81/nodeJS_DailyTasks_d20/tree/8dbd84fab6cabd474b57dc322591d0d9fedb4834) |
|  3  | 北 13 組 / Louisa  | [GitHub - Day 27](https://github.com/louisa0416/NodejsEnterpriseClass/tree/master/daily-task/day27) |
|  4  | 南 1 組 / hiYifang  | [HackMD - Day 27](https://hackmd.io/@gPeowpvtQX2Om6AmD-s3xw/S1WEL_yPc) |

