JSON Web Token: 認証に使える


前提


ドキュメント


JWT概要


JWTの3要素

  1. ヘッダ
    • アルゴリズム情報(JSON)
  2. ペイロード
    • 認証情報など任意のデータ(JSON)
  3. 署名
    • ヘッダ.ペイロードを署名

最終的にJWTは、ヘッダ.ペイロード.署名のように、3要素を.区切りで繋げたものになる。


生成の流れ

  1. ヘッダとペイロードを、それぞれBase64-URLでエンコードして、.区切りで繋げる
  2. 1を署名(HMAC, RSA, ECDSA)し、それをBase64-URLでエンコードする
  3. 1と2を.で繋げる

Base64-URL

function base64url(str) {
  return Buffer.from(str).toString('base64')
    .replace(/=/g, '') // パディング消す
    .replace(/\+/g, '-') // ハイフンに
    .replace(/\//g, '_') // アンダーバーに
}

npmでの利用

npm install jsonwebtoken

jwaパッケージ

const jwa = require('jwa')
const hmac = jwa('HS256') // アルゴリズムHMAC(SHA-256)
let payload = { a: 1 }
let secret = 'pass'

// 署名だけ作成
let signature = hmac.sign(payload, secret)
// => 'ZewmHCjasFpyVFY-7sT10OSULDsJz4kL-2-U0tihpeE'

// 検証
hmac.verify(payload, signature, secret) // true
hmac.verify(payload, signature, 'no-pass') // false

jwsパッケージ

const jws = require('jws')

const header = { alg: 'HS256' } // アルゴリズムHMAC(SHA-256)
let payload = { a: 1 }
let secret = 'pass'

// JWT生成
let token = jws.sign({
  header: header,
  payload: payload,
  secret: secret
})
// => eyJhbGciOiJIUzI1NiJ9.eyJhIjoxfQ.M0xOVzCJoy4FPjgCYKUDe--4aCrnlctjv-74iJ4u8jA

// 検証
jws.verify(token, header.alg, secret) // true
jws.verify(token, header.alg, 'no-pass') // false

// デコード
let obj = jws.decode(token)
/*
{ header: { alg: 'HS256' },
  payload: '{"a":1}',
  signature: 'M0xOVzCJoy4FPjgCYKUDe--4aCrnlctjv-74iJ4u8jA' }
*/

jsonwebtokenパッケージ

const jwt = require('jsonwebtoken')
// デフォルト: アルゴリズムHMAC(SHA-256)

let payload =  { user: 'alice', ログイン: true }
let secret = 'pass'

// JWT生成
let token = jwt.sign(payload, secret)
console.log(token)

// 検証
let options = {complete:true} // 全体をデコード
jwt.verify(token, secret, options, (error, decode) => {
  console.log(decode)
  let date = new Date(decode.payload.iat * 1000) // ミリ秒へ
  console.log(date) // 2019-09-20T08:56:57.000Z
})
/*
{ header: { alg: 'HS256', typ: 'JWT' },
  payload: { user: 'alice', 'ログイン': true, iat: 1568969817 },
  signature: 'QlloP6vnxY2U8VnS0a_zWBfMbJJgqYCQuYPsqb02DVA' }
*/