// Check two-factor func (u *User) IsValidTwoFactor(token string) bool { // Do we have two factor enabled? if len(u.TwoFactorSeed) == 0 { // No, OK pass log.Println(fmt.Sprintf("WARN: User %s login without two-factor enabled", u.DisplayName())) return true } // Configure token var cotp *dgoogauth.OTPConfig = &dgoogauth.OTPConfig{ Secret: u.TwoFactorSeed, WindowSize: 3, } // Validate token authRes, authErr := cotp.Authenticate(token) if authErr != nil || authRes == false { log.Println(fmt.Sprintf("WARN: User %s failed two-factor challenge, invalid token", u.DisplayName())) return false } else { // OK return true } // By default error return false }
// Validate totp token func (u *User) ValidateTotp(t string) bool { // No token set / provided? if len(u.TotpSecret) < 1 || len(strings.TrimSpace(t)) < 1 { return false } // Validate cotp := dgoogauth.OTPConfig{ Secret: u.TotpSecret, WindowSize: TOTP_MAX_WINDOWS, } res, _ := cotp.Authenticate(t) return res }
// Get user two factor data func GetUser2fa(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { jr := jresp.NewJsonResp() if !authUser(r) { jr.Error("Not authorized") fmt.Fprint(w, jr.ToString(debug)) return } // User user := getUser(r) if user.HasTwoFactor() { jr.Error("Two factor authentication already setup") fmt.Fprint(w, jr.ToString(debug)) return } // Create TOTP conf secret := TotpSecret() cotp := dgoogauth.OTPConfig{ Secret: secret, WindowSize: TOTP_MAX_WINDOWS, } // Image uri qrCodeImageUri := cotp.ProvisionURI(fmt.Sprintf("indispenso:%s", user.Username)) // QR code qrCode, qrErr := qr.Encode(qrCodeImageUri, qr.H) if qrErr != nil { jr.Error("Failed to generate QR code") fmt.Fprint(w, jr.ToString(debug)) return } // Save user, not yet enabled user.TotpSecret = secret server.userStore.save() jr.Set("Secret", user.TotpSecret) jr.Set("Png", qrCode.PNG()) jr.OK() fmt.Fprint(w, jr.ToString(debug)) }