JS: jsrsasign xác thực JWT



Xin nhắc lại là: JWT sinh ra là để bảo mật với cách thức xác nhận. Không phải chỉ để truyền đối tượng kiểu JSON dưới dạng string. Và phần bảo mật là phần chữ ký, không phải payload

// các code ở dưới bạn có thể INSPECT và chạy

// chuẩn bị header
var sHeader = JSON.stringify({alg: "HS256"});

// chuẩn bị payload
var oPayload = {};
var tNow = KJUR.jws.IntDate.get('now');
// thiết lập hạn của token là 1 giờ sau khi token tạo ra
var tEnd = KJUR.jws.IntDate.get('now + 1hour');
oPayload.exp = tEnd; oPayload.iat = tNow;
// exp , iat .. là những key ngầm hiểu của JWT (nói sau)
oPayload.user = "diepgepa";

var sPayload = JSON.stringify(oPayload);

// tạo token với từ khóa bí mật : "69696969"
var secretMe = '69696969';
var sJWS = KJUR.jws.JWS.sign(null, sHeader, sPayload, secretMe );

// xác thực token sJWS ở trên với 2 thời điểm để thấy sự khác biệt
var a = {alg: ['HS256'],verifyAt: KJUR.jws.IntDate.get('now')},
 b = {alg: ['HS256'],verifyAt: KJUR.jws.IntDate.get('now + 1year')},
 c = {alg: ['HS256']};

console.log(KJUR.jws.JWS.verifyJWT(sJWS, secretMe , a));
console.log(KJUR.jws.JWS.verifyJWT(sJWS, secretMe , b));
console.log(KJUR.jws.JWS.verifyJWT(sJWS, secretMe , c));


Với a là true, vì còn thời hạn, với b là false vì quá thời hạn, với c là true vì tôi không kiểm tra thời hạn.

Từ đó mà bạn sẽ biết máy chủ mà bạn viết ra cần gì, làm thế nào? (jsrsasign mà bạn đang sử dụng được tôi nhúng vào trang, jsrsasign cũng có thư viện cho NodeJs - client và server nói chung 1 tiếng nói javascript, chắc bạn hiểu tôi đang nói cái gì, chỉ là bạn nên hiểu 1 vài ranh giới, đùng bao giờ gõ console.log(window) trên máy chủ chạy nodejs :D)


---
 Đối với: JWS signature algorithm  RS256 (SHA256withRSA RSA2048bit:z4) chuẩn bị:
RSA PRIVATE KEY, PUBLIC KEY ( trung gian ở giữa 2 key là từ khóa bí mật: SECRET_ME_RSA )

Tạo các mã bằng openssl: SECRET_ME_RSA chọn là: 123456xdf

openssl genrsa -des3 -out private.pem -passout pass:123456xdf 2048
openssl rsa -in private.pem -pubout > private.pub -passin pass:123456xdf

Mở 2 file: private.pem và private.pub, ta có, pri_key , pub_key, ví dụ:

var pri_key = `
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,DC06D91EB0999E41

hwMmY4vCr99hLeRie1kxtPB+WsCOgU2clQZkCYmSsk4XxYtDfoH1KDmrELJ4KDeM
Y33+qmNP63UkZOK9veVrgBnzZBv0DlNg0hnLVTj0UWv82OQIyDScl5O7k1ZpeW4A
3dEQRYunvHjE43GTTX5N4QRfbCwvKXCByopKIVtPLikqsgfyvvM7lMf3JBWK3CmW
q7Ebhrcdi5koJ3d5OWFguyKrLYRATw2noPSjLBYakTQWN1jK2BBTJvUDf1H6TC+8
eUSTHOeUSqjBLYMAudQ50CR9Ta6COVLNZAJNi5uzB6XobvFTV3cGwOBmJgJWX8sd
7QXuPfymaM7rkKGbLQ9pXiDM+LWVwZn/hbCKsk/3w4fyiqrbWv4f3fkvlhjjC5+K
kpC3dtzbrIvIceJw9lqUacCzTplSI0bfWgSNdbLZ38jMnQzDJtFRi9aHqjyCs9Gy
yiQ3VaKhqN01X3asBioHzo/zsXDtObLaWq6U0XTRIbM9owrxUeknvRcT5d/WksTq
SYDz7PIe22/8PniZtL8Oi6x8Vlj4qqmp0ytSR/nDSVMxQPvZeYagI/N86NgI4O+/
2GBJkrlDR5YPYPOUbrsx4xamMVyl1OwOtqdD0tNKM8jworbl0bv86J614HiOPZH/
xZoQnHmLWZ2+49Eqm3rmHVer7qHxABJNiTmiwqRevtbs+H38HUp5cYJF5wc52bkw
GbutrAFjnhFTuwsDtRMggxZmJ9f4XB9UwTmyB7kjXiCzLkRZJWvTPtLelOVuoRyS
tgEbBwJeUCR0fWzDJo9riEBnf00zcpWI0h9syeUPThhqnydMdjLX9ZEsxq1DwjUO
y5d7tTeCUYOxme86+D4g3t/fUGLh0hNnMP9D8Q7EFN3f7w6XSQ3YxgtpBpWloQXE
lVzf0jZ++ucvGt6XtXpH8XIndyYTFZvqDD1BzSEgphRvllmRVTTWUaI8DzUEM0wr
BiexHscvT2bKqR4rB7WOAs4rUD58354Q/tBa/umvRu35xyFsi3RqVMOFtYAenKVi
ZA+1xwwfkR/etjOMdVvzpyOvNNRa9u2DVuyVIX9GqLY4inL+3qmCtIiFVJy+85rc
rXgLlUTfnRAWOPREJU8yORlxwpLsEup29dlU3HManF5ra9a/zMzv2U3LZURI2OX9
SRKkS1uAf3YOJjAw3a9wbv3U5zeMqsyrh/pTX2ddDSrsGwBeZthbv/XMLb1c3pb5
KoVIT3RIrjeZIr7DZDbV+ZJCJ+HhM+VBRbH7a8HfOa8oY/p/nP102TpQS99FQ9X3
x0z7q6aLY+inlTyh1P/k1Vm/LFOoDmrmd5JqofvfoaEGLYuLb9sfPyMTop8iN1FZ
v85EaK02GusK7sYtyNUdVKBMhyi2Y1PW3td5Oium2RknHcj3Ot4YPxsohajoHYtY
cbM9DLlDLzYDUQqrHSP4NaMKqOnz7b2JIMzYzacGSBI63Mqi0QoFR9xRQ/dhplha
4K2Hl/nbZoVyIMyNHZyzdr66V2v//qRzMpE6c2TiCZJM2DKgG88LzWMgX7vNgiYu
mtu7sFdVR9lxB0wZVhpcUH5fsaNHq9FIqq/NM4pnA8A3fcVK7lI1yQ==
-----END RSA PRIVATE KEY-----
`, pub_key = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkdsqZISQmpYplZTVaYpo
A2oLAlU0Zc+nkddYR1YK6W9uwRWjq0w5a6EwQrreVF3f8rq0mqWRwXUlcDf2xqYD
W6oBFPp7dXOi0axxsHAoGNq9aJk5OAmhSiOv4THiYPtn46I+bAKe0bqGhTIt0ZkR
WrJSg7W16L7pnXtIetBWrIuizGa3sLgiG/yuSqkIC0EHkpUKsRGpQEC+8rKus9fM
b512Jv1H6UPRymh6ZVVo/ct28Uy5pHfNjRs0McUu2fHbnpMdtiPKqsjY64shxaBx
jgx00Yq/7HBe5Hsq6/LiQiTnj+PFkRuvDo+tG4zhBJWHcUtAQKF6JuGhMHiCAdEV
5QIDAQAB
-----END PUBLIC KEY-----
`;

// bước 1: chuẩn bị: payload và header, ở ví dụ đầu tiên trong bài viết,
// payload có thêm các key ngầm định, ở đây không cho vào
var sHeader = JSON.stringify({alg: "RS256"});
var sPayload = '{"user": "diepgepa"}';
var a = KJUR.jws.JWS;

// tạo token
var token = a.sign(null, sHeader, sPayload, pri_key,'123456xdf');
console.log(token);

// xác thực
a.verifyJWT( token, pub_key, {alg:['RS256']});

Nếu sử dụng KEYUTIL:

// tạo token
var util_gen = KEYUTIL.getKey(pri_key,'123456xdf');
var token = a.sign(null, sHeader, sPayload, util_gen);
console.log(token);
// xác thực
var util_verify = KEYUTIL.getKey(pub_key);
a.verifyJWT( token, util_verify, {alg:['RS256']});


Để tạo mô hình cung cấp dịch vụ: bạn tự ứng xử phù hợp:
RSA PRIVATE KEY, PUBLIC KEY, SECRET_ME_RSA

---
Các key ngầm định của payload:


  • Issuer(iss)
  • Subject(sub)
  • Not Before Time(nbf)
  • Expiration Time(exp)
  • Issue At Time(iat)
  • JWT ID(jti)
  • Type(typ)
Ví dụ đầu tiên, tôi có demo exp, iat để nắm được hạn thời gian của token, ngoài ra bạn có thể tham khảo


Thắc mắc, hãy comment...

Bài viết tham khảo các tài liệu và faqs:
https://self-issued.info/docs/draft-ietf-oauth-json-web-token.html
https://stackoverflow.com/questions/4294689/how-to-generate-an-openssl-key-using-a-passphrase-from-the-command-line
@Hoàng Thanh

Nhận xét