Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use golang 1.7 context with http.Request (for Authentication)

Tags:

go

I have an IsAuthenticated function to check if the request is authenticated (checking the JWT in the Authorization header)

func IsAuthenticated(a *framework.AppContext, r *http.Request) (int, error) {
  // ... do authentication. user is authenticated User object
  ctx := context.WithValue(r.Context(), "user", user)
  r = r.WithContext(ctx) 
  return 200, nil
} 

I find that it appears that r = r.WithContext(ctx) does not override the request object? How should I implement this? Do I need to requrn a request instead?

like image 844
Jiew Meng Avatar asked Oct 23 '16 05:10

Jiew Meng


1 Answers

It is not clear to me exactly how what you show is a "middleware", or how it is being executed. Since you are only changing your local variable r, and never giving that to anyone else, there is no way your change wil be visible outside your function.

There have been a variety of middleware flavors in the go landscape, but since go 1.7 I have seen a lot more moving towards middleware functions of the form:

func IsAuthenticated(next http.Handler) http.Handler{
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
       //authenticate. Set cookies.
       //403 if not authenticated, etc.
       ctx := context.WithValue(r.Context(), "user",u)
       next(w,r.WithContext(ctx))
    })
}

This can be used to chain handlers together like so:

http.Handle("/foo/bar", IsAuthenticated(myHandler))

(or use something like alice to make chaining middlewares even easier.)

This way, when myHandler gets invoked, it will have the new request created by IsAuthenticated, and it can fetch the user with something like:

user := r.Context().Get("user").(*User)

like image 126
captncraig Avatar answered Sep 24 '22 15:09

captncraig