Fastify で JWT 認証をどう実現するか
Fastify で JWT 認証をするための選択肢として fastify-jwt というエコシステムがあります。
今回はこれを使用してみようと思います。
fastify-jwt について
最初に余談にはなりますが公式にこう書いてあるんですね
As with JavaScript, where everything is an object, with Fastify everything is a plugin.
JavaScript はすべてがオブジェクトだけど、Fastify は全てプラグインということらしいです。(知らなかった)
ということで、fastify-jwt もプラグインとして Fastify に追加します。
import fastify from 'fastify'
import jwt from '@fastify/jwt'
const server = fastify()
server.register(jwt, { secret: 'supersecret' })
これによって supersecret
という共通キーで JWT を作成することができます。
使ってみる
プラグインを追加すると fastify に jwt が追加されるため、あとは好きなペイロードで sign したり verify したりできます。
server.post('/login', () => {
return server.jwt.sign({ name: 'inoh' })
})
サーバーを起動して実行してみると JWT が返却されることが確認できます。
server.listen({ port: 9999 })
※ 9999 ポートで起動してる前提になります
curl --request POST --url http://localhost:9999/login
# eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaW5vaCIsImlhdCI6MTcxMjQ2NDc2Nn0.MK4j6nXFBneArlfjWE1j0ipmMi-N_8Cee0fKZ5m5lrU
次に認証してみます。
request に jwtVerify が拡張されているため、このメソッドを使用して認証します。
server.get('/me', async (request) => {
return await request.jwtVerify()
})
API をリクエストしてみると正常に Payload が取得されることが確認できました。
curl --request GET --url http://localhost:9999/me \
--header 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiaW5vaCIsImlhdCI6MTcxMjQ2NDc2Nn0.MK4j6nXFBneArlfjWE1j0ipmMi-N_8Cee0fKZ5m5lrU'
# { "name": "inoh", "iat": 1712464766 }
デフォルトでは exp が設定されていないため有効期限はなさそうです。
当然 JWT を指定しないとエラーになります。
curl --request GET --url http://localhost:9999/me
# {"statusCode":401,"code":"FST_JWT_NO_AUTHORIZATION_IN_HEADER","error":"Unauthorized","message":"No Authorization was found in request.headers"}
HS256 前提で今回試していますが、register を使用してプラグインを追加するだけで簡単に JWT 認証が実現できるため、認証のサービスを作るためのハードルはかなり下がっている感じがしますね。
RS256 前提でサンプルコードも書いてみたので参考にしてみてください!
Discussion