feat: enable otp email and sms (#6260)

* feat: enable otp email and sms

* feat: enable otp factors in login settings

* remove tests without value

* translate second factors

* don't add new factors yet

* add comment

* add factors to docs

* backward compatible settings api

* compile tests

* add available 2fa types

* test: add mapping tests

---------

Co-authored-by: Livio Spring <livio.a@gmail.com>
This commit is contained in:
Elio Bischof 2023-07-28 07:39:30 +02:00 committed by GitHub
parent d3e403f645
commit 31ec1d83b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 696 additions and 124 deletions

View File

@ -146,7 +146,12 @@ export class FactorTableComponent {
this.componentType === LoginMethodComponentType.MultiFactor this.componentType === LoginMethodComponentType.MultiFactor
? [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION] ? [MultiFactorType.MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION]
: this.componentType === LoginMethodComponentType.SecondFactor : this.componentType === LoginMethodComponentType.SecondFactor
? [SecondFactorType.SECOND_FACTOR_TYPE_U2F, SecondFactorType.SECOND_FACTOR_TYPE_OTP] ? [
SecondFactorType.SECOND_FACTOR_TYPE_U2F,
SecondFactorType.SECOND_FACTOR_TYPE_OTP,
SecondFactorType.SECOND_FACTOR_TYPE_OTP_SMS,
SecondFactorType.SECOND_FACTOR_TYPE_OTP_EMAIL,
]
: []; : [];
const filtered = (allTypes as Array<MultiFactorType | SecondFactorType>).filter((type) => !this.list.includes(type)); const filtered = (allTypes as Array<MultiFactorType | SecondFactorType>).filter((type) => !this.list.includes(type));

View File

@ -1840,8 +1840,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "неизвестен", "0": "неизвестен",
"1": "Еднократна парола (OTP)", "1": "Еднократна парола чрез приложение за удостоверяване на автентичността (TOTP)",
"2": "Пръстов отпечатък, ключове за сигурност, Face ID и други" "2": "Пръстов отпечатък, ключове за сигурност, Face ID и други",
"3": "Еднократна парола по имейл (Email OTP)",
"4": "Еднократна парола чрез SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1849,8 +1849,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Unknown", "0": "Unknown",
"1": "One Time Password (OTP)", "1": "One Time Password per Authenticator App (TOTP)",
"2": "Fingerabdruck, Security Keys, Face ID und andere" "2": "Fingerabdruck, Security Keys, Face ID und andere",
"3": "One Time Password per Email (Email OTP)",
"4": "One Time Password per SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1846,8 +1846,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Unknown", "0": "Unknown",
"1": "One Time Password (OTP)", "1": "One Time Password by Authenticator App (TOTP)",
"2": "Fingerprint, Security Keys, Face ID and other" "2": "Fingerprint, Security Keys, Face ID and other",
"3": "One Time Password by Email (Email OTP)",
"4": "One Time Password by SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1846,8 +1846,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Desconocido", "0": "Desconocido",
"1": "One Time Password (OTP)", "1": "One Time Password por Authenticator App (TOTP)",
"2": "Huella dactilar, claves de seguridad, Face ID y otros" "2": "Huella dactilar, claves de seguridad, Face ID y otros",
"3": "One Time Password por email (Email OTP)",
"4": "One Time Password por SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1850,8 +1850,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Inconnu", "0": "Inconnu",
"1": "Mot de passe à usage unique (OTP)", "1": "One Time Password par authenticator app (TOTP)",
"2": "Empreinte digitale, clés de sécurité, Face ID et autres" "2": "Empreinte digitale, clés de sécurité, Face ID et autres",
"3": "One Time Password par email (Email OTP)",
"4": "One Time Password par SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1850,8 +1850,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Sconosciuto", "0": "Sconosciuto",
"1": "One Time Password (OTP)", "1": "One Time Password per Authenticator App (TOTP)",
"2": "Impronta digitale, chiave di sicurezza, Face ID e altri" "2": "Impronta digitale, chiave di sicurezza, Face ID e altri",
"3": "One Time Password per Email (Email OTP)",
"4": "One Time Password per SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1841,8 +1841,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "不明", "0": "不明",
"1": "ワンタイムパスワードOTP", "1": "認証アプリ用ワンタイムパスワード(TOTP)",
"2": "指紋、セキュリティキー、フェイスIDなど" "2": "指紋、セキュリティキー、フェイスIDなど",
"3": "Eメール用ワンタイムパスワードemail OTP",
"4": "SMS用ワンタイムパスワードSMS OTP"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1846,8 +1846,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Непознато", "0": "Непознато",
"1": "Еднократна лозинка (OTP)", "1": "Еднократна лозинка преку апликација за автентикатор (TOTP)",
"2": "Отисок на прст, безбедносни клучеви, Face ID и другo" "2": "Отпечаток на прст, безбедносни клучеви, Face ID и други",
"3": "Еднократна лозинка по е-пошта (Еmail OTP)",
"4": "Еднократна лозинка преку СМС (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1850,8 +1850,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Nieznany", "0": "Nieznany",
"1": "Jednorazowe hasło (OTP)", "1": "Hasło jednorazowe dla aplikacji uwierzytelniającej (TOTP)",
"2": "Odcisk palca, klucze bezpieczeństwa, Face ID i inne" "2": "Odcisk palca, Klucze Bezpieczeństwa, Face ID i inne",
"3": "Hasło jednorazowe dla wiadomości e-mail (Email OTP)",
"4": "Hasło jednorazowe dla wiadomości SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1844,8 +1844,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "Desconhecido", "0": "Desconhecido",
"1": "Senha de Uso Único (OTP)", "1": "Senha de uso único para o aplicativo autenticador (TOTP)",
"2": "Impressão Digital, Chaves de Segurança, Face ID e outros" "2": "Impressão digital, Chaves de Segurança, Face ID e outros",
"3": "Senha de uso único para e-mail (Email OTP)",
"4": "Senha de uso único para SMS (SMS OTP)"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -1849,8 +1849,10 @@
}, },
"SECONDFACTORTYPES": { "SECONDFACTORTYPES": {
"0": "未知", "0": "未知",
"1": "一次性密码 (OTP)", "1": "身份验证应用程序的一次性密码TOTP",
"2": "指纹、安全密钥、Face ID 等" "2": "指纹、安全密钥、Face ID 等",
"3": "电子邮件一次性密码email OTP",
"4": "短信一次性密码SMS OTP"
} }
}, },
"LOGINPOLICY": { "LOGINPOLICY": {

View File

@ -120,8 +120,10 @@ Multifactors:
Secondfactors (2FA): Secondfactors (2FA):
- OTP (One Time Password), Authenticator Apps like Google/Microsoft Authenticator, Authy, etc. - Time-based One Time Password (TOTP), Authenticator Apps like Google/Microsoft Authenticator, Authy, etc.
- U2F (Universal Second Factor), e.g FaceID, WindowsHello, Fingerprint, Hardwaretokens like Yubikey - Universal Second Factor (U2F), e.g FaceID, WindowsHello, Fingerprint, Hardwaretokens like Yubikey
- One Time Password with Email (Email OTP)
- One Time Password with SMS (SMS OTP)
Force a user to register and use a multifactor authentication, by checking the option "Force MFA". Force a user to register and use a multifactor authentication, by checking the option "Force MFA".
Ensure that you have added the MFA methods you want to allow. Ensure that you have added the MFA methods you want to allow.

View File

@ -16,9 +16,13 @@ func SecondFactorsTypesToDomain(secondFactorTypes []policy_pb.SecondFactorType)
func SecondFactorTypeToDomain(secondFactorType policy_pb.SecondFactorType) domain.SecondFactorType { func SecondFactorTypeToDomain(secondFactorType policy_pb.SecondFactorType) domain.SecondFactorType {
switch secondFactorType { switch secondFactorType {
case policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP: case policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP:
return domain.SecondFactorTypeOTP return domain.SecondFactorTypeTOTP
case policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_U2F: case policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_U2F:
return domain.SecondFactorTypeU2F return domain.SecondFactorTypeU2F
case policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP_EMAIL:
return domain.SecondFactorTypeOTPEmail
case policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP_SMS:
return domain.SecondFactorTypeOTPSMS
default: default:
return domain.SecondFactorTypeUnspecified return domain.SecondFactorTypeUnspecified
} }
@ -34,10 +38,14 @@ func ModelSecondFactorTypesToPb(types []domain.SecondFactorType) []policy_pb.Sec
func ModelSecondFactorTypeToPb(secondFactorType domain.SecondFactorType) policy_pb.SecondFactorType { func ModelSecondFactorTypeToPb(secondFactorType domain.SecondFactorType) policy_pb.SecondFactorType {
switch secondFactorType { switch secondFactorType {
case domain.SecondFactorTypeOTP: case domain.SecondFactorTypeTOTP:
return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP
case domain.SecondFactorTypeU2F: case domain.SecondFactorTypeU2F:
return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_U2F return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_U2F
case domain.SecondFactorTypeOTPEmail:
return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP_EMAIL
case domain.SecondFactorTypeOTPSMS:
return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_OTP_SMS
default: default:
return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED return policy_pb.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED
} }

View File

@ -62,10 +62,14 @@ func passkeysTypeToPb(passwordlessType domain.PasswordlessType) settings.Passkey
func secondFactorTypeToPb(secondFactorType domain.SecondFactorType) settings.SecondFactorType { func secondFactorTypeToPb(secondFactorType domain.SecondFactorType) settings.SecondFactorType {
switch secondFactorType { switch secondFactorType {
case domain.SecondFactorTypeOTP: case domain.SecondFactorTypeTOTP:
return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP
case domain.SecondFactorTypeU2F: case domain.SecondFactorTypeU2F:
return settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F return settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F
case domain.SecondFactorTypeOTPEmail:
return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_EMAIL
case domain.SecondFactorTypeOTPSMS:
return settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_SMS
case domain.SecondFactorTypeUnspecified: case domain.SecondFactorTypeUnspecified:
return settings.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED return settings.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED
default: default:

View File

@ -39,8 +39,10 @@ func Test_loginSettingsToPb(t *testing.T) {
SecondFactorCheckLifetime: time.Microsecond, SecondFactorCheckLifetime: time.Microsecond,
MultiFactorCheckLifetime: time.Nanosecond, MultiFactorCheckLifetime: time.Nanosecond,
SecondFactors: []domain.SecondFactorType{ SecondFactors: []domain.SecondFactorType{
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
domain.SecondFactorTypeU2F, domain.SecondFactorTypeU2F,
domain.SecondFactorTypeOTPEmail,
domain.SecondFactorTypeOTPSMS,
}, },
MultiFactors: []domain.MultiFactorType{ MultiFactors: []domain.MultiFactorType{
domain.MultiFactorTypeU2FWithPIN, domain.MultiFactorTypeU2FWithPIN,
@ -69,6 +71,8 @@ func Test_loginSettingsToPb(t *testing.T) {
SecondFactors: []settings.SecondFactorType{ SecondFactors: []settings.SecondFactorType{
settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP, settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP,
settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F, settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F,
settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_EMAIL,
settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_SMS,
}, },
MultiFactors: []settings.MultiFactorType{ MultiFactors: []settings.MultiFactorType{
settings.MultiFactorType_MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION, settings.MultiFactorType_MULTI_FACTOR_TYPE_U2F_WITH_VERIFICATION,
@ -146,13 +150,21 @@ func Test_secondFactorTypeToPb(t *testing.T) {
want settings.SecondFactorType want settings.SecondFactorType
}{ }{
{ {
args: args{domain.SecondFactorTypeOTP}, args: args{domain.SecondFactorTypeTOTP},
want: settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP, want: settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP,
}, },
{ {
args: args{domain.SecondFactorTypeU2F}, args: args{domain.SecondFactorTypeU2F},
want: settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F, want: settings.SecondFactorType_SECOND_FACTOR_TYPE_U2F,
}, },
{
args: args{domain.SecondFactorTypeOTPSMS},
want: settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_SMS,
},
{
args: args{domain.SecondFactorTypeOTPEmail},
want: settings.SecondFactorType_SECOND_FACTOR_TYPE_OTP_EMAIL,
},
{ {
args: args{domain.SecondFactorTypeUnspecified}, args: args{domain.SecondFactorTypeUnspecified},
want: settings.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED, want: settings.SecondFactorType_SECOND_FACTOR_TYPE_UNSPECIFIED,

View File

@ -889,7 +889,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
&domain.AuthRequest{ &domain.AuthRequest{
UserID: "UserID", UserID: "UserID",
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -923,7 +923,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
&domain.AuthRequest{ &domain.AuthRequest{
UserID: "UserID", UserID: "UserID",
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -959,7 +959,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
UserID: "UserID", UserID: "UserID",
SelectedIDPConfigID: "IDPConfigID", SelectedIDPConfigID: "IDPConfigID",
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
ExternalLoginCheckLifetime: 10 * 24 * time.Hour, ExternalLoginCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
@ -996,7 +996,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
&domain.AuthRequest{ &domain.AuthRequest{
UserID: "UserID", UserID: "UserID",
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1027,7 +1027,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
args{&domain.AuthRequest{ args{&domain.AuthRequest{
UserID: "UserID", UserID: "UserID",
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1059,7 +1059,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
args{&domain.AuthRequest{ args{&domain.AuthRequest{
UserID: "UserID", UserID: "UserID",
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1095,7 +1095,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
UserID: "UserID", UserID: "UserID",
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1132,7 +1132,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Prompt: []domain.Prompt{domain.PromptNone}, Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1169,7 +1169,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Prompt: []domain.Prompt{domain.PromptNone}, Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1208,7 +1208,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Prompt: []domain.Prompt{domain.PromptNone}, Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1248,7 +1248,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Prompt: []domain.Prompt{domain.PromptNone}, Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1288,7 +1288,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Prompt: []domain.Prompt{domain.PromptNone}, Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1329,7 +1329,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
Prompt: []domain.Prompt{domain.PromptNone}, Prompt: []domain.Prompt{domain.PromptNone},
Request: &domain.AuthRequestOIDC{}, Request: &domain.AuthRequestOIDC{},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
@ -1399,7 +1399,7 @@ func TestAuthRequestRepo_nextSteps(t *testing.T) {
SelectedIDPConfigID: "IDPConfigID", SelectedIDPConfigID: "IDPConfigID",
LinkingUsers: []*domain.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}}, LinkingUsers: []*domain.ExternalUser{{IDPConfigID: "IDPConfigID", ExternalUserID: "UserID", DisplayName: "DisplayName"}},
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
PasswordCheckLifetime: 10 * 24 * time.Hour, PasswordCheckLifetime: 10 * 24 * time.Hour,
}, },
@ -1503,7 +1503,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
MFAInitSkipLifetime: 30 * 24 * time.Hour, MFAInitSkipLifetime: 30 * 24 * time.Hour,
}, },
}, },
@ -1528,7 +1528,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
ForceMFA: true, ForceMFA: true,
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
MFAInitSkipLifetime: 30 * 24 * time.Hour, MFAInitSkipLifetime: 30 * 24 * time.Hour,
}, },
}, },
@ -1573,7 +1573,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
}, },
@ -1595,7 +1595,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
}, },
@ -1620,7 +1620,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
}, },
@ -1644,7 +1644,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
}, },
}, },
@ -1666,7 +1666,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
ForceMFA: true, ForceMFA: true,
}, },
@ -1693,7 +1693,7 @@ func TestAuthRequestRepo_mfaChecked(t *testing.T) {
args{ args{
request: &domain.AuthRequest{ request: &domain.AuthRequest{
LoginPolicy: &domain.LoginPolicy{ LoginPolicy: &domain.LoginPolicy{
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
SecondFactorCheckLifetime: 18 * time.Hour, SecondFactorCheckLifetime: 18 * time.Hour,
ForceMFA: true, ForceMFA: true,
ForceMFALocalOnly: true, ForceMFALocalOnly: true,

View File

@ -245,8 +245,12 @@ func (c *Commands) SetUpInstance(ctx context.Context, setup *InstanceSetup) (str
setup.LoginPolicy.SecondFactorCheckLifetime, setup.LoginPolicy.SecondFactorCheckLifetime,
setup.LoginPolicy.MultiFactorCheckLifetime, setup.LoginPolicy.MultiFactorCheckLifetime,
), ),
prepareAddSecondFactorToDefaultLoginPolicy(instanceAgg, domain.SecondFactorTypeOTP), prepareAddSecondFactorToDefaultLoginPolicy(instanceAgg, domain.SecondFactorTypeTOTP),
prepareAddSecondFactorToDefaultLoginPolicy(instanceAgg, domain.SecondFactorTypeU2F), prepareAddSecondFactorToDefaultLoginPolicy(instanceAgg, domain.SecondFactorTypeU2F),
/* TODO: incomment when usable
prepareAddSecondFactorToDefaultLoginPolicy(instanceAgg, domain.SecondFactorTypeOTPEmail),
prepareAddSecondFactorToDefaultLoginPolicy(instanceAgg, domain.SecondFactorTypeOTPSMS),
*/
prepareAddMultiFactorToDefaultLoginPolicy(instanceAgg, domain.MultiFactorTypeU2FWithPIN), prepareAddMultiFactorToDefaultLoginPolicy(instanceAgg, domain.MultiFactorTypeU2FWithPIN),
prepareAddDefaultPrivacyPolicy(instanceAgg, setup.PrivacyPolicy.TOSLink, setup.PrivacyPolicy.PrivacyLink, setup.PrivacyPolicy.HelpLink, setup.PrivacyPolicy.SupportEmail), prepareAddDefaultPrivacyPolicy(instanceAgg, setup.PrivacyPolicy.TOSLink, setup.PrivacyPolicy.PrivacyLink, setup.PrivacyPolicy.HelpLink, setup.PrivacyPolicy.SupportEmail),

View File

@ -884,7 +884,7 @@ func TestCommandSide_AddSecondFactorDefaultLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(), instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, &instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
), ),
@ -892,14 +892,14 @@ func TestCommandSide_AddSecondFactorDefaultLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
}, },
res: res{ res: res{
err: caos_errs.IsErrorAlreadyExists, err: caos_errs.IsErrorAlreadyExists,
}, },
}, },
{ {
name: "add factor, ok", name: "add factor totp, ok",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -910,7 +910,7 @@ func TestCommandSide_AddSecondFactorDefaultLoginPolicy(t *testing.T) {
"INSTANCE", "INSTANCE",
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(), instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, &instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTP), domain.SecondFactorTypeTOTP),
), ),
}, },
), ),
@ -918,7 +918,98 @@ func TestCommandSide_AddSecondFactorDefaultLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"), ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "add factor otp email, ok ",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectPush(
[]*repository.Event{
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPEmail),
),
},
),
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
factor: domain.SecondFactorTypeOTPEmail,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "add factor otp sms, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectPush(
[]*repository.Event{
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPSMS),
),
},
),
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
factor: domain.SecondFactorTypeOTPSMS,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "add factor totp, add otp sms, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeTOTP,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusherWithInstanceID(
"INSTANCE",
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPSMS),
),
},
),
),
},
args: args{
ctx: authz.WithInstanceID(context.Background(), "INSTANCE"),
factor: domain.SecondFactorTypeOTPSMS,
}, },
res: res{ res: res{
want: &domain.ObjectDetails{ want: &domain.ObjectDetails{
@ -989,14 +1080,14 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
}, },
res: res{ res: res{
err: caos_errs.IsNotFound, err: caos_errs.IsNotFound,
}, },
}, },
{ {
name: "factor removed, not found error", name: "factor removed totp, not found error",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -1004,13 +1095,13 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(), instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, &instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
eventFromEventPusher( eventFromEventPusher(
instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(), instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, &instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
), ),
@ -1018,14 +1109,14 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
}, },
res: res{ res: res{
err: caos_errs.IsNotFound, err: caos_errs.IsNotFound,
}, },
}, },
{ {
name: "add factor, ok", name: "factor removed otp email, not found error",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -1033,7 +1124,65 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(), instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, &instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeOTPEmail,
),
),
eventFromEventPusher(
instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPEmail,
),
),
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPEmail,
},
res: res{
err: caos_errs.IsNotFound,
},
},
{
name: "factor removed otp sms, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPSMS,
),
),
eventFromEventPusher(
instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPSMS,
),
),
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
},
res: res{
err: caos_errs.IsNotFound,
},
},
{
name: "remove factor totp, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeTOTP,
), ),
), ),
), ),
@ -1042,7 +1191,7 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(), instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate, &instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTP), domain.SecondFactorTypeTOTP),
), ),
}, },
), ),
@ -1050,7 +1199,7 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
}, },
res: res{ res: res{
want: &domain.ObjectDetails{ want: &domain.ObjectDetails{
@ -1058,6 +1207,97 @@ func TestCommandSide_RemoveSecondFactorDefaultLoginPolicy(t *testing.T) {
}, },
}, },
}, },
{
name: "remove factor email, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPEmail,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPEmail),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPEmail,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "remove factor sms, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPSMS,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
instance.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeOTPSMS),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "INSTANCE",
},
},
},
{
name: "factor added totp, removed otp sms, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
instance.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&instance.NewAggregate("INSTANCE").Aggregate,
domain.SecondFactorTypeTOTP,
),
),
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
},
res: res{
err: caos_errs.IsNotFound,
},
},
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {

View File

@ -231,7 +231,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(), org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
eventFromEventPusher( eventFromEventPusher(
@ -265,7 +265,7 @@ func TestCommandSide_AddLoginPolicy(t *testing.T) {
MFAInitSkipLifetime: time.Hour * 3, MFAInitSkipLifetime: time.Hour * 3,
SecondFactorCheckLifetime: time.Hour * 4, SecondFactorCheckLifetime: time.Hour * 4,
MultiFactorCheckLifetime: time.Hour * 5, MultiFactorCheckLifetime: time.Hour * 5,
SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeOTP}, SecondFactors: []domain.SecondFactorType{domain.SecondFactorTypeTOTP},
MultiFactors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN}, MultiFactors: []domain.MultiFactorType{domain.MultiFactorTypeU2FWithPIN},
}, },
}, },
@ -1504,7 +1504,7 @@ func TestCommandSide_AddSecondFactorLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(), org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
), ),
@ -1512,7 +1512,7 @@ func TestCommandSide_AddSecondFactorLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
resourceOwner: "org1", resourceOwner: "org1",
}, },
res: res{ res: res{
@ -1520,7 +1520,7 @@ func TestCommandSide_AddSecondFactorLoginPolicy(t *testing.T) {
}, },
}, },
{ {
name: "add factor, ok", name: "add factor totp, ok",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -1530,7 +1530,7 @@ func TestCommandSide_AddSecondFactorLoginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(), org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP), domain.SecondFactorTypeTOTP),
), ),
}, },
), ),
@ -1538,11 +1538,96 @@ func TestCommandSide_AddSecondFactorLoginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
resourceOwner: "org1", resourceOwner: "org1",
}, },
res: res{ res: res{
want: domain.SecondFactorTypeOTP, want: domain.SecondFactorTypeTOTP,
},
},
{
name: "add factor otp email, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPEmail),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPEmail,
resourceOwner: "org1",
},
res: res{
want: domain.SecondFactorTypeOTPEmail,
},
},
{
name: "add factor otp sms, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPSMS),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
resourceOwner: "org1",
},
res: res{
want: domain.SecondFactorTypeOTPSMS,
},
},
{
name: "add factor totp, add otp sms, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeTOTP,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPSMS),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
resourceOwner: "org1",
},
res: res{
want: domain.SecondFactorTypeOTPSMS,
}, },
}, },
} }
@ -1593,7 +1678,7 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
}, },
res: res{ res: res{
err: caos_errs.IsErrorInvalidArgument, err: caos_errs.IsErrorInvalidArgument,
@ -1624,7 +1709,7 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
resourceOwner: "org1", resourceOwner: "org1",
}, },
res: res{ res: res{
@ -1632,7 +1717,7 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
}, },
}, },
{ {
name: "factor removed, not found error", name: "factor totp removed, not found error",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -1640,13 +1725,13 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(), org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorRemovedEvent(context.Background(), org.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeTOTP,
), ),
), ),
), ),
@ -1654,7 +1739,7 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
resourceOwner: "org1", resourceOwner: "org1",
}, },
res: res{ res: res{
@ -1662,7 +1747,7 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
}, },
}, },
{ {
name: "add factor, ok", name: "factor otp email removed, not found error",
fields: fields{ fields: fields{
eventstore: eventstoreExpect( eventstore: eventstoreExpect(
t, t,
@ -1670,7 +1755,67 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(), org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP, domain.SecondFactorTypeOTPEmail,
),
),
eventFromEventPusher(
org.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPEmail,
),
),
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPEmail,
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsNotFound,
},
},
{
name: "factor otp sms removed, not found error",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPSMS,
),
),
eventFromEventPusher(
org.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPSMS,
),
),
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
resourceOwner: "org1",
},
res: res{
err: caos_errs.IsNotFound,
},
},
{
name: "add factor totp, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeTOTP,
), ),
), ),
), ),
@ -1679,7 +1824,7 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
eventFromEventPusher( eventFromEventPusher(
org.NewLoginPolicySecondFactorRemovedEvent(context.Background(), org.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate, &org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTP), domain.SecondFactorTypeTOTP),
), ),
}, },
), ),
@ -1687,7 +1832,77 @@ func TestCommandSide_RemoveSecondFactoroginPolicy(t *testing.T) {
}, },
args: args{ args: args{
ctx: context.Background(), ctx: context.Background(),
factor: domain.SecondFactorTypeOTP, factor: domain.SecondFactorTypeTOTP,
resourceOwner: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "add factor otp email, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPEmail,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPEmail),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPEmail,
resourceOwner: "org1",
},
res: res{
want: &domain.ObjectDetails{
ResourceOwner: "org1",
},
},
},
{
name: "add factor otp sms, ok",
fields: fields{
eventstore: eventstoreExpect(
t,
expectFilter(
eventFromEventPusher(
org.NewLoginPolicySecondFactorAddedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPSMS,
),
),
),
expectPush(
[]*repository.Event{
eventFromEventPusher(
org.NewLoginPolicySecondFactorRemovedEvent(context.Background(),
&org.NewAggregate("org1").Aggregate,
domain.SecondFactorTypeOTPSMS),
),
},
),
),
},
args: args{
ctx: context.Background(),
factor: domain.SecondFactorTypeOTPSMS,
resourceOwner: "org1", resourceOwner: "org1",
}, },
res: res{ res: res{

View File

@ -4,20 +4,14 @@ type SecondFactorType int32
const ( const (
SecondFactorTypeUnspecified SecondFactorType = iota SecondFactorTypeUnspecified SecondFactorType = iota
SecondFactorTypeOTP SecondFactorTypeTOTP
SecondFactorTypeU2F SecondFactorTypeU2F
SecondFactorTypeOTPEmail
SecondFactorTypeOTPSMS
secondFactorCount secondFactorCount
) )
func SecondFactorTypes() []SecondFactorType {
types := make([]SecondFactorType, 0, secondFactorCount-1)
for i := SecondFactorTypeUnspecified + 1; i < secondFactorCount; i++ {
types = append(types, i)
}
return types
}
type MultiFactorType int32 type MultiFactorType int32
const ( const (
@ -27,14 +21,6 @@ const (
multiFactorCount multiFactorCount
) )
func MultiFactorTypes() []MultiFactorType {
types := make([]MultiFactorType, 0, multiFactorCount-1)
for i := MultiFactorTypeUnspecified + 1; i < multiFactorCount; i++ {
types = append(types, i)
}
return types
}
type FactorState int32 type FactorState int32
const ( const (

View File

@ -106,8 +106,12 @@ func secondFactorsToDomain(types []domain.SecondFactorType) []domain.SecondFacto
switch secondfactorType { switch secondfactorType {
case domain.SecondFactorTypeU2F: case domain.SecondFactorTypeU2F:
secondfactors[i] = domain.SecondFactorTypeU2F secondfactors[i] = domain.SecondFactorTypeU2F
case domain.SecondFactorTypeOTP: case domain.SecondFactorTypeTOTP:
secondfactors[i] = domain.SecondFactorTypeOTP secondfactors[i] = domain.SecondFactorTypeTOTP
case domain.SecondFactorTypeOTPEmail:
secondfactors[i] = domain.SecondFactorTypeOTPEmail
case domain.SecondFactorTypeOTPSMS:
secondfactors[i] = domain.SecondFactorTypeOTPSMS
} }
} }
return secondfactors return secondfactors

View File

@ -129,7 +129,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
true, true,
true, true,
true, true,
database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeTOTP},
database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN},
domain.PasswordlessTypeAllowed, domain.PasswordlessTypeAllowed,
true, true,
@ -157,7 +157,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
AllowExternalIDPs: true, AllowExternalIDPs: true,
ForceMFA: true, ForceMFA: true,
ForceMFALocalOnly: true, ForceMFALocalOnly: true,
SecondFactors: database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, SecondFactors: database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeTOTP},
MultiFactors: database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN}, MultiFactors: database.EnumArray[domain.MultiFactorType]{domain.MultiFactorTypeU2FWithPIN},
PasswordlessType: domain.PasswordlessTypeAllowed, PasswordlessType: domain.PasswordlessTypeAllowed,
IsDefault: true, IsDefault: true,
@ -217,7 +217,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
regexp.QuoteMeta(prepareLoginPolicy2FAsStmt), regexp.QuoteMeta(prepareLoginPolicy2FAsStmt),
prepareLoginPolicy2FAsCols, prepareLoginPolicy2FAsCols,
[]driver.Value{ []driver.Value{
database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeTOTP},
}, },
), ),
}, },
@ -225,7 +225,7 @@ func Test_LoginPolicyPrepares(t *testing.T) {
SearchResponse: SearchResponse{ SearchResponse: SearchResponse{
Count: 1, Count: 1,
}, },
Factors: database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeOTP}, Factors: database.EnumArray[domain.SecondFactorType]{domain.SecondFactorTypeTOTP},
}, },
}, },
{ {

View File

@ -115,11 +115,11 @@ func (p *loginPolicyProjection) reducers() []handler.AggregateReducer {
}, },
{ {
Event: org.LoginPolicySecondFactorAddedEventType, Event: org.LoginPolicySecondFactorAddedEventType,
Reduce: p.reduce2FAAdded, Reduce: p.reduceSecondFactorAdded,
}, },
{ {
Event: org.LoginPolicySecondFactorRemovedEventType, Event: org.LoginPolicySecondFactorRemovedEventType,
Reduce: p.reduce2FARemoved, Reduce: p.reduceSecondFactorRemoved,
}, },
{ {
Event: org.OrgRemovedEventType, Event: org.OrgRemovedEventType,
@ -148,11 +148,11 @@ func (p *loginPolicyProjection) reducers() []handler.AggregateReducer {
}, },
{ {
Event: instance.LoginPolicySecondFactorAddedEventType, Event: instance.LoginPolicySecondFactorAddedEventType,
Reduce: p.reduce2FAAdded, Reduce: p.reduceSecondFactorAdded,
}, },
{ {
Event: instance.LoginPolicySecondFactorRemovedEventType, Event: instance.LoginPolicySecondFactorRemovedEventType,
Reduce: p.reduce2FARemoved, Reduce: p.reduceSecondFactorRemoved,
}, },
{ {
Event: instance.InstanceRemovedEventType, Event: instance.InstanceRemovedEventType,
@ -345,7 +345,7 @@ func (p *loginPolicyProjection) reduceLoginPolicyRemoved(event eventstore.Event)
), nil ), nil
} }
func (p *loginPolicyProjection) reduce2FAAdded(event eventstore.Event) (*handler.Statement, error) { func (p *loginPolicyProjection) reduceSecondFactorAdded(event eventstore.Event) (*handler.Statement, error) {
var policyEvent policy.SecondFactorAddedEvent var policyEvent policy.SecondFactorAddedEvent
switch e := event.(type) { switch e := event.(type) {
case *instance.LoginPolicySecondFactorAddedEvent: case *instance.LoginPolicySecondFactorAddedEvent:
@ -370,7 +370,7 @@ func (p *loginPolicyProjection) reduce2FAAdded(event eventstore.Event) (*handler
), nil ), nil
} }
func (p *loginPolicyProjection) reduce2FARemoved(event eventstore.Event) (*handler.Statement, error) { func (p *loginPolicyProjection) reduceSecondFactorRemoved(event eventstore.Event) (*handler.Statement, error) {
var policyEvent policy.SecondFactorRemovedEvent var policyEvent policy.SecondFactorRemovedEvent
switch e := event.(type) { switch e := event.(type) {
case *instance.LoginPolicySecondFactorRemovedEvent: case *instance.LoginPolicySecondFactorRemovedEvent:

View File

@ -310,8 +310,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
}, },
}, },
{ {
name: "org reduce2FAAdded", name: "org reduceSecondFactorAdded",
reduce: (&loginPolicyProjection{}).reduce2FAAdded, reduce: (&loginPolicyProjection{}).reduceSecondFactorAdded,
args: args{ args: args{
event: getEvent(testEvent( event: getEvent(testEvent(
repository.EventType(org.LoginPolicySecondFactorAddedEventType), repository.EventType(org.LoginPolicySecondFactorAddedEventType),
@ -342,8 +342,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
}, },
}, },
{ {
name: "org reduce2FARemoved", name: "org reduceSecondFactorRemoved",
reduce: (&loginPolicyProjection{}).reduce2FARemoved, reduce: (&loginPolicyProjection{}).reduceSecondFactorRemoved,
args: args{ args: args{
event: getEvent(testEvent( event: getEvent(testEvent(
repository.EventType(org.LoginPolicySecondFactorRemovedEventType), repository.EventType(org.LoginPolicySecondFactorRemovedEventType),
@ -558,8 +558,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
}, },
}, },
{ {
name: "instance reduce2FAAdded", name: "instance reduceSecondFactorAdded u2f",
reduce: (&loginPolicyProjection{}).reduce2FAAdded, reduce: (&loginPolicyProjection{}).reduceSecondFactorAdded,
args: args{ args: args{
event: getEvent(testEvent( event: getEvent(testEvent(
repository.EventType(instance.LoginPolicySecondFactorAddedEventType), repository.EventType(instance.LoginPolicySecondFactorAddedEventType),
@ -590,8 +590,8 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
}, },
}, },
{ {
name: "instance reduce2FARemoved", name: "instance reduceSecondFactorRemoved u2f",
reduce: (&loginPolicyProjection{}).reduce2FARemoved, reduce: (&loginPolicyProjection{}).reduceSecondFactorRemoved,
args: args{ args: args{
event: getEvent(testEvent( event: getEvent(testEvent(
repository.EventType(instance.LoginPolicySecondFactorRemovedEventType), repository.EventType(instance.LoginPolicySecondFactorRemovedEventType),
@ -621,6 +621,70 @@ func TestLoginPolicyProjection_reduces(t *testing.T) {
}, },
}, },
}, },
{
name: "instance reduceSecondFactorAdded otp email",
reduce: (&loginPolicyProjection{}).reduceSecondFactorAdded,
args: args{
event: getEvent(testEvent(
repository.EventType(instance.LoginPolicySecondFactorAddedEventType),
instance.AggregateType,
[]byte(`{
"mfaType": 3
}`),
), instance.SecondFactorAddedEventMapper),
},
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.login_policies5 SET (change_date, sequence, second_factors) = ($1, $2, array_append(second_factors, $3)) WHERE (aggregate_id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SecondFactorTypeOTPEmail,
"agg-id",
"instance-id",
},
},
},
},
},
},
{
name: "instance reduceSecondFactorRemoved otp email",
reduce: (&loginPolicyProjection{}).reduceSecondFactorRemoved,
args: args{
event: getEvent(testEvent(
repository.EventType(instance.LoginPolicySecondFactorRemovedEventType),
instance.AggregateType,
[]byte(`{
"mfaType": 3
}`),
), instance.SecondFactorRemovedEventMapper),
},
want: wantReduce{
aggregateType: eventstore.AggregateType("instance"),
sequence: 15,
previousSequence: 10,
executer: &testExecuter{
executions: []execution{
{
expectedStmt: "UPDATE projections.login_policies5 SET (change_date, sequence, second_factors) = ($1, $2, array_remove(second_factors, $3)) WHERE (aggregate_id = $4) AND (instance_id = $5)",
expectedArgs: []interface{}{
anyArg{},
uint64(15),
domain.SecondFactorTypeOTPEmail,
"agg-id",
"instance-id",
},
},
},
},
},
},
{ {
name: "org.reduceOwnerRemoved", name: "org.reduceOwnerRemoved",
reduce: (&loginPolicyProjection{}).reduceOwnerRemoved, reduce: (&loginPolicyProjection{}).reduceOwnerRemoved,

View File

@ -156,7 +156,7 @@ func (u *UserView) MFATypesSetupPossible(level domain.MFALevel, policy *domain.L
if policy.HasSecondFactors() { if policy.HasSecondFactors() {
for _, mfaType := range policy.SecondFactors { for _, mfaType := range policy.SecondFactors {
switch mfaType { switch mfaType {
case domain.SecondFactorTypeOTP: case domain.SecondFactorTypeTOTP:
if u.OTPState != MFAStateReady { if u.OTPState != MFAStateReady {
types = append(types, domain.MFATypeOTP) types = append(types, domain.MFATypeOTP)
} }
@ -181,7 +181,7 @@ func (u *UserView) MFATypesAllowed(level domain.MFALevel, policy *domain.LoginPo
if policy.HasSecondFactors() { if policy.HasSecondFactors() {
for _, mfaType := range policy.SecondFactors { for _, mfaType := range policy.SecondFactors {
switch mfaType { switch mfaType {
case domain.SecondFactorTypeOTP: case domain.SecondFactorTypeTOTP:
if u.OTPState == MFAStateReady { if u.OTPState == MFAStateReady {
types = append(types, domain.MFATypeOTP) types = append(types, domain.MFATypeOTP)
} }

View File

@ -248,8 +248,11 @@ message LoginPolicy {
enum SecondFactorType { enum SecondFactorType {
SECOND_FACTOR_TYPE_UNSPECIFIED = 0; SECOND_FACTOR_TYPE_UNSPECIFIED = 0;
// SECOND_FACTOR_TYPE_OTP is the type for TOTP
SECOND_FACTOR_TYPE_OTP = 1; SECOND_FACTOR_TYPE_OTP = 1;
SECOND_FACTOR_TYPE_U2F = 2; SECOND_FACTOR_TYPE_U2F = 2;
SECOND_FACTOR_TYPE_OTP_EMAIL = 3;
SECOND_FACTOR_TYPE_OTP_SMS = 4;
} }
enum MultiFactorType { enum MultiFactorType {

View File

@ -113,8 +113,11 @@ message LoginSettings {
enum SecondFactorType { enum SecondFactorType {
SECOND_FACTOR_TYPE_UNSPECIFIED = 0; SECOND_FACTOR_TYPE_UNSPECIFIED = 0;
// This is the type for TOTP
SECOND_FACTOR_TYPE_OTP = 1; SECOND_FACTOR_TYPE_OTP = 1;
SECOND_FACTOR_TYPE_U2F = 2; SECOND_FACTOR_TYPE_U2F = 2;
SECOND_FACTOR_TYPE_OTP_EMAIL = 3;
SECOND_FACTOR_TYPE_OTP_SMS = 4;
} }
enum MultiFactorType { enum MultiFactorType {