json web token 簡單筆記

Basic

通常使用在驗證client是否已登入過,若Client將未失效token藉由header一起發送,則視為已登入
與傳統session最大分別在jwt驗證不需要在Server存任何訊息

流程

  • Client request login
  • Server驗證User並建立jwt
  • jwt由User的非敏感信息與expire time …etc組成
  • token會藉由server的private key以HMAC alg.加密
  • Client之後的所有request皆需在header中帶上此token
  • Server收到token後使用密鑰解開並檢查是否失效,並根據token中的user信息判斷request user

very easy example

以下code用來理解用
實際server端code使用library node-jsonwebtoken

1
2
3
4
5
6
7
8
9
10
// javascript
// Server
var header = { 'typ': 'JWT', 'alg': 'HS256' };
var payload = { "sub": "1234567890", "name": "John Doe", "admin": true };
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret');
var token = encodedString + '.' + signature;
// Client
fetch('api/user/1', { headers: { 'Authorization': 'Bearer ' + token } })

node-jsonwebtoken example

https://github.com/auth0/node-jsonwebtoken

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
const jwt = require('jsonwebtoken');
const expiresIn = '30m';
const createJwt = (user) => {
return jwt.sign(user, configs.app.privateKey, {
expiresIn: expiresIn,
issuer: configs.app.name,
});
}
const verifyJwt = (jwtString) => {
return jwt.verify(jwtString, configs.app.privateKey, {
issuer: configs.app.name,
});
}
// if user not found, create it. and return user and generated jwt
const checkUser = (userInfo) => {
return db.tx('authenticationController.checkUser', function* (t) {
let user = yield t.users.findByMail(mail);
if(!user) {
user = yield t.users.add({mail, picture});
}
return {user, faceblockToken: createJwt(user)};
});
}
const login = (req) => {
return getUserInfoFromSocial(req.params.socialSite, req.params.socialToken)
.then(userInfo => {
if(!userInfo || !userInfo.email) throw Errors.authenticationError();
return checkUser(userInfo);
}).then(userWithJwt => {
let response = {
authentication: {
userId: userWithJwt.user.id,
faceblockToken: userWithJwt.faceblockToken,
}
}
return response;
}
const authenticate = (req) => {
try {
let faceblockToken = req.headers['faceblock-token'];
let userFromJwt = verifyJwt(faceblockToken);
return db.users.find(userFromJwt.id);
} catch(error) {
throw Errors.authenticationError(error);
}
}