Troubles using middleware in a go-kit microservice

Hello, all… I’m relatively new to GoLang, so my problem is most likely either user error, or user inexperience…

I’m seasoned in Java and C++, so I thought it might be fun to learn Golang by implementing a microservice that I have done in Java in the past. So far, everything seems to be progressing fine: I have separation of concern properly implemented where my service does just what the service is supposed to do and I’ve successfully wrapped that service with logging, instrumenting, circuit breaker, and rate-limiting middleware (largely thanks to go-kit and their examples). However, I seem to be missing something critical when trying to add go-kit’s JWT library in order to do authentication of requests. I’ve followed the very few online examples I’ve found where it basically says to add a middleware layer of: NewParser and NewSigner functions. However, whenever I debug and add breakpoints in either the token issuance endpoint, or in any endpoint that requires authentication via JWT. At either of the breakpoints, I don’t see anything in the context with the key that Go-Kit says should be there. When using something like Insomnia or Postman, I see no “Authrorization” header even being returned from the middleware. Can anyone point me to where I may be able to get some help on figuring out what is or isn’t happening (or more likely, what I’m doing wrong)?

Thanks in advance!

Do you have a login endpoint where you issue the JWT?

Yes, I am even explicitly adding (temporarily for debugging purposes) the token to the JSON response in order to compare it with what I expect to have set in the header. I get the token in the body JSON, but nothing in the header, as I expect I should. Docs say I should get a header record with “authentication: bearer randomtoken”, but I don’t even get the record at all. Plus, if I manually add the header record using the token from the body, I still get an error from the secured endpoints telling me no token was set in the context. So, I think the token isn’t being properly moved from the context to the response and not properly getting moved from the requests to the context on subsequent endpoint calls.

It has to be in the header, so something is wrong there. I have ’t used go-kit :neutral_face: but this worked for me using gin and chi. Most of the frameworks use, so the problem is somewhere out of this package.

Yes, Go-Kit uses as well. Just for sanity’s sake, here is how I’m setting up my middleware in the tokenEndpoint (called from the login endpoint)

	var tokenEndpoint endpoint.Endpoint
		tokenEndpoint = MakeTokenEndpoint(svc)
		tokenEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 1))(tokenEndpoint)
		tokenEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(tokenEndpoint)
		tokenEndpoint = LoggingMiddleware(log.With(logger, "method", "Token"))(tokenEndpoint)
		tokenEndpoint = InstrumentingMiddleware(token_duration.With("method", "Token"))(tokenEndpoint)
		tokenEndpoint = jwt.NewSigner("kid", signingKey, stdjwt.SigningMethodHS256, stdjwt.StandardClaims{Audience: "NCMS"} )(tokenEndpoint)

If I understand correctly, the order of defining middleware starts with the innermost service (defined first), followed by the reverse order you want your middleware to execute in. So, in my case, it would run the jwt.NewSigner(…) middleware first, followed by InstrumentingMiddleware, and so on until it got to the “MakeTokenEndpoint”.

And, here is the middleware stack for one of the endpoints that require authentication:

	var changeUpdateEndpoint endpoint.Endpoint
		changeUpdateEndpoint = MakeCreateUpdateEndpoint(svc)
		changeUpdateEndpoint = ratelimit.NewErroringLimiter(rate.NewLimiter(rate.Every(time.Second), 1))(changeUpdateEndpoint)
		changeUpdateEndpoint = circuitbreaker.Gobreaker(gobreaker.NewCircuitBreaker(gobreaker.Settings{}))(changeUpdateEndpoint)
		changeUpdateEndpoint = LoggingMiddleware(log.With(logger, "method", "CreateUpdate"))(changeUpdateEndpoint)
		changeUpdateEndpoint = InstrumentingMiddleware(cu_duration.With("method", "CreateUpdate"))(changeUpdateEndpoint)
		changeUpdateEndpoint = jwt.NewParser(signingKey, stdjwt.SigningMethodHS256, jwt.StandardClaimsFactory)(changeUpdateEndpoint)

…again the first middleware to fire would be the jwt.NewParser… correct?

If so, then it is definitely an issue with go-kit, because putting a breakpoint in the first line of the Instrumenting middleware in both instances shows nothing in the request header, nor anything in the context.

In the interim, I am going to look at chi and gin to see if they would be easy to implement along-side go-kit (since I’m still successfully using it for the other middleware and microservice framework.)

Try to remove all other middlewares until you resolve this. So keep just jwt stuff.

will give that a try. It can only make it easier. :slight_smile:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.