LoginSignup
1
0

More than 1 year has passed since last update.

Golang echoフレームワークのv4からv5-alphaにアップデートした際の詰まった部分のメモ

Last updated at Posted at 2022-06-13

golangフレームワークechoでV5-alphaがリリースされていたので
V4からV5-alphaにアップデートした際に少し詰まった箇所のメモ

※ alphaバージョンなので変更や修正があるかもしれないので注意してください
後、golangは個人で最近自己学習を始めたので間違っているかもしれません。

リポジトリや説明は下記の記事に記載しております。

middlewareのCORS middleware
https://echo.labstack.com/middleware/cors/

echo.GETのようにアクセスできなくなった為、下記のように書き換え
ソースコードを見るとecho.GETは間接的にhttp.MethodGetを読んでいた為
どちらも同じ意味の様です。

AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE},

AllowMethods: []string{http.MethodGet, http.MethodPut, http.MethodPost, http.MethodDelete},

スクリーンショット 2022-06-14 1.07.15.png

JWT認証

headerにtokenをつけて、認証を行うJWT認証部分が、v4と変わっていました。
以前のコードでは動かなかったのとechoのリファレンス自体には記載されていなかった為、
こちらで記載させて頂きます。
※ golang-jwt/jwt ライブラリーには実装方法について記載されていると説明が書いてありました。

スクリーンショット 2022-06-14 1.17.58.png

v4とv5-alphaの違いを簡単にいうと

(middleware.CORSConfig{})に渡せる引数が消されてしまったという所になります。

下記が実際の箇所の変更部分のソースコードになります。
jwt.go JWTConfig struct
スクリーンショット 2022-06-14 2.18.07.png
ではどう対処するかなのですが、リファレンスでは、
middleware.JWTConfig{}に

ParseTokenFunc: CreateJWTGoParseTokenFunc([]byte("secret"), nil),

を渡しています。
ParseTokenFuncの説明を見ると
ParseTokenFunc defines a user-defined function that parses token from given auth. Returns an error when token parsing fails or parsed token is invalid. Defaults to implementation using github.com/golang-jwt/jwt as JWT implementation library
と書かれており、ユーザー定数関数というのを渡す様です。

ということはユーザー定数関数は、CreateJWTGoParseTokenFuncということになり
引数は、このCreateJWTGoParseTokenFunc()を渡せば良いことになります。

しかし、CreateJWTGoParseTokenFunc()の実装例がechoのリファレンスに記載されておらず
ここで少し難儀しました。
ググってみると下記のドキュメントにいきつき、
CreateJWTGoParseTokenFunc()をみつけました。

// CreateJWTGoParseTokenFunc creates JWTGo implementation for ParseTokenFunc
//
// signingKey is signing key to validate token.
// This is one of the options to provide a token validation key.
// The order of precedence is a user-defined SigningKeys and SigningKey.
// Required if signingKeys is not provided.
//
// signingKeys is Map of signing keys to validate token with kid field usage.
// This is one of the options to provide a token validation key.
// The order of precedence is a user-defined SigningKeys and SigningKey.
// Required if signingKey is not provided
func CreateJWTGoParseTokenFunc(signingKey interface{}, signingKeys map[string]interface{}) func(c echo.Context, auth string) (interface{}, error) {
	// keyFunc defines a user-defined function that supplies the public key for a token validation.
	// The function shall take care of verifying the signing algorithm and selecting the proper key.
	// A user-defined KeyFunc can be useful if tokens are issued by an external party.
	keyFunc := func(t *jwt.Token) (interface{}, error) {
		if t.Method.Alg() != middleware.AlgorithmHS256 {
			return nil, fmt.Errorf("unexpected jwt signing method=%v", t.Header["alg"])
		}
		if len(signingKeys) == 0 {
			return signingKey, nil
		}

		if kid, ok := t.Header["kid"].(string); ok {
			if key, ok := signingKeys[kid]; ok {
				return key, nil
			}
		}
		return nil, fmt.Errorf("unexpected jwt key id=%v", t.Header["kid"])
	}

	return func(c echo.Context, auth string) (interface{}, error) {
		token, err := jwt.ParseWithClaims(auth, jwt.MapClaims{}, keyFunc) // you could add your default claims here
		if err != nil {
			return nil, err
		}
		if !token.Valid {
			return nil, errors.New("invalid token")
		}
		return token, nil
	}
}

で、実際に上記の関数を写経し、下記のv4のコードを
v5-alphaに書き換えてみました。

結果として、CreateJWTGoParseTokenFunc()関数は写経したそのままでは
使えず、一部書き換える必要がありました。

書き換えた箇所はjwt.MapClaimsの記述をjwtCustomClaimsに書き直しました。

jwtCustomClaimsというは何なのか?というとtokenを作るときに、独自の情報を追加することができ
その追加する情報はなんなのかを定義した物になります。Custom Claimと言います。
渡されたtokenを復元する際もどのようなデータが詰まっているか
わからないので、tokenを作成する際に使ったCustom Claimを使用し
tokenに含まれるユーザー情報等を取得します。
一般的にはtoken有効期限やユーザーIDなどを保存しておきます。
ですので、jwtCustomClaimsに関してはそれぞれ異なりますので
注意してください

下記の方の記事が分かりやすいと思います。
JWTの実装等に関しては下記を参考にしてください。

V4のコードrouting部分の抜粋

	config := middleware.JWTConfig{
		Claims:     &model.JwtCustomClaims{},
		SigningKey: []byte("secret"),
	}
	api := e.Group("/api")
	// api 下はJWTの認証が必要
	api.Use(middleware.JWTWithConfig(config))
	api.GET("/restricted", h.Refresh)
    api.POST("/logout", h.Logout)

V5-Alphaのコードrouting部分の抜粋

api := e.Group("/api")
// api 下はJWTの認証が必要
api.Use(middleware.JWTWithConfig(
	middleware.JWTConfig{
		ParseTokenFunc: CreateJWTGoParseTokenFunc([]byte("secret"), nil),
	}))
api.GET("/restricted", h.Refresh)
api.POST("/logout", h.Logout)

CreateJWTGoParseTokenFunc()の写経部分

jwt.MapClaims => jwtCustomClaims(custom claims) に書き換え
スクリーンショット 2022-06-14 14.35.05.png

debugで確認
JwtCustomClaims
スクリーンショット 2022-06-14 0.41.54.png

MapClaims
スクリーンショット 2022-06-14 0.38.39.png

こちらで以上となります。
他、ルーティングや色々変わっている部分がある為
わかったらこちらに追加しようと思っております。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0