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.