fiber: šŸ¤— [Question]: 403 forbidden on POST CSRF request

Question Description

Hi, I’ve set up the frontend and backend to both use HTTPS. I’m trying to create the Synchronizer Token Pattern CSRF Login pre-session using the CSRF middleware. I have a GET response that sets up the CSRF and Session tokens but the POST fails. The header seems to be identically named, the headers are there, both frontend and backend (AllowHeaders: ā€œcontent-type,x-csrf-tokenā€), but I get this 403 error.

Code attached. Am I missing something?

Code Snippet (optional)

Backend code:

presessionConfig := csrf.Config{
		Session:        sessionManager,
		Storage:        memoryStorage, 
		KeyLookup:      "header:X-CSRF-Token", // I feel that here's the issue, but I don't see how
		CookieName:     "__Host-csrf",
		CookieSameSite: "Lax",
		CookieSecure:   true,
		CookieHTTPOnly: false,
		ContextKey:     "csrf", // and that this might interfere somehow
		ErrorHandler:   csrfErrorHandler,
		Expiration:     30 * time.Minute,
	}
	presessionMiddleware := csrf.New(presessionConfig)

	app.Get("/login", presessionMiddleware, func(c *fiber.Ctx) error {
		csrfToken, ok := c.Locals("csrf").(string)
		if !ok {
			return c.SendStatus(fiber.StatusInternalServerError)
		}

		sessionTokenUUID := uuid.New()
		sessionTokenString := sessionTokenUUID.String()
		err := memoryStorage.Set(sessionTokenString, []byte("tempTest"), 120*time.Second)
		if err != nil {
			return err
		}

		return c.Status(fiber.StatusOK).JSON(fiber.Map{
			"csrf":    csrfToken,
			"session": sessionTokenString,
		})
	})

	app.Post("/login", presessionMiddleware, func(c *fiber.Ctx) error {
		... stuff happens here. Nothing to throw a 403 error here, at all. ...
		return c.SendStatus(200)
	})

Frontend request:

export async function getUser(data: { email: string; password: string, csrf: string }): Promise<any> {
    const response = await fetch(
        "https://localhost:3000/login",
        {
            method: "POST",
            mode: "cors",
            credentials: "include",
            headers: {
                "Content-Type": "application/json",
                "X-CSRF-Token": data.csrf,
                cookie: "__Host-csrf="+data.csrf
            },
            body: JSON.stringify(data)
        },
    )
    return response.json()
}

Checklist:

  • I agree to follow Fiber’s Code of Conduct.
  • I have checked for existing issues that describe my questions prior to opening this one.
  • I understand that improperly formatted questions may be closed without explanation.

About this issue

  • Original URL
  • State: closed
  • Created 8 months ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

Yeah, I’ll go with a reverse proxy.

Will setup that reverse proxy and then report it here the next days, so that if someone hits the same wall like me doesn’t repeat my mistakes.

It’s an invalid Referer which is what I mentioned earlier. https://localhost:5173 to https://localhost:3000 is a cross origin post. The middleware is functioning as expected.

I suggest using http for local dev with react.

Or

You could put it behind a reverse proxy so that they come from the same host (and port), per the example I shared earlier. The example isn’t setup for dev debugging react yet, but I’ll be adding that shortly.

I’ll see what I can find out and post it here, most likely tomorrow. I’ll first see how I can debug more using a custom CSRF error handler, maybe that will give me a better hint.

@romanian-bag-void you can also make a custom error handler for csrf to see what error is actually causing the forbidden

example: https://github.com/gofiber/recipes/blob/master/csrf-with-session/main.go

If it’s react, you’re request is Cross origin because you’re using different ports for the host.

Browsers will not let js set a Referer header, my example prior only works in node js.

You would need to either put them behind a reverse proxy or use HTTP.