Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] Headers are not accessible in Middleware when Request sent from Browser #703

Open
akki4vedi opened this issue Nov 21, 2022 · 10 comments
Labels

Comments

@akki4vedi
Copy link

akki4vedi commented Nov 21, 2022

Describe the bug

A clear and concise description of what the bug is.
I am learning to add middleware in mux Router. I am getting token from request header and verifying it with hard written string. It is working fine when I send the request from Postman, but when I send the request from the web page, it never fetches the header in middleware. I have tried to send the request using all three methods fetch(), jquery ajax(), and Axios. But the result is same all the time.

Versions

Go version: 1.19.1
package version: v1.8.0 (gorilla/mux version)

Steps to Reproduce

send the request from browser. I am using Google Chrome v106.0.5249.103 (Official Build) (64-bit)

Expected behavior

value of header sent from browser

Code Snippets

A minimum viable code snippet can be useful! (use backticks to format it).

var userColl = make(map[string]string)

func main() {
	userColl["userTokenForA"] = "a"
	userColl["userTokenForB"] = "b"

	handleRequests()
}

func handleRequests() {
	router := mux.NewRouter().StrictSlash(true)
	router.PathPrefix("/public").Handler(http.StripPrefix("/public/", http.FileServer(http.Dir("./public/"))))
	router.Use(authenticate)
	router.HandleFunc("/todo", db.GetAllLists).Methods("GET")
	log.Fatal(http.ListenAndServe(":4010", router))
}
func authenticate(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

		token := r.Header.Get("authentication")
		user := userColl[token]
		fmt.Println("token", token, "user", user)
		w.Header().Set("Content-Type", "application/json")
		if user != "" { //&& userColl[token] == userId {
			fmt.Println("authorized...")
			r.Header.Set("user", user)
			next.ServeHTTP(w, r)
		} else {
			w.WriteHeader(http.StatusUnauthorized)
			json.NewEncoder(w).Encode(bson.M{
				"ERROR": "AUTHENTICATION FAILED",
			})
		}
	})
}

Front End :-

(()=> {
	axios("/todo", {
				method: "GET",
				headers: {
					authentication: "userTokenForA",
					"Content-Type": "application/json",
				},
	})
	.then((res) => {
		console.log("res", res)
	})
	.catch((err) => {
		console.log("error", err)
         })
})()

@akki4vedi akki4vedi added the bug label Nov 21, 2022
@akki4vedi akki4vedi changed the title [bug] Headers are not accessible in Middleware from Browser Request [bug] Headers are not accessible in Middleware when Request sent from Browser Nov 22, 2022
@amustaque97
Copy link
Contributor

Hey @akki4vedi, I went through the given code. I found an issue in the current implementation that (though it is the correct intended behaviour) authenticate middleware is applied on all the routes.

Technically speaking, when you're making a request to any route containing the public prefix middleware applies and expects you to send header authentication reason as mentioned before the middleware is applied on all the routes. If the header is missing it will return the status http.StatusUnauthorized on the static content page.

I'm guessing this is not what you want. Just to be clear If I'm not wrong you want static routes to be served without authentication. I would highly recommend you to go through the issue #360

I tried the same and it is working fine. Attaching a screenshot for reference.
Screenshot 2022-11-29 at 3 37 57 AM

I hope this helps and solves your problem. If yes, please close this issue else I would be happy to answer your doubts/queries. Thank you 🙌🏻

@akki4vedi
Copy link
Author

Thanks for the reply. Actually, I don't want to deactivate API for any route, there is only one route in my project to test authenticate middleware. So I am testing it and I am not able to get headers in the middleware, only when I send the request from Browser.
When I send the request from Postman, It works fine.
I can see that your middleware is perfectly working as your log msg is showing the value of userColl. This is not happening with my code. As I mentioned in the issue, I've tried sending the request in all three ways (fetch(), jquery ajax(), and Axios).

@amustaque97
Copy link
Contributor

What I have shown in the screenshot is from the browser only using the fetch API. Just that I need to add an exception to the static route in the middleware. As I mentioned before if you're not adding conditions for the static route, it will require an authentication header to be passed while making a request to the static endpoint from the browser.

@akki4vedi
Copy link
Author

akki4vedi commented Dec 1, 2022

I am passing the authentication header in the request.
image

But still, not able to read it in middleware.
image

This message is logged when I send the request from Postman.
image

I am not understanding why It's not working.

@soundkitchen
Copy link

Hi @akki4vedi
Since StrictSlash is true, this may be due to a redirect when accessing with /todo.
Could you try accessing /todo/ once?

@amustaque97
Copy link
Contributor

amustaque97 commented Dec 4, 2022

Hey @soundkitchen, I don't think it will work. I tried it and didn't get the expected output.

I'm sharing my screenshot for reference. We need to send the authentication header when hitting the URL /public from the browser.

In chrome browser {"ERROR":"AUTHENTICATION FAILED"} is from the code where I have written javascript code to hit /todo/ (note the strict slash).

Chrome dev tools console shows what I'm trying to say(on how we should send requests) if we don't want to exclude /public routes.

image

It doesn't matter if we're using fetch, axios or any other library. Middleware by definition is applied to all the routes. cc @akki4vedi

@akki4vedi
Copy link
Author

I've tried adding a slash in the route but still, it's not working. Here I'm attaching two screenshots of headers in middleware and in route,

  1. Headers in authenticate middleware
    image
  2. Headers in /todo route without authenticate middleware
    image

@soundkitchen
Copy link

@akki4vedi
I wrote the code and ran it, but I was able to get the headers in Middleware.

The first screenshot you pasted doesn't seem to have a Referrer, under what circumstances was this requested?
As long as the request is made from a browser using JavaScript, I would expect the Referrer to be present, but is there an exception?

@akki4vedi
Copy link
Author

I am simply calling the fetch API on load of javascript on the HTML page, the code is written in the issue as Front End. @soundkitchen & @amustaque97 Can I have code of API call in your app and the main method of the server for reference?

@soundkitchen
Copy link

@akki4vedi
The code I used for verification is below. I have tried to make it as similar to your code as possible.
gorilla_mux_703.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: No status
Development

No branches or pull requests

3 participants