Skip to content

Commit bed2848

Browse files
author
FusionAuth Automation
committed
Sync from monorepo 8ac7a9897077
1 parent bbba628 commit bed2848

17 files changed

Lines changed: 525 additions & 27 deletions

src/main/java/io/fusionauth/domain/AuthenticationThreats.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2021-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,5 +19,14 @@
1919
* @author Brett Pontarelli
2020
*/
2121
public enum AuthenticationThreats {
22-
ImpossibleTravel
22+
BotDetected,
23+
BlocklistedIp,
24+
DormantAccount,
25+
DormantPassword,
26+
ImpossibleTravel,
27+
RecentIdentityChange,
28+
RecentPasswordChange,
29+
SuspiciousUserAgent,
30+
UnrecognizedDevice,
31+
UntrustedDevice
2332
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2026, FusionAuth, All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the License.
15+
*/
16+
package io.fusionauth.domain;
17+
18+
import java.util.Objects;
19+
20+
/**
21+
* Flags to enable or disable specific risk signals that contribute to the composite client risk calculation.
22+
*/
23+
public class ClientRiskConfiguration extends Enableable implements Buildable<ClientRiskConfiguration> {
24+
25+
public boolean blocklistedIp = true;
26+
27+
public boolean botDetected = true;
28+
29+
public boolean dormantAccount = true;
30+
31+
public boolean dormantPassword = true;
32+
33+
public boolean impossibleTravel = true;
34+
35+
public boolean recentIdentityChange = true;
36+
37+
public boolean recentPasswordChange = true;
38+
39+
public boolean suspiciousUserAgent = true;
40+
41+
public boolean unrecognizedDevice = true;
42+
43+
public boolean untrustedDevice = true;
44+
45+
public ClientRiskConfiguration() {
46+
}
47+
48+
public ClientRiskConfiguration(ClientRiskConfiguration other) {
49+
this.enabled = other.enabled;
50+
this.botDetected = other.botDetected;
51+
this.dormantAccount = other.dormantAccount;
52+
this.impossibleTravel = other.impossibleTravel;
53+
this.blocklistedIp = other.blocklistedIp;
54+
this.unrecognizedDevice = other.unrecognizedDevice;
55+
this.recentIdentityChange = other.recentIdentityChange;
56+
this.dormantPassword = other.dormantPassword;
57+
this.recentPasswordChange = other.recentPasswordChange;
58+
this.untrustedDevice = other.untrustedDevice;
59+
this.suspiciousUserAgent = other.suspiciousUserAgent;
60+
}
61+
62+
@Override
63+
public boolean equals(Object o) {
64+
if (this == o) {
65+
return true;
66+
}
67+
if (!(o instanceof ClientRiskConfiguration)) {
68+
return false;
69+
}
70+
ClientRiskConfiguration that = (ClientRiskConfiguration) o;
71+
return enabled == that.enabled &&
72+
blocklistedIp == that.blocklistedIp &&
73+
botDetected == that.botDetected &&
74+
dormantAccount == that.dormantAccount &&
75+
dormantPassword == that.dormantPassword &&
76+
impossibleTravel == that.impossibleTravel &&
77+
recentIdentityChange == that.recentIdentityChange &&
78+
recentPasswordChange == that.recentPasswordChange &&
79+
suspiciousUserAgent == that.suspiciousUserAgent &&
80+
unrecognizedDevice == that.unrecognizedDevice &&
81+
untrustedDevice == that.untrustedDevice;
82+
}
83+
84+
@Override
85+
public int hashCode() {
86+
return Objects.hash(enabled, blocklistedIp, botDetected, dormantAccount, dormantPassword, impossibleTravel, recentIdentityChange,
87+
recentPasswordChange, suspiciousUserAgent, unrecognizedDevice, untrustedDevice);
88+
}
89+
90+
@Override
91+
public String toString() {
92+
return com.inversoft.json.ToString.toString(this);
93+
}
94+
}

src/main/java/io/fusionauth/domain/MultiFactorLoginPolicy.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,26 @@
11
/*
2-
* Copyright (c) 2022, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2022-2026, FusionAuth, All Rights Reserved
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing,
11+
* software distributed under the License is distributed on an
12+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13+
* either express or implied. See the License for the specific
14+
* language governing permissions and limitations under the License.
315
*/
416
package io.fusionauth.domain;
517

618
/**
719
* @author Daniel DeGroff
820
*/
921
public enum MultiFactorLoginPolicy {
22+
ChallengeOnHighRisk,
23+
ChallengeOnMediumRisk,
1024
Disabled,
1125
Enabled,
1226
Required

src/main/java/io/fusionauth/domain/Tenant.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ public class Tenant implements Buildable<Tenant> {
4747

4848
public TenantCaptchaConfiguration captchaConfiguration = new TenantCaptchaConfiguration();
4949

50+
public ClientRiskConfiguration clientRiskConfiguration = new ClientRiskConfiguration();
51+
5052
public boolean configured;
5153

5254
public List<ConnectorPolicy> connectorPolicies = new ArrayList<>();
@@ -133,6 +135,7 @@ public Tenant() {
133135
public Tenant(Tenant other) {
134136
this.baseURL = other.baseURL;
135137
this.captchaConfiguration = new TenantCaptchaConfiguration(other.captchaConfiguration);
138+
this.clientRiskConfiguration = new ClientRiskConfiguration(other.clientRiskConfiguration);
136139
this.configured = other.configured;
137140
this.connectorPolicies.addAll(other.connectorPolicies.stream().map(ConnectorPolicy::new).collect(Collectors.toList()));
138141
this.data.putAll(other.data);
@@ -184,6 +187,7 @@ public boolean equals(Object o) {
184187
httpSessionMaxInactiveInterval == tenant.httpSessionMaxInactiveInterval &&
185188
Objects.equals(baseURL, tenant.baseURL) &&
186189
Objects.equals(captchaConfiguration, tenant.captchaConfiguration) &&
190+
Objects.equals(clientRiskConfiguration, tenant.clientRiskConfiguration) &&
187191
Objects.equals(connectorPolicies, tenant.connectorPolicies) &&
188192
Objects.equals(data, tenant.data) &&
189193
Objects.equals(emailConfiguration, tenant.emailConfiguration) &&
@@ -228,6 +232,7 @@ public ConnectorPolicy getPolicyByConnectorId(UUID connectorId) {
228232
public int hashCode() {
229233
return Objects.hash(baseURL,
230234
captchaConfiguration,
235+
clientRiskConfiguration,
231236
configured,
232237
connectorPolicies,
233238
data,

src/main/java/io/fusionauth/domain/TenantMultiFactorConfiguration.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
public class TenantMultiFactorConfiguration implements Buildable<TenantMultiFactorConfiguration> {
3030
public MultiFactorAuthenticatorMethod authenticator = new MultiFactorAuthenticatorMethod().with(mfa -> mfa.enabled = true);
3131

32+
public boolean debug;
33+
3234
public MultiFactorEmailMethod email = new MultiFactorEmailMethod();
3335

3436
public MultiFactorLoginPolicy loginPolicy = MultiFactorLoginPolicy.Enabled;
@@ -43,6 +45,7 @@ public TenantMultiFactorConfiguration() {
4345

4446
public TenantMultiFactorConfiguration(TenantMultiFactorConfiguration other) {
4547
this.authenticator = new MultiFactorAuthenticatorMethod(other.authenticator);
48+
this.debug = other.debug;
4649
this.email = new MultiFactorEmailMethod(other.email);
4750
this.loginPolicy = other.loginPolicy;
4851
this.sms = new MultiFactorSMSMethod(other.sms);
@@ -67,6 +70,7 @@ public boolean equals(Object o) {
6770
}
6871
TenantMultiFactorConfiguration that = (TenantMultiFactorConfiguration) o;
6972
return Objects.equals(authenticator, that.authenticator) &&
73+
debug == that.debug &&
7074
Objects.equals(email, that.email) &&
7175
loginPolicy == that.loginPolicy &&
7276
Objects.equals(sms, that.sms) &&
@@ -75,7 +79,7 @@ public boolean equals(Object o) {
7579

7680
@Override
7781
public int hashCode() {
78-
return Objects.hash(authenticator, email, loginPolicy, sms, voice);
82+
return Objects.hash(authenticator, debug, email, loginPolicy, sms, voice);
7983
}
8084

8185
@Override

src/main/java/io/fusionauth/domain/TwoFactorMethod.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ public class TwoFactorMethod implements Buildable<TwoFactorMethod> {
3737

3838
public static final int MaximumNameLength = 256;
3939

40+
/**
41+
* Method which authenticates using a recovery code that was saved during registration.
42+
*/
43+
public static final String RecoveryCode = "recoveryCode";
44+
4045
/**
4146
* Method which authenticates using a code sent to a phone via SMS or voice.
4247
*/

src/main/java/io/fusionauth/domain/api/BaseLoginRequest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018-2023, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2018-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,8 @@
2626
public class BaseLoginRequest extends BaseEventRequest {
2727
public UUID applicationId;
2828

29+
public Double botDetectionScore;
30+
2931
@Deprecated
3032
public String ipAddress;
3133

src/main/java/io/fusionauth/domain/event/EventType.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018-2025, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2018-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -103,6 +103,8 @@ public enum EventType {
103103

104104
UserLoginSuspicious("user.login.suspicious"),
105105

106+
UserTwoFactorChallenge("user.two-factor.challenge"),
107+
106108
UserPasswordBreach("user.password.breach"),
107109

108110
UserPasswordResetSend("user.password.reset.send"),
@@ -141,7 +143,11 @@ public enum EventType {
141143

142144
UserIdentityVerified("user.identity.verified"),
143145

144-
UserIdentityUpdate("user.identity.update");
146+
UserIdentityUpdate("user.identity.update"),
147+
148+
UserTwoFactorFailedAttempt("user.two-factor.failed-attempt"),
149+
150+
UserTwoFactorSuccess("user.two-factor.success");
145151

146152
private static final Map<String, EventType> nameMap = new HashMap<>(EventType.values().length);
147153

@@ -205,8 +211,11 @@ public static List<EventType> allTypes() {
205211
EventType.UserRegistrationUpdate,
206212
EventType.UserRegistrationUpdateComplete,
207213
EventType.UserRegistrationVerified,
214+
EventType.UserTwoFactorChallenge,
215+
EventType.UserTwoFactorFailedAttempt,
208216
EventType.UserTwoFactorMethodAdd,
209217
EventType.UserTwoFactorMethodRemove,
218+
EventType.UserTwoFactorSuccess,
210219
EventType.UserUpdate,
211220
EventType.UserUpdateComplete
212221
);

src/main/java/io/fusionauth/domain/event/UserLoginSuspiciousEvent.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2024, FusionAuth, All Rights Reserved
2+
* Copyright (c) 2021-2026, FusionAuth, All Rights Reserved
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,10 +15,12 @@
1515
*/
1616
package io.fusionauth.domain.event;
1717

18-
import java.util.HashSet;
18+
import java.util.Comparator;
19+
import java.util.LinkedHashSet;
1920
import java.util.Objects;
2021
import java.util.Set;
2122
import java.util.UUID;
23+
import java.util.stream.Collectors;
2224

2325
import com.inversoft.json.JacksonConstructor;
2426
import io.fusionauth.domain.AuthenticationThreats;
@@ -32,7 +34,7 @@
3234
* @author Daniel DeGroff
3335
*/
3436
public class UserLoginSuspiciousEvent extends UserLoginSuccessEvent {
35-
public Set<AuthenticationThreats> threatsDetected = new HashSet<>();
37+
public Set<AuthenticationThreats> threatsDetected = new LinkedHashSet<>();
3638

3739
@JacksonConstructor
3840
public UserLoginSuspiciousEvent() {
@@ -41,14 +43,17 @@ public UserLoginSuspiciousEvent() {
4143
public UserLoginSuspiciousEvent(EventInfo info, UUID applicationId, String authenticationType, BaseIdentityProvider<?> identityProvider,
4244
User user, Set<AuthenticationThreats> threatsDetected) {
4345
super(info, applicationId, authenticationType, identityProvider, user);
44-
this.threatsDetected = threatsDetected;
45-
46+
this.threatsDetected = threatsDetected.stream()
47+
.sorted(Comparator.comparing(Enum::name))
48+
.collect(Collectors.toCollection(LinkedHashSet::new));
4649
}
4750

4851
public UserLoginSuspiciousEvent(EventInfo info, UUID applicationId, UUID connectorId, String authenticationType, User user,
4952
Set<AuthenticationThreats> threatsDetected) {
5053
super(info, applicationId, connectorId, authenticationType, user);
51-
this.threatsDetected = threatsDetected;
54+
this.threatsDetected = threatsDetected.stream()
55+
.sorted(Comparator.comparing(Enum::name))
56+
.collect(Collectors.toCollection(LinkedHashSet::new));
5257
}
5358

5459
@Override

0 commit comments

Comments
 (0)