feat:
* added totp methods in db's providers * adding totp in login method
This commit is contained in:
68
server/db/providers/arangodb/totp.go
Normal file
68
server/db/providers/arangodb/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package arangodb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
68
server/db/providers/cassandradb/totp.go
Normal file
68
server/db/providers/cassandradb/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package cassandradb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
68
server/db/providers/couchbase/totp.go
Normal file
68
server/db/providers/couchbase/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package couchbase
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
68
server/db/providers/dynamodb/totp.go
Normal file
68
server/db/providers/dynamodb/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package dynamodb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
68
server/db/providers/mongodb/totp.go
Normal file
68
server/db/providers/mongodb/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package mongodb
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
68
server/db/providers/provider_template/totp.go
Normal file
68
server/db/providers/provider_template/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package provider_template
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,7 +2,6 @@ package providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/authorizerdev/authorizer/server/db/models"
|
||||
"github.com/authorizerdev/authorizer/server/graph/model"
|
||||
)
|
||||
@@ -88,4 +87,9 @@ type Provider interface {
|
||||
GetOTPByPhoneNumber(ctx context.Context, phoneNumber string) (*models.OTP, error)
|
||||
// DeleteOTP to delete otp
|
||||
DeleteOTP(ctx context.Context, otp *models.OTP) error
|
||||
|
||||
// GenerateTotp to generate totp, store secret into db and returns base64 of QR code image
|
||||
GenerateTotp(ctx context.Context, id string) (*string, error)
|
||||
// ValidatePasscode validate user passcode with secret stored in our db
|
||||
ValidatePasscode(ctx context.Context, passcode string, id string) (bool, error)
|
||||
}
|
||||
|
68
server/db/providers/sql/totp.go
Normal file
68
server/db/providers/sql/totp.go
Normal file
@@ -0,0 +1,68 @@
|
||||
package sql
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"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")
|
||||
}
|
||||
|
||||
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
|
||||
for {
|
||||
status := totp.Validate(passcode, *user.TotpSecret)
|
||||
if status {
|
||||
return status, nil
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user