add expiry/size to otp

This commit is contained in:
Asim Aslam
2021-06-08 11:15:47 +01:00
parent 702fda8269
commit 9437ca4b86
4 changed files with 93 additions and 37 deletions

View File

@@ -15,20 +15,33 @@ import (
type Otp struct{}
type otpKey struct {
Secret string
Expiry uint
}
func (e *Otp) Generate(ctx context.Context, req *pb.GenerateRequest, rsp *pb.GenerateResponse) error {
if len(req.Id) == 0 {
return errors.BadRequest("otp.generate", "missing id")
}
// check if a key exists for the user
var secret string
okey := new(otpKey)
if err := cache.Context(ctx).Get(req.Id, &secret); err != nil {
if req.Expiry <= 0 {
req.Expiry = 60
}
if req.Size <= 0 {
req.Size = 6
}
if err := cache.Context(ctx).Get("otp:"+req.Id, &okey); err != nil || okey == nil {
// generate a key
key, err := totp.Generate(totp.GenerateOpts{
Issuer: "Micro",
AccountName: req.Id,
Period: 60,
Period: 300,
Algorithm: otp.AlgorithmSHA1,
})
if err != nil {
@@ -36,19 +49,24 @@ func (e *Otp) Generate(ctx context.Context, req *pb.GenerateRequest, rsp *pb.Gen
return errors.InternalServerError("otp.generate", "failed to generate code")
}
secret = key.Secret()
okey = &otpKey{
Secret: key.Secret(),
Expiry: uint(req.Expiry),
}
if err := cache.Context(ctx).Set(req.Id, secret, time.Now().Add(time.Minute*5)); err != nil {
if err := cache.Context(ctx).Set("otp:"+req.Id, okey, time.Now().Add(time.Minute*5)); err != nil {
logger.Error("Failed to store secret: %v", err)
return errors.InternalServerError("otp.generate", "failed to generate code")
}
}
logger.Info("generating the code: ", okey.Secret, " ", okey.Expiry)
// generate a new code
code, err := totp.GenerateCodeCustom(secret, time.Now(), totp.ValidateOpts{
Period: 60,
code, err := totp.GenerateCodeCustom(okey.Secret, time.Now(), totp.ValidateOpts{
Period: uint(req.Expiry),
Skew: 1,
Digits: otp.DigitsSix,
Digits: otp.Digits(req.Size),
Algorithm: otp.AlgorithmSHA1,
})
@@ -56,6 +74,16 @@ func (e *Otp) Generate(ctx context.Context, req *pb.GenerateRequest, rsp *pb.Gen
return errors.InternalServerError("otp.generate", "failed to generate code: %v", err)
}
// we have to replaced the cached value if the expiry is different
if v := uint(req.Expiry); v != okey.Expiry {
okey.Expiry = v
if err := cache.Context(ctx).Set("otp:"+req.Id, okey, time.Now().Add(time.Minute*5)); err != nil {
logger.Error("Failed to store secret: %v", err)
return errors.InternalServerError("otp.generate", "failed to generate code")
}
}
// return the code
rsp.Code = code
@@ -70,17 +98,18 @@ func (e *Otp) Validate(ctx context.Context, req *pb.ValidateRequest, rsp *pb.Val
return errors.BadRequest("otp.generate", "missing code")
}
var secret string
key := new(otpKey)
if err := cache.Context(ctx).Get(req.Id, &secret); err != nil {
if err := cache.Context(ctx).Get("otp:"+req.Id, &key); err != nil {
logger.Error("Failed to get secret from store: %v", err)
return errors.InternalServerError("otp.generate", "failed to validate code")
}
ok, err := totp.ValidateCustom(req.Code, secret, time.Now(), totp.ValidateOpts{
Period: 60,
logger.Info("validating the code: ", key.Secret, " ", key.Expiry)
ok, err := totp.ValidateCustom(req.Code, key.Secret, time.Now(), totp.ValidateOpts{
Period: key.Expiry,
Skew: 1,
Digits: otp.DigitsSix,
Digits: otp.Digits(len(req.Code)),
Algorithm: otp.AlgorithmSHA1,
})
if err != nil {