feat: add mfa session to secure otp login

This commit is contained in:
catusax
2023-07-20 15:11:39 +08:00
parent 87a962504f
commit 5018462559
9 changed files with 185 additions and 9 deletions

View File

@@ -7,18 +7,20 @@ import (
)
type provider struct {
mutex sync.Mutex
sessionStore *stores.SessionStore
stateStore *stores.StateStore
envStore *stores.EnvStore
mutex sync.Mutex
sessionStore *stores.SessionStore
mfasessionStore *stores.SessionStore
stateStore *stores.StateStore
envStore *stores.EnvStore
}
// NewInMemoryStore returns a new in-memory store.
func NewInMemoryProvider() (*provider, error) {
return &provider{
mutex: sync.Mutex{},
envStore: stores.NewEnvStore(),
sessionStore: stores.NewSessionStore(),
stateStore: stores.NewStateStore(),
mutex: sync.Mutex{},
envStore: stores.NewEnvStore(),
sessionStore: stores.NewSessionStore(),
mfasessionStore: stores.NewSessionStore(),
stateStore: stores.NewStateStore(),
}, nil
}

View File

@@ -42,6 +42,24 @@ func (c *provider) DeleteSessionForNamespace(namespace string) error {
return nil
}
func (c *provider) SetMfaSession(email, key string, expiration int64) error {
c.mfasessionStore.Set(email, key, email, expiration)
return nil
}
func (c *provider) GetMfaSession(email, key string) (string, error) {
val := c.mfasessionStore.Get(email, key)
if val == "" {
return "", fmt.Errorf("Not found")
}
return val, nil
}
func (c *provider) DeleteMfaSession(email, key string) error {
c.mfasessionStore.Remove(email, key)
return nil
}
// SetState sets the state in the in-memory store.
func (c *provider) SetState(key, state string) error {
if os.Getenv("ENV") != constants.TestEnv {

View File

@@ -112,4 +112,15 @@ func ProviderTests(t *testing.T, p Provider) {
key, err = p.GetUserSession("auth_provider1:124", "access_token_key")
assert.Empty(t, key)
assert.Error(t, err)
err = p.SetMfaSession("auth_provider:123", "session123", time.Now().Add(60*time.Second).Unix())
assert.NoError(t, err)
key, err = p.GetMfaSession("auth_provider:123", "session123")
assert.NoError(t, err)
assert.Equal(t, "auth_provider:123", key)
err = p.DeleteMfaSession("auth_provider:123", "session123")
assert.NoError(t, err)
key, err = p.GetMfaSession("auth_provider:123", "session123")
assert.Error(t, err)
assert.Empty(t, key)
}

View File

@@ -13,6 +13,10 @@ type Provider interface {
// DeleteSessionForNamespace deletes the session for a given namespace
DeleteSessionForNamespace(namespace string) error
SetMfaSession(email, key string, expiration int64) error
GetMfaSession(email, key string) (string, error)
DeleteMfaSession(email, key string) error
// SetState sets the login state (key, value form) in the session store
SetState(key, state string) error
// GetState returns the state from the session store

View File

@@ -16,6 +16,8 @@ var (
envStorePrefix = "authorizer_env"
)
const mfaSessionPrefix = "mfa_sess_"
// SetUserSession sets the user session for given user identifier in form recipe:user_id
func (c *provider) SetUserSession(userId, key, token string, expiration int64) error {
currentTime := time.Now()
@@ -91,6 +93,34 @@ func (c *provider) DeleteSessionForNamespace(namespace string) error {
return nil
}
func (c *provider) SetMfaSession(email, key string, expiration int64) error {
currentTime := time.Now()
expireTime := time.Unix(expiration, 0)
duration := expireTime.Sub(currentTime)
err := c.store.Set(c.ctx, fmt.Sprintf("%s%s:%s", mfaSessionPrefix, email, key), email, duration).Err()
if err != nil {
log.Debug("Error saving user session to redis: ", err)
return err
}
return nil
}
func (c *provider) GetMfaSession(email, key string) (string, error) {
data, err := c.store.Get(c.ctx, fmt.Sprintf("%s%s:%s", mfaSessionPrefix, email, key)).Result()
if err != nil {
return "", err
}
return data, nil
}
func (c *provider) DeleteMfaSession(email, key string) error {
if err := c.store.Del(c.ctx, fmt.Sprintf("%s%s:%s", mfaSessionPrefix, email, key)).Err(); err != nil {
log.Debug("Error deleting user session from redis: ", err)
// continue
}
return nil
}
// SetState sets the state in redis store.
func (c *provider) SetState(key, value string) error {
err := c.store.Set(c.ctx, stateStorePrefix+key, value, 0).Err()