LoginSignup
21
17

More than 5 years have passed since last update.

echoでRSAモードでJWTを使う

Posted at

JSON Web Token (JWT)はマイクロサービスの認証、認可に使える署名付きJSON。ユーザは内容を改ざんできないため、サーバ側に認証ステータスを保持しなくて良いし、検証時に認証サーバにアクセス不要。なので、スケーラブルな認証サービスをJSONのシンプルさを損なわず実装できる。GoogleはOAuth2のトークンに採用しているし、広く採用されている標準と言える。

Echoフレームワークでは、JWT Middlewareを使用可能。公式のサンプル

公式のサンプルは共有秘密鍵を使った署名であるHMACを使っているが、実際に運用する場合には秘密鍵を個別のマイクロサービスに複製しなくて良い公開鍵暗号方式の署名の方が楽なので、やりかたを調べてみた。

署名方法をRSAにして、JWTWithConfigをミドルウェアに渡してあげるだけ。楽チンですね :)

package main

import (
    "io/ioutil"
    "net/http"
    "time"

    jwt "github.com/dgrijalva/jwt-go"
    "github.com/labstack/echo"
    "github.com/labstack/echo/middleware"
)

func login(c echo.Context) error {
    username := c.FormValue("username")
    password := c.FormValue("password")

    if username == "jon" && password == "shhh!" {
        // Create token
        token := jwt.New(jwt.SigningMethodRS512)

        // Set claims
        claims := token.Claims.(jwt.MapClaims)
        claims["name"] = "Jon Snow"
        claims["admin"] = true
        claims["exp"] = time.Now().Add(time.Hour * 72).Unix()

        keyData, _ := ioutil.ReadFile("sample_key")
        key, _ := jwt.ParseRSAPrivateKeyFromPEM(keyData)
        // Generate encoded token and send it as response.
        t, err := token.SignedString(key)
        if err != nil {
            return err
        }
        return c.JSON(http.StatusOK, map[string]string{
            "token": t,
        })
    }

    return echo.ErrUnauthorized
}

func accessible(c echo.Context) error {
    return c.String(http.StatusOK, "Accessible")
}

func restricted(c echo.Context) error {
    user := c.Get("user").(*jwt.Token)
    claims := user.Claims.(jwt.MapClaims)
    name := claims["name"].(string)
    return c.String(http.StatusOK, "Welcome "+name+"!")
}

func main() {
    e := echo.New()

    // Middleware
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())

    // Login route
    e.POST("/login", login)

    // Unauthenticated route
    e.GET("/", accessible)

    // Restricted group
    r := e.Group("/restricted")

    keyData, _ := ioutil.ReadFile("sample_key.pub")
    key, _ := jwt.ParseRSAPublicKeyFromPEM(keyData)

    r.Use(middleware.JWTWithConfig(middleware.JWTConfig{
        SigningKey:    key,
        SigningMethod: "RS512",
    }))
    r.GET("", restricted)

    e.Logger.Fatal(e.Start(":1323"))
}

21
17
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
21
17