Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
301747e
first lambda type
wied03 Nov 21, 2025
ada093b
reduce client blast radius (#184)
wied03 Nov 25, 2025
4c212f8
MFA lambda configuration (#185)
hjaret Dec 3, 2025
0a329b6
Merge remote-tracking branch 'origin/develop' into feature/ENG-1111/m…
wied03 Dec 8, 2025
5a2e974
Merge wied03/ENG-3602/mfa-lambda-invocation (#186)
wied03 Dec 8, 2025
c05482d
Merge wied03/ENG-3603/mfa-retrieve-status-post (#187)
wied03 Dec 9, 2025
9ef12bc
missing client stuff
wied03 Dec 9, 2025
8bcae28
Merge branch 'feature/ENG-1111/mfa-lambda' into wied03/ENG-3606/suspi…
wied03 Dec 9, 2025
b02416d
Merge pull request #188 from FusionAuth/wied03/ENG-3606/suspicious_login
wied03 Dec 9, 2025
3d05b53
Merge wied03/ENG-3608/mfa-change-password (#190)
wied03 Dec 10, 2025
25d3cf3
Merge remote-tracking branch 'origin/develop' into feature/ENG-1111/m…
wied03 Dec 10, 2025
3fb84ea
naming advice
wied03 Dec 10, 2025
d108461
mfa lambda
hjaret Dec 12, 2025
f19a4ad
Change function name and parameters
wied03 Dec 16, 2025
be84a7e
Change function name and parameters
wied03 Dec 16, 2025
0da5fd1
PR feedback - lambda classses - new package and names
wied03 Dec 16, 2025
43bb771
keep value as mfaTrust within lambda
wied03 Dec 16, 2025
6cf03f2
pass raw JWT all the way in
wied03 Dec 16, 2025
f586e84
Lambda signature - registration out of context, action and app in
wied03 Dec 17, 2025
7bcce62
Change context.encodedJWT to context.accessToken
wied03 Dec 17, 2025
4e3497c
rename token to accessToken on status API
wied03 Dec 17, 2025
286fbe2
Merge remote-tracking branch 'origin/develop' into feature/ENG-1111/m…
wied03 Dec 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/main/api/checkChangePasswordUsingIdAndIPAddress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"uri": "/api/user/change-password",
"comments": [
"Check to see if the user must obtain a Trust Token Id in order to complete a change password request.",
"When a user has enabled Two-Factor authentication, before you are allowed to use the Change Password API to change",
"your password, you must obtain a Trust Token by completing a Two-Factor Step-Up authentication.",
"",
"An HTTP status code of 400 with a general error code of [TrustTokenRequired] indicates that a Trust Token is required to make a POST request to this API."
],
"method": "get",
"methodName": "checkChangePasswordUsingIdAndIPAddress",
"successResponse": "Void",
"errorResponse": "Errors",
"anonymous": true,
"params": [
{
"name": "changePasswordId",
"comments": [
"The change password Id used to find the user. This value is generated by FusionAuth once the change password workflow has been initiated."
],
"type": "urlSegment",
"javaType": "String"
},
{
"name": "ipAddress",
"comments": [
"(Optional) IP address of the user changing their password. This is used for MFA risk assessment."
],
"type": "urlParameter",
"parameterName": "ipAddress",
"javaType": "String"
}
]
}
35 changes: 35 additions & 0 deletions src/main/api/checkChangePasswordUsingJWTAndIPAddress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"uri": "/api/user/change-password",
"comments": [
"Check to see if the user must obtain a Trust Token Id in order to complete a change password request.",
"When a user has enabled Two-Factor authentication, before you are allowed to use the Change Password API to change",
"your password, you must obtain a Trust Token by completing a Two-Factor Step-Up authentication.",
"",
"An HTTP status code of 400 with a general error code of [TrustTokenRequired] indicates that a Trust Token is required to make a POST request to this API."
],
"method": "get",
"methodName": "checkChangePasswordUsingJWTAndIPAddress",
"successResponse": "Void",
"errorResponse": "Errors",
"anonymous": true,
"authorization": "\"Bearer \" + encodedJWT",
"params": [
{
"name": "encodedJWT",
"comments": [
"The encoded JWT (access token)."
],
"type": "notUsed",
"javaType": "String"
},
{
"name": "ipAddress",
"comments": [
"(Optional) IP address of the user changing their password. This is used for MFA risk assessment."
],
"type": "urlParameter",
"parameterName": "ipAddress",
"javaType": "String"
}
]
}
34 changes: 34 additions & 0 deletions src/main/api/checkChangePasswordUsingLoginIdAndIPAddress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"uri": "/api/user/change-password",
"comments": [
"Check to see if the user must obtain a Trust Request Id in order to complete a change password request.",
"When a user has enabled Two-Factor authentication, before you are allowed to use the Change Password API to change",
"your password, you must obtain a Trust Request Id by completing a Two-Factor Step-Up authentication.",
"",
"An HTTP status code of 400 with a general error code of [TrustTokenRequired] indicates that a Trust Token is required to make a POST request to this API."
],
"method": "get",
"methodName": "checkChangePasswordUsingLoginIdAndIPAddress",
"successResponse": "Void",
"errorResponse": "Errors",
"params": [
{
"name": "loginId",
"comments": [
"The loginId (email or username) of the User that you intend to change the password for."
],
"type": "urlParameter",
"parameterName": "loginId",
"javaType": "String"
},
{
"name": "ipAddress",
"comments": [
"(Optional) IP address of the user changing their password. This is used for MFA risk assessment."
],
"type": "urlParameter",
"parameterName": "ipAddress",
"javaType": "String"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"uri": "/api/user/change-password",
"comments": [
"Check to see if the user must obtain a Trust Request Id in order to complete a change password request.",
"When a user has enabled Two-Factor authentication, before you are allowed to use the Change Password API to change",
"your password, you must obtain a Trust Request Id by completing a Two-Factor Step-Up authentication.",
"",
"An HTTP status code of 400 with a general error code of [TrustTokenRequired] indicates that a Trust Token is required to make a POST request to this API."
],
"method": "get",
"methodName": "checkChangePasswordUsingLoginIdAndLoginIdTypesAndIPAddress",
"successResponse": "Void",
"errorResponse": "Errors",
"params": [
{
"name": "loginId",
"comments": [
"The loginId of the User that you intend to change the password for."
],
"type": "urlParameter",
"parameterName": "loginId",
"javaType": "String"
},
{
"name": "loginIdTypes",
"comments": [
"The identity types that FusionAuth will compare the loginId to."
],
"type": "urlParameter",
"parameterName": "loginIdTypes",
"javaType": "List<String>"
},
{
"name": "ipAddress",
"comments": [
"(Optional) IP address of the user changing their password. This is used for MFA risk assessment."
],
"type": "urlParameter",
"parameterName": "ipAddress",
"javaType": "String"
}
]
}
24 changes: 24 additions & 0 deletions src/main/api/retrieveTwoFactorStatusWithRequest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"uri": "/api/two-factor/status",
"comments": [
"Retrieve a user's two-factor status.",
"",
"This can be used to see if a user will need to complete a two-factor challenge to complete a login,",
"and optionally identify the state of the two-factor trust across various applications. This operation",
"provides more payload options than retrieveTwoFactorStatus."
],
"method": "post",
"methodName": "retrieveTwoFactorStatusWithRequest",
"successResponse": "TwoFactorStatusResponse",
"errorResponse": "Errors",
"params": [
{
"name": "request",
"comments": [
"The request object that contains all the information used to check the status."
],
"type": "body",
"javaType": "TwoFactorStatusRequest"
}
]
}
1 change: 1 addition & 0 deletions src/main/client/java.client.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ import io.fusionauth.domain.api.twoFactor.TwoFactorSendRequest;
import io.fusionauth.domain.api.twoFactor.TwoFactorStartRequest;
import io.fusionauth.domain.api.twoFactor.TwoFactorStartResponse;
import io.fusionauth.domain.api.twoFactor.TwoFactorStatusResponse;
import io.fusionauth.domain.api.twoFactor.TwoFactorStatusRequest;
import io.fusionauth.domain.api.user.ActionRequest;
import io.fusionauth.domain.api.user.ActionResponse;
import io.fusionauth.domain.api.user.ChangePasswordRequest;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"idTokenPopulateId" : {
"type" : "UUID"
},
"multiFactorRequirementId" : {
"type" : "UUID"
},
"samlv2PopulateId" : {
"type" : "UUID"
},
Expand Down
3 changes: 3 additions & 0 deletions src/main/domain/io.fusionauth.domain.LambdaType.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,8 @@
}, {
"name" : "LoginValidation",
"args" : [ "validate" ]
}, {
"name" : "MFARequirement",
"args" : [ "checkRequired" ]
} ]
}
6 changes: 6 additions & 0 deletions src/main/domain/io.fusionauth.domain.MultiFactorAction.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"packageName" : "io.fusionauth.domain",
"type" : "MultiFactorAction",
"description" : "/**\n * Communicate various actions/contexts in which multi-factor authentication can be used.\n */\n",
"enum" : [ "changePassword", "login", "stepUp" ]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"loginValidationId" : {
"type" : "UUID"
},
"multiFactorRequirementId" : {
"type" : "UUID"
},
"scimEnterpriseUserRequestConverterId" : {
"type" : "UUID"
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"packageName" : "io.fusionauth.domain.api.twoFactor",
"type" : "TwoFactorStatusRequest",
"description" : "/**\n * Check the status of two-factor authentication for a user, with more options than on a GET request.\n */\n",
"extends" : [ {
"type" : "BaseEventRequest"
} ],
"fields" : {
"userId" : {
"type" : "UUID"
},
"accessToken" : {
"type" : "String"
},
"action" : {
"type" : "MultiFactorAction"
},
"applicationId" : {
"type" : "UUID"
},
"twoFactorTrustId" : {
"type" : "String"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"packageName" : "io.fusionauth.domain.lambda.parameters.mfa",
"type" : "Context",
"description" : "/**\n * Represents the inbound lambda parameter 'context' for MFA Required lambdas.\n */\n",
"fields" : {
"accessToken" : {
"type" : "String"
},
"action" : {
"type" : "MultiFactorAction"
},
"application" : {
"type" : "Application"
},
"authenticationThreats" : {
"type" : "Set",
"typeArguments" : [ {
"type" : "AuthenticationThreats"
} ]
},
"eventInfo" : {
"type" : "EventInfo"
},
"mfaTrust" : {
"type" : "Trust"
},
"policies" : {
"type" : "Policies"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"packageName" : "io.fusionauth.domain.lambda.parameters.mfa",
"type" : "Policies",
"description" : "/**\n * Represents the inbound lambda parameter 'policies' for MFA Required lambdas.\n */\n",
"fields" : {
"applicationLoginPolicy" : {
"type" : "MultiFactorLoginPolicy"
},
"applicationMultiFactorTrustPolicy" : {
"type" : "ApplicationMultiFactorTrustPolicy"
},
"tenantLoginPolicy" : {
"type" : "MultiFactorLoginPolicy"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"packageName" : "io.fusionauth.domain.lambda.parameters.mfa",
"type" : "RequiredLambdaResult",
"description" : "/**\n * Represents the inbound lambda parameter 'result' for MFA Required lambdas.\n */\n",
"fields" : {
"required" : {
"type" : "boolean"
},
"sendSuspiciousLoginEvent" : {
"type" : "boolean"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"packageName" : "io.fusionauth.domain.lambda.parameters.mfa",
"type" : "StartInstant",
"fields" : {
"applications" : {
"type" : "Map",
"typeArguments" : [ {
"type" : "UUID"
}, {
"type" : "ZonedDateTime"
} ]
},
"tenant" : {
"type" : "ZonedDateTime"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"packageName" : "io.fusionauth.domain.lambda.parameters.mfa",
"type" : "Trust",
"description" : "/**\n * Represents the inbound lambda parameter 'mfaTrust' inside the 'context' parameter for MFA Required lambdas.\n */\n",
"fields" : {
"applicationId" : {
"type" : "UUID"
},
"attributes" : {
"type" : "Map",
"typeArguments" : [ {
"type" : "String"
}, {
"type" : "String"
} ]
},
"expirationInstant" : {
"type" : "ZonedDateTime"
},
"id" : {
"type" : "String"
},
"insertInstant" : {
"type" : "ZonedDateTime"
},
"startInstants" : {
"type" : "StartInstant"
},
"state" : {
"type" : "Map",
"typeArguments" : [ {
"type" : "String"
}, {
"type" : "Object"
} ]
},
"tenantId" : {
"type" : "UUID"
},
"userId" : {
"type" : "UUID"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
"licensed" : {
"type" : "boolean"
},
"multiFactorLambdas" : {
"type" : "ReactorFeatureStatus"
},
"scimServer" : {
"type" : "ReactorFeatureStatus"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"className" : "java.util.UUID",
"type" : "UUID"
},
"multiFactorRequirementId" : {
"className" : "java.util.UUID",
"type" : "UUID"
},
"samlv2PopulateId" : {
"className" : "java.util.UUID",
"type" : "UUID"
Expand Down
Loading