In a Golang app, I'm using gorilla/sessions with the mySQL backend to store data in a session but I'd like to store the data in the chi router context instead. How do I add auth token strings or structs into the context? I see plenty of examples explaining how to read/use them but none I saw explain how to insert the data into the context within a login function.
For example, the chi documentation here has the following code to check admin user which will work for me but it offers no clue as to how the auth object got into the context in the first place. There is another middleware function describing how to load an article struct into the context and gets its id parameter from the URL but that wont work for me. I don't really want to use a cookie as that would defeat the whole purpose in using the context.
// AdminOnly middleware restricts access to just administrators.
func AdminOnly(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
isAdmin, ok := r.Context().Value("acl.admin").(bool)
if !ok || !isAdmin {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
next.ServeHTTP(w, r)
})
}
In the example below I want to store the User struct or an auth token in the context.
Additionally, how would I handle flashes in the context? Can I do that or should I just stick to the db based sessions for web apps?
Ideally, I want to use the same method for both a web app serving templates and a separate API app.
Here is my web app login code, simplified a bit to remove the cruft:
func (rs *appResource) login(w http.ResponseWriter, r *http.Request) {
// appResource contains db connection, session store and templates
var authUser AuthUser //struct
session, err := rs.store.Get(r, "admin-data")
email := r.FormValue("email")
password := r.FormValue("password")
sqlStatement := "SELECT id, venue_id, first_name, last_name, email, password FROM Users WHERE email=?"
row := rs.db.QueryRow(sqlStatement, email)
err = row.Scan(&authUser.UserID, &authUser.VenueID, &authUser.FirstName, &authUser.LastName, &authUser.Email, &authUser.Password)
if err = bcrypt.CompareHashAndPassword([]byte(authUser.Password), []byte(password)); err != nil {
session.AddFlash("Your password is incorrect")
session.Save(r, w)
http.Redirect(w, r, "/signin", http.StatusFound)
return
}
authUser.Authenticated = true
session.Values["authUser"] = authUser
firstName := authUser.FirstName
message := fmt.Sprintf("Welcome, %s!", firstName)
session.AddFlash(message)
session.Save(r, w)
http.Redirect(w, r, "/", http.StatusFound)
}