samedi 1 juillet 2017

Golang User cookie verification fails randomly

I'm using two structs to hold user's info

// SecureDevice holds a user's device's infos
type SecureDevice struct {
    Name     string // Defined by the user
    DeviceIP string
    Token    struct {
        Token        string
        StartingDate time.Time // The token is supposed to last only a week before becoming invalid
    }
}

// GlobalUser is a struct defining all user's infos registered inside the server
type GlobalUser struct {
    Username          string
    Password          string
    Salt              string
    Mail              string
    ValidationToken   string // Used to validate the user's mail adress
    Lang              string
    ConversationsID   []int // The private messages the user has part in
    SecureDevicesList []SecureDevice
}

And I'm using a function to check if the user is logged in

// IsLoggedIn checks if client's token is valid
func IsLoggedIn(r *http.Request) string {
    ips := strings.Split(r.Header.Get("X-Forwarded-For"), ", ")
    ip := ips[0]
    cookie, err := r.Cookie("auth")
    if err != nil {
        return "ERR$" + "not_connected"
    }
    cookieValue := strings.Split(cookie.Value, "$")
    println(cookie.Value)
    user := GetUser(cookieValue[0])
    userToken := cookieValue[1]
    if user.Username == "" {
        return "ERR$" + "error"
    }
    for _, SecureDevice := range user.SecureDevicesList {
        if SecureDevice.DeviceIP == ip && SecureDevice.Token.Token == userToken { // We make sure that the token provided is actually the user's token
            if time.Since(SecureDevice.Token.StartingDate)*time.Hour >= 168 { // If token is older than 1 week, we throw it away
                return "ERR$" + "error_token_expired"
            } else if time.Since(SecureDevice.Token.StartingDate)*time.Second >= 30 { // If it's age is between 1 hour and one week, we renew it
                db, err := scribble.New("./brony/db", nil)
                if err != nil {
                    return "ERR$" + "error_internal"
                }
                tokenBytes, err := GenerateRandomBytes(64) // Generates a salt
                if err != nil {
                    return "ERR$" + "error_internal"
                }
                token := base64.URLEncoding.EncodeToString(tokenBytes)
                SecureDevice.Token.Token = token
                SecureDevice.Token.StartingDate = time.Now()
                errr := db.Write("users", user.Username, user)
                if errr != nil {
                    return "ERR$" + "error_internal"
                }
                return "TOK$" + user.Username + "$" + SecureDevice.Token.Token
            } else if time.Since(SecureDevice.Token.StartingDate)*time.Hour <= 1 {
                return "NIL$"
            }
        } else if SecureDevice.DeviceIP == ip {
            return "ERR$" + "error_bad_token"
        }
    }
    return "ERR$" + "error_device_not_registered"
}

But almost always when I load the page with

status := IsLoggedIn(r)
println(status)

It often gives me an error, since I'm printing "IsLoggedIn" to understand where the problem comes from

At first I thought it was my token's renewal code which was faulty, but while beeing faulty and unfinished, it doesn't seem to be it's fault since after a few f5, it said that the cookie was ok. I really don't understand where the fault is, and it's starting to get really annoying, as I can't just let it be, it would be very annoying to say the least for a user to do f5 everytime and hope that when the page will refresh, it will miraculously work. The code runs on a debian server




Aucun commentaire:

Enregistrer un commentaire