package endpoints import ( "encoding/json" "net/http" "time" "github.com/golang-jwt/jwt/v4" "github.com/imosed/signet/auth" . "github.com/imosed/signet/data" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) type LoginResponse struct { Token *string `json:"token"` } func Login(w http.ResponseWriter, r *http.Request) { var req AuthenticationRequest err := json.NewDecoder(r.Body).Decode(&req) if err != nil { log.Error().Err(err).Msg("Failed to decode body in login attempt") return } var userData struct { ID uint Password string Privileges uint } var resp LoginResponse Db.Table("users").Select("id, password, privileges"). Where("username = ?", req.Username).First(&userData) var passwordMatches bool passwordMatches, err = ComparePasswordAndHash(req.Password, userData.Password) if err != nil { log.Error().Err(err).Msg("Could not compare password to hash in login attempt") return } if !passwordMatches { resp.Token = nil err = json.NewEncoder(w).Encode(resp) if err != nil { log.Error().Err(err).Msg("Failed to deliver failed login attempt response") } return } token := jwt.NewWithClaims(jwt.SigningMethodHS256, &auth.Claims{ Username: req.Username, Privileges: userData.Privileges, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(10 * time.Hour)), }, }) secret := viper.GetString("app.secretKey") tokenString, err := token.SignedString([]byte(secret)) if err != nil { log.Error().Err(err).Msg("Could not generate JWT token") return } resp.Token = &tokenString err = json.NewEncoder(w).Encode(resp) if err != nil { log.Error().Err(err).Msg("Could not deliver response in Login call") } }