|
|
|
@@ -3,6 +3,8 @@ package eventstore
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"encoding/json"
|
|
|
|
|
iam_model "github.com/caos/zitadel/internal/iam/model"
|
|
|
|
|
iam_view_model "github.com/caos/zitadel/internal/iam/repository/view/model"
|
|
|
|
|
"testing"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
@@ -46,7 +48,7 @@ func (m *mockViewErrUserSession) UserSessionsByAgentID(string) ([]*user_view_mod
|
|
|
|
|
type mockViewUserSession struct {
|
|
|
|
|
ExternalLoginVerification time.Time
|
|
|
|
|
PasswordVerification time.Time
|
|
|
|
|
MfaSoftwareVerification time.Time
|
|
|
|
|
SecondFactorVerification time.Time
|
|
|
|
|
Users []mockUser
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -59,7 +61,7 @@ func (m *mockViewUserSession) UserSessionByIDs(string, string) (*user_view_model
|
|
|
|
|
return &user_view_model.UserSessionView{
|
|
|
|
|
ExternalLoginVerification: m.ExternalLoginVerification,
|
|
|
|
|
PasswordVerification: m.PasswordVerification,
|
|
|
|
|
MfaSoftwareVerification: m.MfaSoftwareVerification,
|
|
|
|
|
SecondFactorVerification: m.SecondFactorVerification,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -116,6 +118,14 @@ type mockViewUser struct {
|
|
|
|
|
MfaInitSkipped time.Time
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type mockLoginPolicy struct {
|
|
|
|
|
policy *iam_view_model.LoginPolicyView
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *mockLoginPolicy) LoginPolicyByAggregateID(id string) (*iam_view_model.LoginPolicyView, error) {
|
|
|
|
|
return m.policy, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *mockViewUser) UserByID(string) (*user_view_model.UserView, error) {
|
|
|
|
|
return &user_view_model.UserView{
|
|
|
|
|
State: int32(user_model.UserStateActive),
|
|
|
|
@@ -186,11 +196,12 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
userEventProvider userEventProvider
|
|
|
|
|
orgViewProvider orgViewProvider
|
|
|
|
|
userGrantProvider userGrantProvider
|
|
|
|
|
loginPolicyProvider loginPolicyViewProvider
|
|
|
|
|
PasswordCheckLifeTime time.Duration
|
|
|
|
|
ExternalLoginCheckLifeTime time.Duration
|
|
|
|
|
MfaInitSkippedLifeTime time.Duration
|
|
|
|
|
MfaSoftwareCheckLifeTime time.Duration
|
|
|
|
|
MfaHardwareCheckLifeTime time.Duration
|
|
|
|
|
SecondFactorCheckLifeTime time.Duration
|
|
|
|
|
MultiFactorCheckLifeTime time.Duration
|
|
|
|
|
}
|
|
|
|
|
type args struct {
|
|
|
|
|
request *model.AuthRequest
|
|
|
|
@@ -417,15 +428,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"external user (no external verification), external login step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
|
|
|
|
|
[]model.NextStep{&model.ExternalLoginStep{}},
|
|
|
|
@@ -436,19 +447,29 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
ExternalLoginVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
loginPolicyProvider: &mockLoginPolicy{
|
|
|
|
|
policy: &iam_view_model.LoginPolicyView{},
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID", Request: &model.AuthRequestOIDC{}}, false},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
SelectedIDPConfigID: "IDPConfigID",
|
|
|
|
|
Request: &model.AuthRequestOIDC{},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{},
|
|
|
|
|
},
|
|
|
|
|
false},
|
|
|
|
|
[]model.NextStep{&model.RedirectToCallbackStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -471,21 +492,27 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"external user (no password check needed), callback",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
ExternalLoginVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID", Request: &model.AuthRequestOIDC{}}, false},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
SelectedIDPConfigID: "IDPConfigID",
|
|
|
|
|
Request: &model.AuthRequestOIDC{},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.RedirectToCallbackStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -498,16 +525,22 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
OTPState: int32(user_model.MfaStateReady),
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID"}, false},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.MfaVerificationStep{
|
|
|
|
|
MfaProviders: []model.MfaType{model.MfaTypeOTP},
|
|
|
|
|
MfaProviders: []model.MFAType{model.MFATypeOTP},
|
|
|
|
|
}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -521,17 +554,24 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
OTPState: int32(user_model.MfaStateReady),
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
SelectedIDPConfigID: "IDPConfigID",
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.MfaVerificationStep{
|
|
|
|
|
MfaProviders: []model.MfaType{model.MfaTypeOTP},
|
|
|
|
|
MfaProviders: []model.MFAType{model.MFATypeOTP},
|
|
|
|
|
}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -539,21 +579,27 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"password change required and email verified, password change step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
PasswordChangeRequired: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID"}, false},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.ChangePasswordStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -561,19 +607,24 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"email not verified and no password change required, mail verification step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID"}, false},
|
|
|
|
|
args{&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.VerifyEMailStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -581,20 +632,25 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"email not verified and password change required, mail verification step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
PasswordChangeRequired: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID"}, false},
|
|
|
|
|
args{&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.ChangePasswordStep{}, &model.VerifyEMailStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -602,21 +658,27 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"email verified and no password change required, redirect to callback step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", Request: &model.AuthRequestOIDC{}}, false},
|
|
|
|
|
args{&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
Request: &model.AuthRequestOIDC{},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.RedirectToCallbackStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -624,21 +686,28 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"prompt none, checkLoggedIn true and authenticated, redirect to callback step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
userGrantProvider: &mockUserGrants{},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone, Request: &model.AuthRequestOIDC{}}, true},
|
|
|
|
|
args{&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
Prompt: model.PromptNone,
|
|
|
|
|
Request: &model.AuthRequestOIDC{},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, true},
|
|
|
|
|
[]model.NextStep{&model.RedirectToCallbackStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -646,13 +715,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"prompt none, checkLoggedIn true, authenticated and required user grants missing, grant required step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
@@ -660,10 +729,17 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
roleCheck: true,
|
|
|
|
|
userGrants: 0,
|
|
|
|
|
},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone, Request: &model.AuthRequestOIDC{}}, true},
|
|
|
|
|
args{&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
Prompt: model.PromptNone,
|
|
|
|
|
Request: &model.AuthRequestOIDC{},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, true},
|
|
|
|
|
[]model.NextStep{&model.GrantRequiredStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -671,13 +747,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"prompt none, checkLoggedIn true, authenticated and required user grants exist, redirect to callback step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
@@ -685,10 +761,17 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
roleCheck: true,
|
|
|
|
|
userGrants: 2,
|
|
|
|
|
},
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&model.AuthRequest{UserID: "UserID", Prompt: model.PromptNone, Request: &model.AuthRequestOIDC{}}, true},
|
|
|
|
|
args{&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
Prompt: model.PromptNone,
|
|
|
|
|
Request: &model.AuthRequestOIDC{},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, true},
|
|
|
|
|
[]model.NextStep{&model.RedirectToCallbackStep{}},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -696,16 +779,16 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"linking users, password step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
@@ -720,24 +803,27 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
"linking users, linking step",
|
|
|
|
|
fields{
|
|
|
|
|
userSessionViewProvider: &mockViewUserSession{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Add(-5 * time.Minute),
|
|
|
|
|
},
|
|
|
|
|
userViewProvider: &mockViewUser{
|
|
|
|
|
PasswordSet: true,
|
|
|
|
|
IsEmailVerified: true,
|
|
|
|
|
MfaMaxSetUp: int32(model.MfaLevelSoftware),
|
|
|
|
|
MfaMaxSetUp: int32(model.MFALevelSecondFactor),
|
|
|
|
|
},
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
userEventProvider: &mockEventUser{},
|
|
|
|
|
orgViewProvider: &mockViewOrg{State: org_model.OrgStateActive},
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
&model.AuthRequest{
|
|
|
|
|
UserID: "UserID",
|
|
|
|
|
SelectedIDPConfigID: "IDPConfigID",
|
|
|
|
|
LinkingUsers: []*model.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
}, false},
|
|
|
|
|
[]model.NextStep{&model.LinkUsersStep{}},
|
|
|
|
|
nil,
|
|
|
|
@@ -754,11 +840,12 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
UserEventProvider: tt.fields.userEventProvider,
|
|
|
|
|
OrgViewProvider: tt.fields.orgViewProvider,
|
|
|
|
|
UserGrantProvider: tt.fields.userGrantProvider,
|
|
|
|
|
LoginPolicyViewProvider: tt.fields.loginPolicyProvider,
|
|
|
|
|
PasswordCheckLifeTime: tt.fields.PasswordCheckLifeTime,
|
|
|
|
|
ExternalLoginCheckLifeTime: tt.fields.ExternalLoginCheckLifeTime,
|
|
|
|
|
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
|
|
|
|
|
MfaSoftwareCheckLifeTime: tt.fields.MfaSoftwareCheckLifeTime,
|
|
|
|
|
MfaHardwareCheckLifeTime: tt.fields.MfaHardwareCheckLifeTime,
|
|
|
|
|
SecondFactorCheckLifeTime: tt.fields.SecondFactorCheckLifeTime,
|
|
|
|
|
MultiFactorCheckLifeTime: tt.fields.MultiFactorCheckLifeTime,
|
|
|
|
|
}
|
|
|
|
|
got, err := repo.nextSteps(context.Background(), tt.args.request, tt.args.checkLoggedIn)
|
|
|
|
|
if (err != nil && tt.wantErr == nil) || (tt.wantErr != nil && !tt.wantErr(err)) {
|
|
|
|
@@ -772,14 +859,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
|
|
|
|
|
|
|
|
|
func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
|
|
|
|
type fields struct {
|
|
|
|
|
MfaInitSkippedLifeTime time.Duration
|
|
|
|
|
MfaSoftwareCheckLifeTime time.Duration
|
|
|
|
|
MfaHardwareCheckLifeTime time.Duration
|
|
|
|
|
MfaInitSkippedLifeTime time.Duration
|
|
|
|
|
SecondFactorCheckLifeTime time.Duration
|
|
|
|
|
MultiFactorCheckLifeTime time.Duration
|
|
|
|
|
}
|
|
|
|
|
type args struct {
|
|
|
|
|
userSession *user_model.UserSessionView
|
|
|
|
|
request *model.AuthRequest
|
|
|
|
|
user *user_model.UserView
|
|
|
|
|
policy *iam_model.LoginPolicyView
|
|
|
|
|
}
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
@@ -787,6 +875,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
|
|
|
|
args args
|
|
|
|
|
want model.NextStep
|
|
|
|
|
wantChecked bool
|
|
|
|
|
errFunc func(err error) bool
|
|
|
|
|
}{
|
|
|
|
|
//{
|
|
|
|
|
// "required, prompt and false", //TODO: enable when LevelsOfAssurance is checked
|
|
|
|
@@ -799,25 +888,78 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
|
|
|
|
// },
|
|
|
|
|
// false,
|
|
|
|
|
//},
|
|
|
|
|
{
|
|
|
|
|
"not set up, forced by policy, no mfas configured, error",
|
|
|
|
|
fields{
|
|
|
|
|
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
request: &model.AuthRequest{
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
ForceMFA: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
user: &user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MFALevelNotSetUp,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
false,
|
|
|
|
|
errors.IsPreconditionFailed,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"not set up, prompt and false",
|
|
|
|
|
fields{
|
|
|
|
|
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
request: &model.AuthRequest{},
|
|
|
|
|
request: &model.AuthRequest{
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
user: &user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MfaLevelNotSetUp,
|
|
|
|
|
MfaMaxSetUp: model.MFALevelNotSetUp,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
&model.MfaPromptStep{
|
|
|
|
|
MfaProviders: []model.MfaType{
|
|
|
|
|
model.MfaTypeOTP,
|
|
|
|
|
MfaProviders: []model.MFAType{
|
|
|
|
|
model.MFATypeOTP,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"not set up, forced by org, true",
|
|
|
|
|
fields{
|
|
|
|
|
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
request: &model.AuthRequest{
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
ForceMFA: true,
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
user: &user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MFALevelNotSetUp,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
&model.MfaPromptStep{
|
|
|
|
|
Required: true,
|
|
|
|
|
MfaProviders: []model.MFAType{
|
|
|
|
|
model.MFATypeOTP,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"not set up and skipped, true",
|
|
|
|
@@ -825,45 +967,55 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
|
|
|
|
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
request: &model.AuthRequest{},
|
|
|
|
|
request: &model.AuthRequest{
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{},
|
|
|
|
|
},
|
|
|
|
|
user: &user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MfaLevelNotSetUp,
|
|
|
|
|
MfaMaxSetUp: model.MFALevelNotSetUp,
|
|
|
|
|
MfaInitSkipped: time.Now().UTC(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
true,
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"checked mfa software, true",
|
|
|
|
|
"checked second factor, true",
|
|
|
|
|
fields{
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
request: &model.AuthRequest{},
|
|
|
|
|
request: &model.AuthRequest{
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{},
|
|
|
|
|
},
|
|
|
|
|
user: &user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MfaLevelSoftware,
|
|
|
|
|
MfaMaxSetUp: model.MFALevelSecondFactor,
|
|
|
|
|
OTPState: user_model.MfaStateReady,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
userSession: &user_model.UserSessionView{MfaSoftwareVerification: time.Now().UTC().Add(-5 * time.Hour)},
|
|
|
|
|
userSession: &user_model.UserSessionView{SecondFactorVerification: time.Now().UTC().Add(-5 * time.Hour)},
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
true,
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"not checked, check and false",
|
|
|
|
|
fields{
|
|
|
|
|
MfaSoftwareCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
SecondFactorCheckLifeTime: 18 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{
|
|
|
|
|
request: &model.AuthRequest{},
|
|
|
|
|
request: &model.AuthRequest{
|
|
|
|
|
LoginPolicy: &iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
user: &user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MfaLevelSoftware,
|
|
|
|
|
MfaMaxSetUp: model.MFALevelSecondFactor,
|
|
|
|
|
OTPState: user_model.MfaStateReady,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
@@ -871,19 +1023,24 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
&model.MfaVerificationStep{
|
|
|
|
|
MfaProviders: []model.MfaType{model.MfaTypeOTP},
|
|
|
|
|
MfaProviders: []model.MFAType{model.MFATypeOTP},
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
repo := &AuthRequestRepo{
|
|
|
|
|
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
|
|
|
|
|
MfaSoftwareCheckLifeTime: tt.fields.MfaSoftwareCheckLifeTime,
|
|
|
|
|
MfaHardwareCheckLifeTime: tt.fields.MfaHardwareCheckLifeTime,
|
|
|
|
|
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
|
|
|
|
|
SecondFactorCheckLifeTime: tt.fields.SecondFactorCheckLifeTime,
|
|
|
|
|
MultiFactorCheckLifeTime: tt.fields.MultiFactorCheckLifeTime,
|
|
|
|
|
}
|
|
|
|
|
got, ok, err := repo.mfaChecked(tt.args.userSession, tt.args.request, tt.args.user)
|
|
|
|
|
if (tt.errFunc != nil && !tt.errFunc(err)) || (err != nil && tt.errFunc == nil) {
|
|
|
|
|
t.Errorf("got wrong err: %v ", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
got, ok := repo.mfaChecked(tt.args.userSession, tt.args.request, tt.args.user)
|
|
|
|
|
if ok != tt.wantChecked {
|
|
|
|
|
t.Errorf("mfaChecked() checked = %v, want %v", ok, tt.wantChecked)
|
|
|
|
|
}
|
|
|
|
@@ -897,7 +1054,8 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
|
|
|
|
MfaInitSkippedLifeTime time.Duration
|
|
|
|
|
}
|
|
|
|
|
type args struct {
|
|
|
|
|
user *user_model.UserView
|
|
|
|
|
user *user_model.UserView
|
|
|
|
|
policy *iam_model.LoginPolicyView
|
|
|
|
|
}
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
@@ -908,11 +1066,16 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
|
|
|
|
{
|
|
|
|
|
"mfa set up, true",
|
|
|
|
|
fields{},
|
|
|
|
|
args{&user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MfaLevelSoftware,
|
|
|
|
|
args{
|
|
|
|
|
&user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: model.MFALevelSecondFactor,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}},
|
|
|
|
|
&iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@@ -920,12 +1083,17 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
|
|
|
|
fields{
|
|
|
|
|
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: -1,
|
|
|
|
|
MfaInitSkipped: time.Now().UTC().Add(-10 * time.Hour),
|
|
|
|
|
args{
|
|
|
|
|
&user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: -1,
|
|
|
|
|
MfaInitSkipped: time.Now().UTC().Add(-10 * time.Hour),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}},
|
|
|
|
|
&iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
@@ -933,12 +1101,17 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
|
|
|
|
fields{
|
|
|
|
|
MfaInitSkippedLifeTime: 30 * 24 * time.Hour,
|
|
|
|
|
},
|
|
|
|
|
args{&user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: -1,
|
|
|
|
|
MfaInitSkipped: time.Now().UTC().Add(-40 * 24 * time.Hour),
|
|
|
|
|
args{
|
|
|
|
|
&user_model.UserView{
|
|
|
|
|
HumanView: &user_model.HumanView{
|
|
|
|
|
MfaMaxSetUp: -1,
|
|
|
|
|
MfaInitSkipped: time.Now().UTC().Add(-40 * 24 * time.Hour),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}},
|
|
|
|
|
&iam_model.LoginPolicyView{
|
|
|
|
|
SecondFactors: []iam_model.SecondFactorType{iam_model.SecondFactorTypeOTP},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
@@ -947,7 +1120,7 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
|
|
|
|
repo := &AuthRequestRepo{
|
|
|
|
|
MfaInitSkippedLifeTime: tt.fields.MfaInitSkippedLifeTime,
|
|
|
|
|
}
|
|
|
|
|
if got := repo.mfaSkippedOrSetUp(tt.args.user); got != tt.want {
|
|
|
|
|
if got := repo.mfaSkippedOrSetUp(tt.args.user, tt.args.policy); got != tt.want {
|
|
|
|
|
t.Errorf("mfaSkippedOrSetUp() = %v, want %v", got, tt.want)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
@@ -996,9 +1169,9 @@ func Test_userSessionByIDs(t *testing.T) {
|
|
|
|
|
eventProvider: &mockEventErrUser{},
|
|
|
|
|
},
|
|
|
|
|
&user_model.UserSessionView{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
MfaSoftwareVerification: time.Time{},
|
|
|
|
|
MfaHardwareVerification: time.Time{},
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
SecondFactorVerification: time.Time{},
|
|
|
|
|
MultiFactorVerification: time.Time{},
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -1019,9 +1192,9 @@ func Test_userSessionByIDs(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
&user_model.UserSessionView{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
MfaSoftwareVerification: time.Time{},
|
|
|
|
|
MfaHardwareVerification: time.Time{},
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
SecondFactorVerification: time.Time{},
|
|
|
|
|
MultiFactorVerification: time.Time{},
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -1046,9 +1219,9 @@ func Test_userSessionByIDs(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
&user_model.UserSessionView{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
MfaSoftwareVerification: time.Time{},
|
|
|
|
|
MfaHardwareVerification: time.Time{},
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
SecondFactorVerification: time.Time{},
|
|
|
|
|
MultiFactorVerification: time.Time{},
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
@@ -1073,9 +1246,9 @@ func Test_userSessionByIDs(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
&user_model.UserSessionView{
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
MfaSoftwareVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
ChangeDate: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
PasswordVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
SecondFactorVerification: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
ChangeDate: time.Now().UTC().Round(1 * time.Second),
|
|
|
|
|
},
|
|
|
|
|
nil,
|
|
|
|
|
},
|
|
|
|
|