jwt icon indicating copy to clipboard operation
jwt copied to clipboard

work with wildcard routing ?

Open Macrow opened this issue 4 years ago • 4 comments

I found this: https://github.com/gofiber/fiber/issues/207

but it seems that if I use wildcard routing, then I can't use this middleware, I just could handle jwt authentication in custom handler.

I want this middleware works with wildcard routing, anybody could tell me how?

thanks!

Macrow avatar Sep 19 '21 15:09 Macrow

Could you maybe provide a code snippet to illustrate the problem?

shytikov avatar Sep 19 '21 22:09 shytikov

func main() {
	app := fiber.New()

	// Login route
	app.Post("/login", login)

	// Unauthenticated route
	app.Get("/", accessible)

	// JWT Middleware
	app.Use(jwtware.New(jwtware.Config{
		SigningKey: []byte("secret"),
	}))

	// Restricted Routes
	app.Get("/restricted", restricted)

	// handle not found error (https: //docs.gofiber.io/extra/faq#how-do-i-handle-custom-404-responses)
	app.Use(func(c *fiber.Ctx) error {
		return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
	})

	app.Listen(":3000")
}

In this code snippet, if we visit some url(not exist) without jwt token, we can't reach not found handler.

according to gofiber/fiber#207 , we just could handle like this

func main() {
	app := fiber.New()

	// Login route
	app.Post("/login", login)

	// Unauthenticated route
	app.Get("/", accessible)

	// JWT Middleware <- we could not use this middleware
	//app.Use(jwtware.New(jwtware.Config{
	//	SigningKey: []byte("secret"),
	//}))

	// Restricted Routes
	app.Get("/restricted", jwtHandler, restricted)

	// handle not found error (https: //docs.gofiber.io/extra/faq#how-do-i-handle-custom-404-responses)
	app.Use(func(c *fiber.Ctx) error {
		return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
	})

	app.Listen(":3000")
}

func JwtHandler(c *fiber.Ctx) error {
	// retrieve raw token
	// parse raw token
	// store custom claims
	// store custom info into fiber.Locals
	// some authorization checking by casbin for example
	return c.Next()
}

Macrow avatar Sep 20 '21 03:09 Macrow

Not sure I'm getting information from gofiber/fiber#207 right, so maybe @ReneWerner87 could correct me there, but for me that looks like desired behavior – seems to be that all auth middleware work this way in fiber – people won't be able to discover the structure of the website (or an API) if they would try to.

But I believe it could be some workarounds for that:

  • Add auth middleware before specific route, like here: https://github.com/gofiber/fiber/issues/207#issuecomment-596080462;
  • If there are too many routes, maybe it would be possible to group them and add auth middleware to selected groups only;
  • If it's still undesired, you may try to override ErrorHandler in the configuration of this middleware, so instead of sending 401 in case of missing token it would let the execution path through. And you could check the presence of a token in ctx.Locals() map. And in case if it is missing you may send 401 from your handler instead.

But please don't take my words as the final truth, I'm not the top banana here :)

shytikov avatar Sep 20 '21 06:09 shytikov

@shytikov Thanks for your reply, you are great! :)

Here is my solution for now

method.go

func assembleHandler(handler ...fiber.Handler) []fiber.Handler {
	h := make([]fiber.Handler, 0, len(handler) + 1)
	h = append(h, auth.JwtHandler)
	h = append(h, handler...)
	return h
}

func AuthGet(router fiber.Router, path string, handler ...fiber.Handler) fiber.Router {
	return router.Get(path, assembleHandler(handler...)...)
}

func AuthPost(router fiber.Router, path string, handler ...fiber.Handler) fiber.Router {
	return router.Post(path, assembleHandler(handler...)...)
}

func AuthPut(router fiber.Router, path string, handler ...fiber.Handler) fiber.Router {
	return router.Put(path, assembleHandler(handler...)...)
}

func AuthPatch(router fiber.Router, path string, handler ...fiber.Handler) fiber.Router {
	return router.Patch(path, assembleHandler(handler...)...)
}

func AuthDelete(router fiber.Router, path string, handler ...fiber.Handler) fiber.Router {
	return router.Delete(path, assembleHandler(handler...)...)
}

route.go

func Routes(app *fiber.App) {
        // not handle auth
        app.Get("/your-path", v1.SomeService)
        
        // v1
        apiV1 := app.Group("/api/v1")
        
        // auth
        auth := apiV1.Group("auth")
        // handle auth
        AuthPost(auth, "/login", v1.Login)
}

There should be a better way.

Macrow avatar Sep 20 '21 10:09 Macrow

@ReneWerner87 This is from v1, can it be closed?

gaby avatar Apr 11 '23 02:04 gaby