feat:
* added totp methods in db's providers * adding totp in login method
This commit is contained in:
parent
d9bfb74c98
commit
3f5283bf7f
|
@ -160,6 +160,9 @@ const (
|
|||
// EnvKeyDisableMultiFactorAuthentication is key for env variable DISABLE_MULTI_FACTOR_AUTHENTICATION
|
||||
// this variable is used to completely disable multi factor authentication. It will have no effect on profile preference
|
||||
EnvKeyDisableMultiFactorAuthentication = "DISABLE_MULTI_FACTOR_AUTHENTICATION"
|
||||
// EnvKeyDisableTotpAuthentication is key for env variable DISABLE_TOTP_AUTHENTICATION
|
||||
// this variable is used to completely disable totp verification
|
||||
EnvKeyDisableTotpAuthentication = "DISABLE_TOTP_AUTHENTICATION"
|
||||
// EnvKeyDisablePhoneVerification is key for env variable DISABLE_PHONE_VERIFICATION
|
||||
// this variable is used to disable phone verification
|
||||
EnvKeyDisablePhoneVerification = "DISABLE_PHONE_VERIFICATION"
|
||||
|
|
|
@ -34,6 +34,7 @@ type User struct {
|
|||
UpdatedAt int64 `json:"updated_at" bson:"updated_at" cql:"updated_at" dynamo:"updated_at"`
|
||||
CreatedAt int64 `json:"created_at" bson:"created_at" cql:"created_at" dynamo:"created_at"`
|
||||
AppData *string `json:"app_data" bson:"app_data" cql:"app_data" dynamo:"app_data"`
|
||||
TotpSecret *string `json:"totp_secret" bson:"totp_secret" cql:"totp_secret" dynamo:"totp_secret"`
|
||||
}
|
||||
|
||||
func (user *User) AsAPIUser() *model.User {
|
||||
|
|
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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ require (
|
|||
github.com/joho/godotenv v1.3.0
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/redis/go-redis/v9 v9.0.3
|
||||
github.com/robertkrimen/otto v0.0.0-20211024170158-b87d35c0b86f
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
|
|
|
@ -58,6 +58,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYE
|
|||
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
|
||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
|
||||
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
|
||||
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
|
||||
|
@ -285,6 +287,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k=
|
||||
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
|
||||
|
|
|
@ -52,6 +52,7 @@ type ComplexityRoot struct {
|
|||
RefreshToken func(childComplexity int) int
|
||||
ShouldShowEmailOtpScreen func(childComplexity int) int
|
||||
ShouldShowMobileOtpScreen func(childComplexity int) int
|
||||
TotpBase64url func(childComplexity int) int
|
||||
User func(childComplexity int) int
|
||||
}
|
||||
|
||||
|
@ -446,6 +447,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
|||
|
||||
return e.complexity.AuthResponse.ShouldShowMobileOtpScreen(childComplexity), true
|
||||
|
||||
case "AuthResponse.totpBase64URL":
|
||||
if e.complexity.AuthResponse.TotpBase64url == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.AuthResponse.TotpBase64url(childComplexity), true
|
||||
|
||||
case "AuthResponse.user":
|
||||
if e.complexity.AuthResponse.User == nil {
|
||||
break
|
||||
|
@ -2301,6 +2309,7 @@ type AuthResponse {
|
|||
refresh_token: String
|
||||
expires_in: Int64
|
||||
user: User
|
||||
totpBase64URL: String
|
||||
}
|
||||
|
||||
type Response {
|
||||
|
@ -3845,6 +3854,47 @@ func (ec *executionContext) fieldContext_AuthResponse_user(ctx context.Context,
|
|||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _AuthResponse_totpBase64URL(ctx context.Context, field graphql.CollectedField, obj *model.AuthResponse) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
if err != nil {
|
||||
return graphql.Null
|
||||
}
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.TotpBase64url, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*string)
|
||||
fc.Result = res
|
||||
return ec.marshalOString2ᚖstring(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) fieldContext_AuthResponse_totpBase64URL(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
|
||||
fc = &graphql.FieldContext{
|
||||
Object: "AuthResponse",
|
||||
Field: field,
|
||||
IsMethod: false,
|
||||
IsResolver: false,
|
||||
Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
|
||||
return nil, errors.New("field of type String does not have child fields")
|
||||
},
|
||||
}
|
||||
return fc, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) _EmailTemplate_id(ctx context.Context, field graphql.CollectedField, obj *model.EmailTemplate) (ret graphql.Marshaler) {
|
||||
fc, err := ec.fieldContext_EmailTemplate_id(ctx, field)
|
||||
if err != nil {
|
||||
|
@ -7901,6 +7951,8 @@ func (ec *executionContext) fieldContext_Mutation_signup(ctx context.Context, fi
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -7974,6 +8026,8 @@ func (ec *executionContext) fieldContext_Mutation_mobile_signup(ctx context.Cont
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -8047,6 +8101,8 @@ func (ec *executionContext) fieldContext_Mutation_login(ctx context.Context, fie
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -8120,6 +8176,8 @@ func (ec *executionContext) fieldContext_Mutation_mobile_login(ctx context.Conte
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -8359,6 +8417,8 @@ func (ec *executionContext) fieldContext_Mutation_verify_email(ctx context.Conte
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -8668,6 +8728,8 @@ func (ec *executionContext) fieldContext_Mutation_verify_otp(ctx context.Context
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -10090,6 +10152,8 @@ func (ec *executionContext) fieldContext_Query_session(ctx context.Context, fiel
|
|||
return ec.fieldContext_AuthResponse_expires_in(ctx, field)
|
||||
case "user":
|
||||
return ec.fieldContext_AuthResponse_user(ctx, field)
|
||||
case "totpBase64URL":
|
||||
return ec.fieldContext_AuthResponse_totpBase64URL(ctx, field)
|
||||
}
|
||||
return nil, fmt.Errorf("no field named %q was found under type AuthResponse", field.Name)
|
||||
},
|
||||
|
@ -18150,6 +18214,10 @@ func (ec *executionContext) _AuthResponse(ctx context.Context, sel ast.Selection
|
|||
|
||||
out.Values[i] = ec._AuthResponse_user(ctx, field, obj)
|
||||
|
||||
case "totpBase64URL":
|
||||
|
||||
out.Values[i] = ec._AuthResponse_totpBase64URL(ctx, field, obj)
|
||||
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ type AuthResponse struct {
|
|||
RefreshToken *string `json:"refresh_token"`
|
||||
ExpiresIn *int64 `json:"expires_in"`
|
||||
User *User `json:"user"`
|
||||
TotpBase64url *string `json:"totpBase64URL"`
|
||||
}
|
||||
|
||||
type DeleteEmailTemplateRequest struct {
|
||||
|
|
|
@ -99,6 +99,7 @@ type AuthResponse {
|
|||
refresh_token: String
|
||||
expires_in: Int64
|
||||
user: User
|
||||
totpBase64URL: String
|
||||
}
|
||||
|
||||
type Response {
|
||||
|
|
|
@ -150,6 +150,16 @@ func LoginResolver(ctx context.Context, params model.LoginInput) (*model.AuthRes
|
|||
}, nil
|
||||
}
|
||||
|
||||
if !isMFADisabled && refs.BoolValue(user.IsMultiFactorAuthEnabled) {
|
||||
if user.TotpSecret == nil {
|
||||
base64URL, err := db.Provider.GenerateTotp(ctx, user.ID)
|
||||
if err != nil {
|
||||
log.Debug("error while generating base64 url: ", err)
|
||||
}
|
||||
res.TotpBase64url = base64URL
|
||||
}
|
||||
}
|
||||
|
||||
code := ""
|
||||
codeChallenge := ""
|
||||
nonce := ""
|
||||
|
|
Loading…
Reference in New Issue
Block a user