func (h *HOTP) Validate(token string) (bool, error) {
	if h.Key == "" {
		return false, errors.New("missing secret key for validation")
	}
	h.ensureDefaults()
	isValid := false
	for step := uint64(0); step <= h.Leeway; step++ {
		under := h.Counter - step
		expected, err := generateOTP(h.Key, under, h.Length, h.Algorithm)
		if err != nil {
			return false, err
		}
		if expected == token {
			isValid = true
			break
		}
		over := h.Counter + step
		expected, err = generateOTP(h.Key, over, h.Length, h.Algorithm)
		if err != nil {
			return false, err
		}
		if expected == token {
			isValid = true
			break
		}
	}
	if isValid {
		h.Counter++
	}
	return isValid, nil
}
Validate will try to check if the provided token is a valid OTP for the
current HOTP config. If the validation is successful the internal Counter
will be incremented by one.
package otpgo
import (
	"errors"
	"net/url"
	"strconv"
	"github.com/jltorresm/otpgo/authenticator"
	"github.com/jltorresm/otpgo/config"
)
const (
	HOTPDefaultLeeway uint64 = 1
)
type HOTP struct {
	Key       string               `json:"key"`        
	Counter   uint64               `json:"counter"`    
	Leeway    uint64               `json:"leeway"`     
	Algorithm config.HmacAlgorithm `json:"algorithm"`  
	Length    config.Length        `json:"length"`     
}
func (h *HOTP) Generate() (string, error) {
	h.ensureDefaults()
	if err := h.ensureKey(); err != nil {
		return "", err
	}
	return generateOTP(h.Key, h.Counter, h.Length, h.Algorithm)
}