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},
JWT認証
headerにtokenをつけて、認証を行うJWT認証部分が、v4と変わっていました。
以前のコードでは動かなかったのとechoのリファレンス自体には記載されていなかった為、
こちらで記載させて頂きます。
※ golang-jwt/jwt ライブラリーには実装方法について記載されていると説明が書いてありました。
v4とv5-alphaの違いを簡単にいうと
(middleware.CORSConfig{})に渡せる引数が消されてしまったという所になります。
下記が実際の箇所の変更部分のソースコードになります。
jwt.go JWTConfig struct
ではどう対処するかなのですが、リファレンスでは、
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) に書き換え
こちらで以上となります。
他、ルーティングや色々変わっている部分がある為
わかったらこちらに追加しようと思っております。