package sql import ( "bytes" "context" "crypto/rand" "crypto/rsa" "fmt" log "github.com/sirupsen/logrus" "image/png" "time" "github.com/pquerna/otp/totp" "github.com/authorizerdev/authorizer/server/crypto" ) func (p *provider) GenerateTotp(ctx context.Context, id string) (*string, error) { var buf bytes.Buffer //get user details user, err := p.GetUserByID(ctx, id) if err != nil { return nil, fmt.Errorf("error while getting user details") } // generate totp, TOTP hash is valid for 30 seconds key, err := totp.Generate(totp.GenerateOpts{ Issuer: "authorizer", AccountName: user.Email, }) if err != nil { return nil, fmt.Errorf("error while genrating totp") } // get secret for user secret := key.Secret() //generating image for key and encoding to base64 for displaying in frontend img, err := key.Image(200, 200) if err != nil { return nil, fmt.Errorf("error while creating qr image for totp") } png.Encode(&buf, img) encodedText := crypto.EncryptB64(buf.String()) // update user totp secret in db user.UpdatedAt = time.Now().Unix() user.TotpSecret = &secret _, err = p.UpdateUser(ctx, user) if err != nil { return nil, fmt.Errorf("error while updating user's totp secret") } log.Info("\n\n\n", &encodedText) return &encodedText, nil } func (p *provider) ValidatePasscode(ctx context.Context, passcode string, id string) (bool, error) { // get user details user, err := p.GetUserByID(ctx, id) if err != nil { return false, fmt.Errorf("error while getting user details") } // validate passcode inputted by user status := totp.Validate(passcode, *user.TotpSecret) return status, nil } func (p *provider) GenerateKeysTOTP() (*rsa.PublicKey, error) { privateKey, err := rsa.GenerateKey(rand.Reader, 1024) if err != nil { return nil, err } publicKey := privateKey.PublicKey return &publicKey, nil }