---
# System prepended metadata

title: Token-Based Authentication JWT

---

# Token-Based Authentication JWT

## JWT 介紹
1. JSON Web Token (JWT) 是一種基於 JSON 的開放標準(RFC 7519)，基於 JSON object 的編碼，並透過這個編碼進行傳遞資訊。
2. JWT會透過HMAC、RSA、ECDS等演算法進行加密
[https://jwt.io/](https://jwt.io/)
## JWT 組成
JWT 分為 Header, Payload, Signature 三個部份以 Base64 編碼, 並且以 . 分開。
eg: `xxxxx.yyyyy.zzzzz`

* **Header**
Header 由 alg, typ 兩個欄位所組成
1. alg: Signature 所要使用的加密演算法
2. typ: token 種類，基本上是 JWT
eg:
```json=
{
    "alg": "HS256",
    "typ": "JWT"
}
```

* **Payload** 
Payload 是用來傳送訊息（claim）的地方（也可以空白），主要有三種內容
1. Registered claims: 一些已經標準公認的訊息，建議放，但不強迫
    * iss: JWT簽發者
    * iat: JWT簽發時間
    * exp: JWT的過期時間
    * ...
2. Public claims: 可以向官方申請公開聲明
3. Private claims: 自定義的訊息
eg:
```json=
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
```
:::warning 
**由於加密只作用於 Signature ，因此 Payload 不應該存放隱私資訊**
:::

* **Signature**
Signature 由三個部份組成
1. base64UrlEncode(header)
2. base64UrlEncode(payload)
3. secret
```
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)
```
signature 是用來確保訊息不會在傳送途中被竄改，並且有一個 private secret key 用來確保 JWT 發行者的正確性
## JWT 使用
* 流程
![](https://i.imgur.com/7uX2Hxh.png)
* client 端使用方法
當使用需要驗證的 api 時，在 Authorization header 使用 Bearer schema
```
Authorization: Bearer <token>
```

## Server 範例
``` javascript
import jsonwebtoken from "jsonwebtoken";
import express, { urlencoded } from "express";
import "dotenv/config";

const app = express();
app.use(urlencoded({ extended: true }));
app.post("/login", async (req, res, next) => {
  const { id } = req.body;
  const token = jsonwebtoken.sign({ id: id }, process.env.JWT_SIGN_SECRET, {
    noTimestamp: true,
    algorithm: process.env.JWT_ALGO,
  });
  return res.status(200).json({ jwt: token });
});

app.get("/hello", async (req, res, next) => {
  try {
    const token = req.header("Authorization").replace("Bearer ", "");
    const decoded = jsonwebtoken.verify(token, process.env.JWT_SIGN_SECRET, {
      algorithm: process.env.JWT_ALGO,
    });
    return res.status(200).send(`Hello ${decoded.id}`);
  } catch (e) {
    return res.status(404).send({ error: "Please authenticate." });
  }
});

app.listen(8080, () => {
  console.log(`
################################################
🛡️  HTTP server listening on port: 8080 🛡️
################################################
`);
});

```
## JWT with Nginx
[https://github.com/TeslaGov/ngx-http-auth-jwt-module](https://github.com/TeslaGov/ngx-http-auth-jwt-module)
[https://github.com/auth0/nginx-jwt](https://github.com/auth0/nginx-jwt)
待更新



## 流程
![](https://i.imgur.com/5UOpEwX.png)










```javascript=
import express, { Router, urlencoded, json } from "express";
import { createProxyMiddleware } from "http-proxy-middleware";
import jsonwebtoken from "jsonwebtoken";
import morgan from "morgan";
// Create Express Server
const app = express();

// Configuration
const PORT = 3000;
const HOST = "localhost";
const API_SERVICE_URL = "http://127.0.0.1:4444/";

const route = Router();

app.post("/login", async (req, res, next) => {
  const { id } = req.body;
  const token = jsonwebtoken.sign({ id: id }, "ABCDEFG");
  return res.status(200).json({ jwt: token });
});

// Proxy endpoints
app.use("/wd/hub/session/", morgan("common"), route);
route.post(
  "/",
  createProxyMiddleware({
    target: API_SERVICE_URL,
    changeOrigin: true,
    onProxyReq(proxyReq, req, res) {
      try {
        let data = "";
        let token;
        req.on("data", (chunk) => {
          data += chunk;
        });
        req.on("end", () => {
          //console.log(JSON.parse(data).capabilities.auth);
          token = JSON.parse(data).capabilities.auth;
          console.log(token);
          jsonwebtoken.verify(token, "ABCDEFG");
          proxyReq.end();
        });
        proxyReq.setHeader("content-type", "application/json; charset=utf-8");
        proxyReq.write(data);
        
      } catch (e) {
        console.log(e);
        return res.status(404).send({ error: "Please authenticate." });
      }
    },
  })
);
route.post(
  "/:id",
  morgan("common"),
  createProxyMiddleware({
    target: API_SERVICE_URL,
    changeOrigin: true,
  })
);
// Start Proxy
app.listen(PORT, HOST, () => {
  console.log(`Starting Proxy at ${HOST}:${PORT}`);
});
```


###### tags: JWT Nginx