Search code examples
goframeworksrouterbasic-authentication

How to ignore one router for BasicAuth check with Echo framework?


In order to use basic auth to protect the whole application this way can do for all the routers:

package main

import (
    "crypto/subtle"
    "net/http"

    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

type Message struct {
    Status string `json:"status"`
}

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

    e.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
        if subtle.ConstantTimeCompare([]byte(username), []byte("username")) == 1 &&
            subtle.ConstantTimeCompare([]byte(password), []byte("password")) == 1 {
            return true, nil
        }
        return false, nil
    }))

    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })

    e.GET("/hello", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello")
    })

    e.GET("/healthcheck", func(c echo.Context) error {
        u := &Message{
            Status: "OK",
        }
        return c.JSON(http.StatusOK, u)
    })
    e.Logger.Fatal(e.Start(":8080"))
}

If want to ignore one router -- /healthcheck to its target, how to do?

If set e.Use(middleware.BasicAuth) to each router except /healthcheck will resolve the issue, but it needs to many codes.


Solution

  • You can Group routes

    package main
    
    import (
        "crypto/subtle"
        "net/http"
    
        "github.com/labstack/echo/v4"
        "github.com/labstack/echo/v4/middleware"
    )
    
    type Message struct {
        Status string `json:"status"`
    }
    
    func main() {
        e := echo.New()
        g := e.Group("/")
        g.Use(middleware.BasicAuth(func(username, password string, c echo.Context) (bool, error) {
            if subtle.ConstantTimeCompare([]byte(username), []byte("username")) == 1 &&
                subtle.ConstantTimeCompare([]byte(password), []byte("password")) == 1 {
                return true, nil
            }
            return false, nil
        }))
    
        g.GET("/", func(c echo.Context) error {
            return c.String(http.StatusOK, "Hello, World!")
        })
    
        e.GET("/healthcheck", func(c echo.Context) error {
            u := &Message{
                Status: "OK",
            }
            return c.JSON(http.StatusOK, u)
        })
        e.Logger.Fatal(e.Start(":8080"))
    }