简体   繁体   中英

Can I put JWT token in Context in Golang Echo framework?

I am learning how to implement the useful, and robust web server can with Echo Framework with Golang.

Now I am trying to build a real user authentication attaching JWT tokens and Hash function.
Within Echo Official Documentation, and several blog posts, I made the authentication process putting jwt token in cookie and taking out it when entering route restricted.

But, It is said that saving authentication methods in cookie, local storage, and session storage is very dangerous, because someone who i don't know is enable to access this 3 methods, and invade my secret information.

Then I am trying to save tokens in echo Context, not cookies.

I write the code putting tokens in context, but i don't know how can i take them from context, and submit to authentication process.

Maybe the property TokenLookup in jwt config decides where i can store tokens, such as header, cookie, query, and params. Then Can i store JWT tokens in the echo context?

I attached my example code.

package main

import (
    "fmt"
    "net/http"
    "time"

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

// jwtCustomClaims are custom claims extending default ones.
type jwtCustomClaims struct {
    Name  string `json:"name"`
    Admin bool   `json:"admin"`
    jwt.StandardClaims
}

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

    // Throws unauthorized error
    if username != "jon" || password != "shhh!" {
        return echo.ErrUnauthorized
    }

    // Set custom claims
    claims := &jwtCustomClaims{
        "Jon Snow",
        true,
        jwt.StandardClaims{
            ExpiresAt: time.Now().Add(time.Hour * 3).Unix(),
        },
    }

    // Create token with claims
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    // Generate encoded token and send it as response.
    t, err := token.SignedString([]byte("secret"))
    if err != nil {
        return err
    }

    c.Set("Authorization", fmt.Sprintf("Bearer %s", t))
    return c.Redirect(http.StatusPermanentRedirect, "/restricted")
}

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.(*jwtCustomClaims)
    name := claims.Name
    return c.String(http.StatusOK, "Welcome "+name+"!")
}

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

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

    // Login route
    e.GET("/login", func(c echo.Context) error {
        return c.HTML(http.StatusOK,
            `
                <html>
                    <head>
                        <meta charset="utf-8" />
                        <title>Login Page</title>
                    </head>
                    <body>
                        <form action="/login" method="post">
                            <input type="text" name="username" />
                            <input type="text" name="password" />
                            <button type="submit">Action</button>
                        </form>
                    </body>
                </html>
            `,
        )
    })
    e.POST("/login", login)

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

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

    // Configure middleware with the custom claims type
    config := middleware.JWTConfig{
        Claims:      &jwtCustomClaims{},
        SigningKey:  []byte("secret"),
        TokenLookup: "cookie:FakeToken",
    }
    r.Use(middleware.JWTWithConfig(config))
    r.GET("", restricted)

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

Saving tokens in context is executed in the function login.

Reading https://echo.labstack.com/guide/context ,

echo.Context represents the context of the current HTTP request. It holds request and response reference, path, path parameters, data, registered handler and APIs to read request and write response. As Context is an interface, it is easy to extend it with custom APIs.

This can't replace client side storage of credentials. After all, the client is what needs to authenticate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM