mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 04:57:33 +00:00
feat: Login verification lifetimes (#3190)
* feat: add login check lifetimes to login policy * feat: org features test * feat: read lifetimes from loginpolicy
This commit is contained in:
@@ -50,12 +50,6 @@ type AuthRequestRepo struct {
|
||||
ApplicationProvider applicationProvider
|
||||
|
||||
IdGenerator id.Generator
|
||||
|
||||
PasswordCheckLifeTime time.Duration
|
||||
ExternalLoginCheckLifeTime time.Duration
|
||||
MFAInitSkippedLifeTime time.Duration
|
||||
SecondFactorCheckLifeTime time.Duration
|
||||
MultiFactorCheckLifeTime time.Duration
|
||||
}
|
||||
|
||||
type labelPolicyProvider interface {
|
||||
@@ -761,7 +755,7 @@ func (repo *AuthRequestRepo) nextSteps(ctx context.Context, request *domain.Auth
|
||||
}
|
||||
|
||||
isInternalLogin := request.SelectedIDPConfigID == "" && userSession.SelectedIDPConfigID == ""
|
||||
if !isInternalLogin && len(request.LinkingUsers) == 0 && !checkVerificationTimeMaxAge(userSession.ExternalLoginVerification, repo.ExternalLoginCheckLifeTime, request) {
|
||||
if !isInternalLogin && len(request.LinkingUsers) == 0 && !checkVerificationTimeMaxAge(userSession.ExternalLoginVerification, request.LoginPolicy.ExternalLoginCheckLifetime, request) {
|
||||
selectedIDPConfigID := request.SelectedIDPConfigID
|
||||
if selectedIDPConfigID == "" {
|
||||
selectedIDPConfigID = userSession.SelectedIDPConfigID
|
||||
@@ -858,7 +852,7 @@ func (repo *AuthRequestRepo) firstFactorChecked(request *domain.AuthRequest, use
|
||||
|
||||
var step domain.NextStep
|
||||
if request.LoginPolicy.PasswordlessType != domain.PasswordlessTypeNotAllowed && user.IsPasswordlessReady() {
|
||||
if checkVerificationTimeMaxAge(userSession.PasswordlessVerification, repo.MultiFactorCheckLifeTime, request) {
|
||||
if checkVerificationTimeMaxAge(userSession.PasswordlessVerification, request.LoginPolicy.MultiFactorCheckLifetime, request) {
|
||||
request.AuthTime = userSession.PasswordlessVerification
|
||||
return nil
|
||||
}
|
||||
@@ -875,7 +869,7 @@ func (repo *AuthRequestRepo) firstFactorChecked(request *domain.AuthRequest, use
|
||||
return &domain.InitPasswordStep{}
|
||||
}
|
||||
|
||||
if checkVerificationTimeMaxAge(userSession.PasswordVerification, repo.PasswordCheckLifeTime, request) {
|
||||
if checkVerificationTimeMaxAge(userSession.PasswordVerification, request.LoginPolicy.PasswordCheckLifetime, request) {
|
||||
request.PasswordVerified = true
|
||||
request.AuthTime = userSession.PasswordVerification
|
||||
return nil
|
||||
@@ -890,7 +884,7 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView,
|
||||
mfaLevel := request.MFALevel()
|
||||
allowedProviders, required := user.MFATypesAllowed(mfaLevel, request.LoginPolicy)
|
||||
promptRequired := (model.MFALevelToDomain(user.MFAMaxSetUp) < mfaLevel) || (len(allowedProviders) == 0 && required)
|
||||
if promptRequired || !repo.mfaSkippedOrSetUp(user) {
|
||||
if promptRequired || !repo.mfaSkippedOrSetUp(user, request) {
|
||||
types := user.MFATypesSetupPossible(mfaLevel, request.LoginPolicy)
|
||||
if promptRequired && len(types) == 0 {
|
||||
return nil, false, errors.ThrowPreconditionFailed(nil, "LOGIN-5Hm8s", "Errors.Login.LoginPolicy.MFA.ForceAndNotConfigured")
|
||||
@@ -912,14 +906,14 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView,
|
||||
}
|
||||
fallthrough
|
||||
case domain.MFALevelSecondFactor:
|
||||
if checkVerificationTimeMaxAge(userSession.SecondFactorVerification, repo.SecondFactorCheckLifeTime, request) {
|
||||
if checkVerificationTimeMaxAge(userSession.SecondFactorVerification, request.LoginPolicy.SecondFactorCheckLifetime, request) {
|
||||
request.MFAsVerified = append(request.MFAsVerified, model.MFATypeToDomain(userSession.SecondFactorVerificationType))
|
||||
request.AuthTime = userSession.SecondFactorVerification
|
||||
return nil, true, nil
|
||||
}
|
||||
fallthrough
|
||||
case domain.MFALevelMultiFactor:
|
||||
if checkVerificationTimeMaxAge(userSession.MultiFactorVerification, repo.MultiFactorCheckLifeTime, request) {
|
||||
if checkVerificationTimeMaxAge(userSession.MultiFactorVerification, request.LoginPolicy.MultiFactorCheckLifetime, request) {
|
||||
request.MFAsVerified = append(request.MFAsVerified, model.MFATypeToDomain(userSession.MultiFactorVerificationType))
|
||||
request.AuthTime = userSession.MultiFactorVerification
|
||||
return nil, true, nil
|
||||
@@ -930,11 +924,11 @@ func (repo *AuthRequestRepo) mfaChecked(userSession *user_model.UserSessionView,
|
||||
}, false, nil
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView) bool {
|
||||
func (repo *AuthRequestRepo) mfaSkippedOrSetUp(user *user_model.UserView, request *domain.AuthRequest) bool {
|
||||
if user.MFAMaxSetUp > model.MFALevelNotSetUp {
|
||||
return true
|
||||
}
|
||||
return checkVerificationTime(user.MFAInitSkipped, repo.MFAInitSkippedLifeTime)
|
||||
return checkVerificationTime(user.MFAInitSkipped, request.LoginPolicy.MFAInitSkipLifetime)
|
||||
}
|
||||
|
||||
func (repo *AuthRequestRepo) getPrivacyPolicy(ctx context.Context, orgID string) (*domain.PrivacyPolicy, error) {
|
||||
|
@@ -252,22 +252,17 @@ func (m *mockApp) AppByOIDCClientID(ctx context.Context, id string) (*query.App,
|
||||
|
||||
func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
type fields struct {
|
||||
AuthRequests *cache.AuthRequestCache
|
||||
View *view.View
|
||||
userSessionViewProvider userSessionViewProvider
|
||||
userViewProvider userViewProvider
|
||||
userEventProvider userEventProvider
|
||||
orgViewProvider orgViewProvider
|
||||
userGrantProvider userGrantProvider
|
||||
projectProvider projectProvider
|
||||
applicationProvider applicationProvider
|
||||
loginPolicyProvider loginPolicyViewProvider
|
||||
lockoutPolicyProvider lockoutPolicyViewProvider
|
||||
PasswordCheckLifeTime time.Duration
|
||||
ExternalLoginCheckLifeTime time.Duration
|
||||
MFAInitSkippedLifeTime time.Duration
|
||||
SecondFactorCheckLifeTime time.Duration
|
||||
MultiFactorCheckLifeTime time.Duration
|
||||
AuthRequests *cache.AuthRequestCache
|
||||
View *view.View
|
||||
userSessionViewProvider userSessionViewProvider
|
||||
userViewProvider userViewProvider
|
||||
userEventProvider userEventProvider
|
||||
orgViewProvider orgViewProvider
|
||||
userGrantProvider userGrantProvider
|
||||
projectProvider projectProvider
|
||||
applicationProvider applicationProvider
|
||||
loginPolicyProvider loginPolicyViewProvider
|
||||
lockoutPolicyProvider lockoutPolicyViewProvider
|
||||
}
|
||||
type args struct {
|
||||
request *domain.AuthRequest
|
||||
@@ -570,14 +565,18 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
userViewProvider: &mockViewUser{
|
||||
PasswordlessInitRequired: true,
|
||||
},
|
||||
userEventProvider: &mockEventUser{},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
MultiFactorCheckLifeTime: 10 * time.Hour,
|
||||
userEventProvider: &mockEventUser{},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
lockoutPolicyProvider: &mockLockoutPolicy{
|
||||
policy: &query.LockoutPolicy{
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{
|
||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
||||
[]domain.NextStep{&domain.PasswordlessRegistrationPromptStep{}},
|
||||
@@ -597,7 +596,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
MultiFactorCheckLifeTime: 10 * time.Hour,
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{
|
||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
||||
[]domain.NextStep{&domain.PasswordlessStep{}},
|
||||
@@ -618,7 +621,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
MultiFactorCheckLifeTime: 10 * time.Hour,
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{
|
||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{PasswordlessType: domain.PasswordlessTypeAllowed}}, false},
|
||||
[]domain.NextStep{&domain.PasswordlessStep{PasswordSet: true}},
|
||||
@@ -644,14 +651,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
MultiFactorCheckLifeTime: 10 * time.Hour,
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
MultiFactors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN},
|
||||
PasswordlessType: domain.PasswordlessTypeAllowed,
|
||||
MultiFactors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN},
|
||||
MultiFactorCheckLifetime: 10 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.VerifyEMailStep{}},
|
||||
@@ -692,10 +699,19 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
args{&domain.AuthRequest{UserID: "UserID", SelectedIDPConfigID: "IDPConfigID"}, false},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
SelectedIDPConfigID: "IDPConfigID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
}}, false},
|
||||
[]domain.NextStep{&domain.ExternalLoginStep{SelectedIDPConfigID: "IDPConfigID"}},
|
||||
nil,
|
||||
},
|
||||
@@ -715,23 +731,21 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
userGrantProvider: &mockUserGrants{},
|
||||
projectProvider: &mockProject{},
|
||||
applicationProvider: &mockApp{app: &query.App{OIDCConfig: &query.OIDCApp{AppType: domain.OIDCApplicationTypeWeb}}},
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{},
|
||||
},
|
||||
lockoutPolicyProvider: &mockLockoutPolicy{
|
||||
policy: &query.LockoutPolicy{
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
SelectedIDPConfigID: "IDPConfigID",
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
ExternalLoginCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
},
|
||||
false},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
@@ -751,7 +765,11 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
args{&domain.AuthRequest{UserID: "UserID", LoginPolicy: &domain.LoginPolicy{}}, false},
|
||||
[]domain.NextStep{&domain.PasswordStep{}},
|
||||
@@ -779,15 +797,16 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
SelectedIDPConfigID: "IDPConfigID",
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
ExternalLoginCheckLifetime: 10 * 24 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
nil,
|
||||
@@ -811,14 +830,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.MFAVerificationStep{
|
||||
@@ -844,14 +863,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.MFAVerificationStep{
|
||||
@@ -878,16 +897,16 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
ExternalLoginCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
SelectedIDPConfigID: "IDPConfigID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
ExternalLoginCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.MFAVerificationStep{
|
||||
@@ -915,14 +934,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.ChangePasswordStep{}},
|
||||
@@ -946,13 +965,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.VerifyEMailStep{}},
|
||||
@@ -977,13 +996,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.ChangePasswordStep{}, &domain.VerifyEMailStep{}},
|
||||
@@ -1011,14 +1030,14 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
@@ -1046,15 +1065,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Prompt: []domain.Prompt{domain.PromptNone},
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, true},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
@@ -1082,15 +1101,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Prompt: []domain.Prompt{domain.PromptNone},
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, true},
|
||||
[]domain.NextStep{&domain.LoginSucceededStep{}, &domain.RedirectToCallbackStep{}},
|
||||
@@ -1120,15 +1139,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Prompt: []domain.Prompt{domain.PromptNone},
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, true},
|
||||
[]domain.NextStep{&domain.GrantRequiredStep{}},
|
||||
@@ -1159,15 +1178,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Prompt: []domain.Prompt{domain.PromptNone},
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, true},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
@@ -1197,15 +1216,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Prompt: []domain.Prompt{domain.PromptNone},
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, true},
|
||||
[]domain.NextStep{&domain.ProjectRequiredStep{}},
|
||||
@@ -1236,15 +1255,15 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{&domain.AuthRequest{
|
||||
UserID: "UserID",
|
||||
Prompt: []domain.Prompt{domain.PromptNone},
|
||||
Request: &domain.AuthRequestOIDC{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
}, true},
|
||||
[]domain.NextStep{&domain.RedirectToCallbackStep{}},
|
||||
@@ -1266,9 +1285,13 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
userEventProvider: &mockEventUser{},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
loginPolicyProvider: &mockLoginPolicy{
|
||||
policy: &query.LoginPolicy{
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
},
|
||||
userEventProvider: &mockEventUser{},
|
||||
orgViewProvider: &mockViewOrg{State: domain.OrgStateActive},
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
@@ -1299,8 +1322,6 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
ShowFailures: true,
|
||||
},
|
||||
},
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
PasswordCheckLifeTime: 10 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
&domain.AuthRequest{
|
||||
@@ -1308,7 +1329,9 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
SelectedIDPConfigID: "IDPConfigID",
|
||||
LinkingUsers: []*domain.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
PasswordCheckLifetime: 10 * 24 * time.Hour,
|
||||
},
|
||||
}, false},
|
||||
[]domain.NextStep{&domain.LinkUsersStep{}},
|
||||
@@ -1318,22 +1341,17 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repo := &AuthRequestRepo{
|
||||
AuthRequests: tt.fields.AuthRequests,
|
||||
View: tt.fields.View,
|
||||
UserSessionViewProvider: tt.fields.userSessionViewProvider,
|
||||
UserViewProvider: tt.fields.userViewProvider,
|
||||
UserEventProvider: tt.fields.userEventProvider,
|
||||
OrgViewProvider: tt.fields.orgViewProvider,
|
||||
UserGrantProvider: tt.fields.userGrantProvider,
|
||||
ProjectProvider: tt.fields.projectProvider,
|
||||
ApplicationProvider: tt.fields.applicationProvider,
|
||||
LoginPolicyViewProvider: tt.fields.loginPolicyProvider,
|
||||
LockoutPolicyViewProvider: tt.fields.lockoutPolicyProvider,
|
||||
PasswordCheckLifeTime: tt.fields.PasswordCheckLifeTime,
|
||||
ExternalLoginCheckLifeTime: tt.fields.ExternalLoginCheckLifeTime,
|
||||
MFAInitSkippedLifeTime: tt.fields.MFAInitSkippedLifeTime,
|
||||
SecondFactorCheckLifeTime: tt.fields.SecondFactorCheckLifeTime,
|
||||
MultiFactorCheckLifeTime: tt.fields.MultiFactorCheckLifeTime,
|
||||
AuthRequests: tt.fields.AuthRequests,
|
||||
View: tt.fields.View,
|
||||
UserSessionViewProvider: tt.fields.userSessionViewProvider,
|
||||
UserViewProvider: tt.fields.userViewProvider,
|
||||
UserEventProvider: tt.fields.userEventProvider,
|
||||
OrgViewProvider: tt.fields.orgViewProvider,
|
||||
UserGrantProvider: tt.fields.userGrantProvider,
|
||||
ProjectProvider: tt.fields.projectProvider,
|
||||
ApplicationProvider: tt.fields.applicationProvider,
|
||||
LoginPolicyViewProvider: tt.fields.loginPolicyProvider,
|
||||
LockoutPolicyViewProvider: tt.fields.lockoutPolicyProvider,
|
||||
}
|
||||
got, err := repo.nextSteps(context.Background(), tt.args.request, tt.args.checkLoggedIn)
|
||||
if (err != nil && tt.wantErr == nil) || (tt.wantErr != nil && !tt.wantErr(err)) {
|
||||
@@ -1346,11 +1364,6 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
type fields struct {
|
||||
MFAInitSkippedLifeTime time.Duration
|
||||
SecondFactorCheckLifeTime time.Duration
|
||||
MultiFactorCheckLifeTime time.Duration
|
||||
}
|
||||
type args struct {
|
||||
userSession *user_model.UserSessionView
|
||||
request *domain.AuthRequest
|
||||
@@ -1358,7 +1371,6 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want domain.NextStep
|
||||
wantChecked bool
|
||||
@@ -1377,13 +1389,11 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
//},
|
||||
{
|
||||
"not set up, forced by policy, no mfas configured, error",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
ForceMFA: true,
|
||||
ForceMFA: true,
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
@@ -1398,12 +1408,11 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"not set up, no mfas configured, no prompt and true",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
HumanView: &user_model.HumanView{
|
||||
@@ -1417,13 +1426,11 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"not set up, prompt and false",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
@@ -1442,14 +1449,12 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"not set up, forced by org, true",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
ForceMFA: true,
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
ForceMFA: true,
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
@@ -1469,12 +1474,11 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"not set up and skipped, true",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{},
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
HumanView: &user_model.HumanView{
|
||||
@@ -1489,13 +1493,11 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"checked second factor, true",
|
||||
fields{
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
@@ -1512,13 +1514,11 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"not checked, check and false",
|
||||
fields{
|
||||
SecondFactorCheckLifeTime: 18 * time.Hour,
|
||||
},
|
||||
args{
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP},
|
||||
SecondFactorCheckLifetime: 18 * time.Hour,
|
||||
},
|
||||
},
|
||||
user: &user_model.UserView{
|
||||
@@ -1539,11 +1539,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repo := &AuthRequestRepo{
|
||||
MFAInitSkippedLifeTime: tt.fields.MFAInitSkippedLifeTime,
|
||||
SecondFactorCheckLifeTime: tt.fields.SecondFactorCheckLifeTime,
|
||||
MultiFactorCheckLifeTime: tt.fields.MultiFactorCheckLifeTime,
|
||||
}
|
||||
repo := &AuthRequestRepo{}
|
||||
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)
|
||||
@@ -1562,7 +1558,8 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
||||
MFAInitSkippedLifeTime time.Duration
|
||||
}
|
||||
type args struct {
|
||||
user *user_model.UserView
|
||||
user *user_model.UserView
|
||||
request *domain.AuthRequest
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -1574,51 +1571,58 @@ func TestAuthRequestRepo_mfaSkippedOrSetUp(t *testing.T) {
|
||||
"mfa set up, true",
|
||||
fields{},
|
||||
args{
|
||||
&user_model.UserView{
|
||||
user: &user_model.UserView{
|
||||
HumanView: &user_model.HumanView{
|
||||
MFAMaxSetUp: model.MFALevelSecondFactor,
|
||||
},
|
||||
},
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"mfa skipped active, true",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
fields{},
|
||||
args{
|
||||
&user_model.UserView{
|
||||
user: &user_model.UserView{
|
||||
HumanView: &user_model.HumanView{
|
||||
MFAMaxSetUp: -1,
|
||||
MFAInitSkipped: time.Now().UTC().Add(-10 * time.Hour),
|
||||
},
|
||||
},
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"mfa skipped inactive, false",
|
||||
fields{
|
||||
MFAInitSkippedLifeTime: 30 * 24 * time.Hour,
|
||||
},
|
||||
fields{},
|
||||
args{
|
||||
&user_model.UserView{
|
||||
user: &user_model.UserView{
|
||||
HumanView: &user_model.HumanView{
|
||||
MFAMaxSetUp: -1,
|
||||
MFAInitSkipped: time.Now().UTC().Add(-40 * 24 * time.Hour),
|
||||
},
|
||||
},
|
||||
request: &domain.AuthRequest{
|
||||
LoginPolicy: &domain.LoginPolicy{
|
||||
MFAInitSkipLifetime: 30 * 24 * time.Hour,
|
||||
},
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
repo := &AuthRequestRepo{
|
||||
MFAInitSkippedLifeTime: tt.fields.MFAInitSkippedLifeTime,
|
||||
}
|
||||
if got := repo.mfaSkippedOrSetUp(tt.args.user); got != tt.want {
|
||||
repo := &AuthRequestRepo{}
|
||||
if got := repo.mfaSkippedOrSetUp(tt.args.user, tt.args.request); got != tt.want {
|
||||
t.Errorf("mfaSkippedOrSetUp() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
|
@@ -72,31 +72,26 @@ func Start(conf Config, systemDefaults sd.SystemDefaults, command *command.Comma
|
||||
es,
|
||||
userRepo,
|
||||
eventstore.AuthRequestRepo{
|
||||
PrivacyPolicyProvider: queries,
|
||||
LabelPolicyProvider: queries,
|
||||
Command: command,
|
||||
Query: queries,
|
||||
OrgViewProvider: queries,
|
||||
AuthRequests: authReq,
|
||||
View: view,
|
||||
Eventstore: es,
|
||||
UserCodeAlg: userCrypto,
|
||||
UserSessionViewProvider: view,
|
||||
UserViewProvider: view,
|
||||
UserCommandProvider: command,
|
||||
UserEventProvider: &userRepo,
|
||||
IDPProviderViewProvider: view,
|
||||
LockoutPolicyViewProvider: queries,
|
||||
LoginPolicyViewProvider: queries,
|
||||
UserGrantProvider: queryView,
|
||||
ProjectProvider: queryView,
|
||||
ApplicationProvider: queries,
|
||||
IdGenerator: idGenerator,
|
||||
PasswordCheckLifeTime: systemDefaults.VerificationLifetimes.PasswordCheck,
|
||||
ExternalLoginCheckLifeTime: systemDefaults.VerificationLifetimes.PasswordCheck,
|
||||
MFAInitSkippedLifeTime: systemDefaults.VerificationLifetimes.MFAInitSkip,
|
||||
SecondFactorCheckLifeTime: systemDefaults.VerificationLifetimes.SecondFactorCheck,
|
||||
MultiFactorCheckLifeTime: systemDefaults.VerificationLifetimes.MultiFactorCheck,
|
||||
PrivacyPolicyProvider: queries,
|
||||
LabelPolicyProvider: queries,
|
||||
Command: command,
|
||||
Query: queries,
|
||||
OrgViewProvider: queries,
|
||||
AuthRequests: authReq,
|
||||
View: view,
|
||||
Eventstore: es,
|
||||
UserCodeAlg: userCrypto,
|
||||
UserSessionViewProvider: view,
|
||||
UserViewProvider: view,
|
||||
UserCommandProvider: command,
|
||||
UserEventProvider: &userRepo,
|
||||
IDPProviderViewProvider: view,
|
||||
LockoutPolicyViewProvider: queries,
|
||||
LoginPolicyViewProvider: queries,
|
||||
UserGrantProvider: queryView,
|
||||
ProjectProvider: queryView,
|
||||
ApplicationProvider: queries,
|
||||
IdGenerator: idGenerator,
|
||||
},
|
||||
eventstore.TokenRepo{
|
||||
View: view,
|
||||
|
Reference in New Issue
Block a user