自前で JWT を発行、検証を Node.js で行う

Node.js で JSON Web Token (JWT) の ID トークンを発行し、検証する処理のメモです。 JWT のメリットはアクセストークンそのものが有効期間やコンテクストを保持できるため、個別にリクエストごとにセッションIDからセッション情報を引くという機構を省くことができます。そのため、自前の API サーバにおいて、アクセストークンとして JWT の ID トークンを使えるとサーバ処理を省力化できます。 今回の例では、JWT の検証をグローバルにできるようにはせず、サーバ内でのみ行うこととします。一般的な JWT トークンは JSON Web Key (JWK) Set から提供されており、JWT の署名検証ができるようになっていますが、それは行いません。 依存ライブラリ Auth0 がものすごく便利なライブラリを提供してくれています。 https://github.com/auth0/node-jsonwebtoken $ npm i -save jsonwebtoken $ npm i -save-dev @types/jsonwebtoken 鍵の生成 公開鍵と秘密鍵を別々にすることも可能ですが、分けると管理が面倒なのと同一サーバ内で処理するため、PEMファイルで管理します。 $ openssl genrsa > auth.pem 発行と検証処理 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 import fs from 'fs' import jwt from 'jsonwebtoken' const PEM = fs.readFileSync('auth.pem') function issueToken(subject: string): string { const opts: jwt.SignOptions = { algorithm: 'RS256', issuer: 'https://issuer.example.com', expiresIn: '1d', // https://github.com/zeit/ms } const payload = { sub: subject, } return jwt.sign(payload, PEM, opts) } export async function verifyToken(idToken: string): Promise<object> { const opts: jwt.VerifyOptions = { algorithms: ['RS256'], issuer: 'https://issuer.example.com', maxAge: '1d', // https://github.com/zeit/ms } return new Promise((resolve, reject) => { jwt.verify(idToken, PEM, opts, (err: Error, decoded: any) => { if (err) { reject(err) } else { resolve(decoded) } }) }) } // 実行確認 ;(async () => { const idToken = issueToken('userId') const result = await verifyToken(idToken) console.log(result) })() JWT 署名時の expiresIn より時間が経過している場合は、検証時に TokenExpiredError: jwt expired がスローされます。 時間内であっても発行時よりも maxAge が経過している場合は、検証時に TokenExpiredError: maxAge exceeded がスローされます。 実行結果 1 2 3 4 5 6 { sub: 'userId', iat: 1582639938, exp: 1582726338, iss: 'https://issuer.example.com' } まとめ ログイン成功時に issueToken を呼んで ID トークンをクライアントに発行します。クライアントは API リクエストの Authorization ヘッダに付与して、サーバ側は verifyToken で検証することで、認証および subject(sub)フィールドなどからユーザー情報を取得することができます。

2020年2月24日 · Toshimitsu Takahashi