mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 07:57:32 +00:00
feat: mfa policy (#913)
* feat: add mfa to login policy * feat: add mfa to login policy * feat: add mfa to login policy * feat: add mfa to login policy * feat: add mfa to login policy on org * feat: add mfa to login policy on org * feat: append events on policy views * feat: iam login policy mfa definition * feat: login policies on orgs * feat: configured mfas in login process * feat: configured mfas in login process * Update internal/ui/login/static/i18n/en.yaml Co-authored-by: Livio Amstutz <livio.a@gmail.com> * fix: rename software and hardware mfas * fix: pr requests * fix user mfa * fix: test * fix: oidc version * fix: oidc version * fix: proto gen Co-authored-by: Livio Amstutz <livio.a@gmail.com> Co-authored-by: Max Peintner <max@caos.ch>
This commit is contained in:
@@ -140,7 +140,7 @@ func UserToModel(user *UserView) *model.UserView {
|
||||
Region: user.Region,
|
||||
StreetAddress: user.StreetAddress,
|
||||
OTPState: model.MfaState(user.OTPState),
|
||||
MfaMaxSetUp: req_model.MfaLevel(user.MfaMaxSetUp),
|
||||
MfaMaxSetUp: req_model.MFALevel(user.MfaMaxSetUp),
|
||||
MfaInitSkipped: user.MfaInitSkipped,
|
||||
InitRequired: user.InitRequired,
|
||||
}
|
||||
@@ -313,9 +313,9 @@ func (u *UserView) ComputeObject() {
|
||||
}
|
||||
}
|
||||
if u.OTPState != int32(model.MfaStateReady) {
|
||||
u.MfaMaxSetUp = int32(req_model.MfaLevelNotSetUp)
|
||||
u.MfaMaxSetUp = int32(req_model.MFALevelNotSetUp)
|
||||
}
|
||||
if u.OTPState == int32(model.MfaStateReady) {
|
||||
u.MfaMaxSetUp = int32(req_model.MfaLevelSoftware)
|
||||
u.MfaMaxSetUp = int32(req_model.MFALevelSecondFactor)
|
||||
}
|
||||
}
|
||||
|
@@ -21,23 +21,23 @@ const (
|
||||
)
|
||||
|
||||
type UserSessionView struct {
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
|
||||
State int32 `json:"-" gorm:"column:state"`
|
||||
UserAgentID string `json:"userAgentID" gorm:"column:user_agent_id;primary_key"`
|
||||
UserID string `json:"userID" gorm:"column:user_id;primary_key"`
|
||||
UserName string `json:"-" gorm:"column:user_name"`
|
||||
LoginName string `json:"-" gorm:"column:login_name"`
|
||||
DisplayName string `json:"-" gorm:"column:user_display_name"`
|
||||
SelectedIDPConfigID string `json:"selectedIDPConfigID" gorm:"column:selected_idp_config_id"`
|
||||
PasswordVerification time.Time `json:"-" gorm:"column:password_verification"`
|
||||
ExternalLoginVerification time.Time `json:"-" gorm:"column:external_login_verification"`
|
||||
MfaSoftwareVerification time.Time `json:"-" gorm:"column:mfa_software_verification"`
|
||||
MfaSoftwareVerificationType int32 `json:"-" gorm:"column:mfa_software_verification_type"`
|
||||
MfaHardwareVerification time.Time `json:"-" gorm:"column:mfa_hardware_verification"`
|
||||
MfaHardwareVerificationType int32 `json:"-" gorm:"column:mfa_hardware_verification_type"`
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
CreationDate time.Time `json:"-" gorm:"column:creation_date"`
|
||||
ChangeDate time.Time `json:"-" gorm:"column:change_date"`
|
||||
ResourceOwner string `json:"-" gorm:"column:resource_owner"`
|
||||
State int32 `json:"-" gorm:"column:state"`
|
||||
UserAgentID string `json:"userAgentID" gorm:"column:user_agent_id;primary_key"`
|
||||
UserID string `json:"userID" gorm:"column:user_id;primary_key"`
|
||||
UserName string `json:"-" gorm:"column:user_name"`
|
||||
LoginName string `json:"-" gorm:"column:login_name"`
|
||||
DisplayName string `json:"-" gorm:"column:user_display_name"`
|
||||
SelectedIDPConfigID string `json:"selectedIDPConfigID" gorm:"column:selected_idp_config_id"`
|
||||
PasswordVerification time.Time `json:"-" gorm:"column:password_verification"`
|
||||
ExternalLoginVerification time.Time `json:"-" gorm:"column:external_login_verification"`
|
||||
SecondFactorVerification time.Time `json:"-" gorm:"column:second_factor_verification"`
|
||||
SecondFactorVerificationType int32 `json:"-" gorm:"column:second_factor_verification_type"`
|
||||
MultiFactorVerification time.Time `json:"-" gorm:"column:multi_factor_verification"`
|
||||
MultiFactorVerificationType int32 `json:"-" gorm:"column:multi_factor_verification_type"`
|
||||
Sequence uint64 `json:"-" gorm:"column:sequence"`
|
||||
}
|
||||
|
||||
func UserSessionFromEvent(event *models.Event) (*UserSessionView, error) {
|
||||
@@ -51,23 +51,23 @@ func UserSessionFromEvent(event *models.Event) (*UserSessionView, error) {
|
||||
|
||||
func UserSessionToModel(userSession *UserSessionView) *model.UserSessionView {
|
||||
return &model.UserSessionView{
|
||||
ChangeDate: userSession.ChangeDate,
|
||||
CreationDate: userSession.CreationDate,
|
||||
ResourceOwner: userSession.ResourceOwner,
|
||||
State: req_model.UserSessionState(userSession.State),
|
||||
UserAgentID: userSession.UserAgentID,
|
||||
UserID: userSession.UserID,
|
||||
UserName: userSession.UserName,
|
||||
LoginName: userSession.LoginName,
|
||||
DisplayName: userSession.DisplayName,
|
||||
SelectedIDPConfigID: userSession.SelectedIDPConfigID,
|
||||
PasswordVerification: userSession.PasswordVerification,
|
||||
ExternalLoginVerification: userSession.ExternalLoginVerification,
|
||||
MfaSoftwareVerification: userSession.MfaSoftwareVerification,
|
||||
MfaSoftwareVerificationType: req_model.MfaType(userSession.MfaSoftwareVerificationType),
|
||||
MfaHardwareVerification: userSession.MfaHardwareVerification,
|
||||
MfaHardwareVerificationType: req_model.MfaType(userSession.MfaHardwareVerificationType),
|
||||
Sequence: userSession.Sequence,
|
||||
ChangeDate: userSession.ChangeDate,
|
||||
CreationDate: userSession.CreationDate,
|
||||
ResourceOwner: userSession.ResourceOwner,
|
||||
State: req_model.UserSessionState(userSession.State),
|
||||
UserAgentID: userSession.UserAgentID,
|
||||
UserID: userSession.UserID,
|
||||
UserName: userSession.UserName,
|
||||
LoginName: userSession.LoginName,
|
||||
DisplayName: userSession.DisplayName,
|
||||
SelectedIDPConfigID: userSession.SelectedIDPConfigID,
|
||||
PasswordVerification: userSession.PasswordVerification,
|
||||
ExternalLoginVerification: userSession.ExternalLoginVerification,
|
||||
SecondFactorVerification: userSession.SecondFactorVerification,
|
||||
SecondFactorVerificationType: req_model.MFAType(userSession.SecondFactorVerificationType),
|
||||
MultiFactorVerification: userSession.MultiFactorVerification,
|
||||
MultiFactorVerificationType: req_model.MFAType(userSession.MultiFactorVerificationType),
|
||||
Sequence: userSession.Sequence,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,20 +100,20 @@ func (v *UserSessionView) AppendEvent(event *models.Event) {
|
||||
v.PasswordVerification = time.Time{}
|
||||
case es_model.MFAOTPCheckSucceeded,
|
||||
es_model.HumanMFAOTPCheckSucceeded:
|
||||
v.MfaSoftwareVerification = event.CreationDate
|
||||
v.MfaSoftwareVerificationType = int32(req_model.MfaTypeOTP)
|
||||
v.SecondFactorVerification = event.CreationDate
|
||||
v.SecondFactorVerificationType = int32(req_model.MFATypeOTP)
|
||||
v.State = int32(req_model.UserSessionStateActive)
|
||||
case es_model.MFAOTPCheckFailed,
|
||||
es_model.MFAOTPRemoved,
|
||||
es_model.HumanMFAOTPCheckFailed,
|
||||
es_model.HumanMFAOTPRemoved:
|
||||
v.MfaSoftwareVerification = time.Time{}
|
||||
v.SecondFactorVerification = time.Time{}
|
||||
case es_model.SignedOut,
|
||||
es_model.HumanSignedOut,
|
||||
es_model.UserLocked,
|
||||
es_model.UserDeactivated:
|
||||
v.PasswordVerification = time.Time{}
|
||||
v.MfaSoftwareVerification = time.Time{}
|
||||
v.SecondFactorVerification = time.Time{}
|
||||
v.ExternalLoginVerification = time.Time{}
|
||||
v.State = int32(req_model.UserSessionStateTerminated)
|
||||
}
|
||||
|
@@ -78,7 +78,7 @@ func TestAppendEvent(t *testing.T) {
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.MFAOTPCheckSucceeded},
|
||||
userView: &UserSessionView{},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), MfaSoftwareVerification: now()},
|
||||
result: &UserSessionView{ChangeDate: now(), SecondFactorVerification: now()},
|
||||
},
|
||||
{
|
||||
name: "append human otp check succeeded event",
|
||||
@@ -86,55 +86,55 @@ func TestAppendEvent(t *testing.T) {
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.HumanMFAOTPCheckSucceeded},
|
||||
userView: &UserSessionView{},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), MfaSoftwareVerification: now()},
|
||||
result: &UserSessionView{ChangeDate: now(), SecondFactorVerification: now()},
|
||||
},
|
||||
{
|
||||
name: "append user otp check failed event",
|
||||
args: args{
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.MFAOTPCheckFailed},
|
||||
userView: &UserSessionView{MfaSoftwareVerification: now()},
|
||||
userView: &UserSessionView{SecondFactorVerification: now()},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), MfaSoftwareVerification: time.Time{}},
|
||||
result: &UserSessionView{ChangeDate: now(), SecondFactorVerification: time.Time{}},
|
||||
},
|
||||
{
|
||||
name: "append human otp check failed event",
|
||||
args: args{
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.HumanMFAOTPCheckFailed},
|
||||
userView: &UserSessionView{MfaSoftwareVerification: now()},
|
||||
userView: &UserSessionView{SecondFactorVerification: now()},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), MfaSoftwareVerification: time.Time{}},
|
||||
result: &UserSessionView{ChangeDate: now(), SecondFactorVerification: time.Time{}},
|
||||
},
|
||||
{
|
||||
name: "append user otp removed event",
|
||||
args: args{
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.MFAOTPRemoved},
|
||||
userView: &UserSessionView{MfaSoftwareVerification: now()},
|
||||
userView: &UserSessionView{SecondFactorVerification: now()},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), MfaSoftwareVerification: time.Time{}},
|
||||
result: &UserSessionView{ChangeDate: now(), SecondFactorVerification: time.Time{}},
|
||||
},
|
||||
{
|
||||
name: "append human otp removed event",
|
||||
args: args{
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.HumanMFAOTPRemoved},
|
||||
userView: &UserSessionView{MfaSoftwareVerification: now()},
|
||||
userView: &UserSessionView{SecondFactorVerification: now()},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), MfaSoftwareVerification: time.Time{}},
|
||||
result: &UserSessionView{ChangeDate: now(), SecondFactorVerification: time.Time{}},
|
||||
},
|
||||
{
|
||||
name: "append user signed out event",
|
||||
args: args{
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.SignedOut},
|
||||
userView: &UserSessionView{PasswordVerification: now(), MfaSoftwareVerification: now()},
|
||||
userView: &UserSessionView{PasswordVerification: now(), SecondFactorVerification: now()},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), PasswordVerification: time.Time{}, MfaSoftwareVerification: time.Time{}, State: 1},
|
||||
result: &UserSessionView{ChangeDate: now(), PasswordVerification: time.Time{}, SecondFactorVerification: time.Time{}, State: 1},
|
||||
},
|
||||
{
|
||||
name: "append human signed out event",
|
||||
args: args{
|
||||
event: &es_models.Event{CreationDate: now(), Type: es_model.HumanSignedOut},
|
||||
userView: &UserSessionView{PasswordVerification: now(), MfaSoftwareVerification: now()},
|
||||
userView: &UserSessionView{PasswordVerification: now(), SecondFactorVerification: now()},
|
||||
},
|
||||
result: &UserSessionView{ChangeDate: now(), PasswordVerification: time.Time{}, MfaSoftwareVerification: time.Time{}, State: 1},
|
||||
result: &UserSessionView{ChangeDate: now(), PasswordVerification: time.Time{}, SecondFactorVerification: time.Time{}, State: 1},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
Reference in New Issue
Block a user