Fiber JWT
JWT ミドルウェアは、JSON Web Token (JWT) 認証ミドルウェアを返します。有効なトークンの場合、ユーザーを Ctx.Locals に設定し、次のハンドラーを呼び出します。無効なトークンの場合は、「401 - 認証されていません」エラーを返します。トークンが不足している場合は、「400 - リクエストが不正です」エラーを返します。
注: Go バージョン 1.19 以上が必要です
インストール
このミドルウェアは Fiber v1 および v2 をサポートしています。それぞれに合わせてインストールしてください。
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/jwt
go get -u github.com/golang-jwt/jwt/v5
シグネチャ
jwtware.New(config ...jwtware.Config) func(*fiber.Ctx) error
設定
プロパティ | タイプ | 説明 | デフォルト値 |
---|---|---|---|
Filter | func(*fiber.Ctx) bool |
ミドルウェアをスキップするための関数 | nil |
SuccessHandler | func(*fiber.Ctx) error |
有効なトークンがある場合に実行する関数 | nil |
ErrorHandler | func(*fiber.Ctx, error) error |
無効なトークンがある場合に実行する関数 | 401 Invalid or expired JWT |
SigningKey | interface{} |
トークンを検証するために使用される署名キー。SigningKeys の長さが 0 の場合はフォールバックとして使用されます | nil |
SigningKeys | map[string]interface{} |
kid フィールドを持つトークンを検証するために使用される署名キーのマッピング |
nil |
ContextKey | string |
コンテキスト内のトークンからユーザー情報を格納するために使用されるコンテキストキー | "user" |
Claims | jwt.Claim |
トークン内容を定義する拡張クレームデータ | jwt.MapClaims{} |
TokenLookup | string |
トークンを解析するために使用されるフォーマット : を含む文字列 |
"header:Authorization" |
AuthScheme | string |
Authorization ヘッダーで使用される AuthScheme。デフォルト値 ("Bearer") はデフォルトの TokenLookup 値と一緒に使用されます |
"Bearer" |
KeyFunc | func() jwt.Keyfunc |
トークンの検証のために公開鍵を提供するユーザー定義関数 | jwtKeyFunc |
JWKSetURLs | []string |
JWT の解析に使用される一意の JSON Web Key (JWK) Set URL のスライス | nil |
HS256 の例
package main
import (
"time"
"github.com/gofiber/fiber/v2"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
app := fiber.New()
// ログインルート
app.Post("/login", login)
// 認証なしでアクセス可能なルート
app.Get("/", accessible)
// JWT ミドルウェア
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{Key: []byte("secret")},
}))
// 制限付きルート
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// 認証エラーをスロー
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// クレームを作成
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// トークンを作成
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// エンコードされたトークンを生成してレスポンスとして送信
t, err := token.SignedString([]byte("secret"))
if err != nil {
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": t})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("アクセス可能")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("ようこそ " + name + " さん")
}
HS256 テスト
ユーザー名とパスワードでログインしてトークンを取得します。
curl --data "user=john&pass=doe" http://localhost:3000/login
レスポンス
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
}
認証ヘッダー内のトークンを使用してリクエストを制限されたリソースに送信します。
curl localhost:3000/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
レスポンス
Welcome John Doe
package main
import (
"crypto/rand"
"crypto/rsa"
"log"
"time"
"github.com/gofiber/fiber/v2"
"github.com/golang-jwt/jwt/v5"
jwtware "github.com/gofiber/contrib/jwt"
)
var (
// 明らかに、これは単なるテストの例です。本番環境では行わないでください。
// 本番環境では、事前にキーペアを生成する必要があります。
// 私鍵を GitHub リポジトリに追加しないでください。
privateKey *rsa.PrivateKey
)
func main() {
app := fiber.New()
// デモ用に、プログラムが実行されるたびに新しい秘密鍵/公開鍵ペアを生成します。上記の注釈を参照してください。
rng := rand.Reader
var err error
privateKey, err = rsa.GenerateKey(rng, 2048)
if err != nil {
log.Fatalf("rsa.GenerateKey:%v", err)
}
// ログインルート
app.Post("/login", login)
// 認証なしのルート
app.Get("/", accessible)
// JWT ミドルウェア
app.Use(jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{
JWTAlg: jwtware.RS256,
Key: privateKey.Public(),
},
}))
// 制限されたルート
app.Get("/restricted", restricted)
app.Listen(":3000")
}
func login(c *fiber.Ctx) error {
user := c.FormValue("user")
pass := c.FormValue("pass")
// 認証エラーをスロー
if user != "john" || pass != "doe" {
return c.SendStatus(fiber.StatusUnauthorized)
}
// クレームを作成
claims := jwt.MapClaims{
"name": "John Doe",
"admin": true,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
// トークンを作成
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
// エンコードされたトークンを生成してレスポンスとして送信します
t, err := token.SignedString(privateKey)
if err != nil {
log.Printf("token.SignedString:%v", err)
return c.SendStatus(fiber.StatusInternalServerError)
}
return c.JSON(fiber.Map{"token": t})
}
func accessible(c *fiber.Ctx) error {
return c.SendString("Accessible")
}
func restricted(c *fiber.Ctx) error {
user := c.Locals("user").(*jwt.Token)
claims := user.Claims.(jwt.MapClaims)
name := claims["name"].(string)
return c.SendString("Welcome " + name)
}
RS256 テスト
RS256 は上記の HS256 テストと本質的に同じです。
JWK セット テスト
これらのテストは基本の JWT テストと同じですが、JWK Set 形式の有効な公開鍵セットが JWKSetURLs に必要です。
カスタム KeyFunc の例
KeyFunc は、トークンの検証に使用されるユーザー定義の関数を定義します。この関数は、署名アルゴリズムの検証および正しいキーの選択に責任を持ちます。もしトークンが外部のパーティによって発行された場合、ユーザー定義の KeyFunc が役立つかもしれません。
ユーザー定義の KeyFunc が提供されると、SigningKey、SigningKeys、および SigningMethod は無視されます。これはトークン検証キーを提供するための三つのオプションのうちの一つです。優先順位は、ユーザー定義の KeyFunc、SigningKeys、SigningKey の順です。SigningKeys と SigningKey の両方が提供されない場合、この関数は必ず提供されなければなりません。デフォルトでは、内部実装を使用して署名アルゴリズムを検証し、適切なキーを選択します。
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/golang-jwt/jwt/v5"
)
func main() {
app := fiber.New()
app.Use(jwtware.New(jwtware.Config{
KeyFunc: customKeyFunc(),
}))
app.Get("/ok", func(c *fiber.Ctx) error {
return c.SendString("OK")
})
}
func customKeyFunc() jwt.Keyfunc {
return func(t *jwt.Token) (interface{}, error) {
// 署名メソッドが正しいかどうかを確認
if t.Method.Alg() != jwtware.HS256 {
return nil, fmt.Errorf("予期しない jwt 署名メソッド=%v", t.Header["alg"])
}
// 署名キーのカスタム読み込みを実装する、たとえば、データベースから読み込む
signingKey := "secret"
return []byte(signingKey), nil
}
}