MFA for OAuth Clients

Centrify provides the ability to define challenge policies which can be used to perform multi-factor authentication (MFA) on behalf of a designated user (e.g. so OAuth clients can provide MFA).

This page describes the API workflows to programmatically create a challenge policy and use it in enabling MFA in an OAuth client.

Before continuing, ensure you are familiar with:

Creating a Challenge Policy

Step 1. Get the Roles

The first step is to get all roles by invoking the /RedRock/Query endpoint as shown here:

POST /RedRock/query

{  
   "Script":"Select *, COALESCE(Name, ID) AS DisplayName from Role ORDER BY DisplayName COLLATE NOCASE",
   "Args":{  
      "PageNumber":1,
      "PageSize":100000,
      "Limit":100000,
      "SortBy":"",
      "direction":"False",
      "Caching":-1
   }
}

The Results array contains information about each policy:

{  
   "success":true,
   "Result":{  
      "IsAggregate":false,
      "Count":57,
      "Columns":[  
         {  
            "Name":"Description",
            "IsHidden":false,
            "DDName":"Description",
            "Title":"Description",
            "DDTitle":"Description",
            "Description":null,
            "Type":12,
            "Format":null,
            "Width":0,
            "TableKey":"NotAKey",
            "ForeignKey":null,
            "TableName":"Role"
         },
         ...
      ],
      "FullCount":57,
      "Results":[  
         {  
            "Entities":[  
               {  
                  "Type":"Role",
                  "Key":"12332112_cea1_4fb6_80d7_de847c152d82",
                  "IsForeignKey":false
               }
            ],
            "Row":{  
               "ReadOnly":false,
               "Description":null,
               "DisplayName":"App Gateway Devs",
               "DirectoryServiceUuid":"ABC12345-6CE8-465F-AB03-65766D33B05E",
               "RoleType":"PrincipalList",
               "_MatchFilter":null,
               "Name":"App Gateway Devs",
               "ID":"18240b41_cea1_4fb6_80d7_de847c152d82"
            }
         },
         ...
      ],
      "ReturnID":""
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 2. Determine if Cloud Mobile GP is being used.

The next step is determine if cloud mobile GP is enabled by invoking the /policy/GetUsingCloudMobileGP:

POST /policy/GetUsingCloudMobileGP

The useCloudGP field indicates whether cloud GP is enabled:

{  
   "success":true,
   "Result":{  
      "useCloudGP":true,
      "useCloudCA":false,
      "refreshInterval":15,
      "gpUpdateInterval":300,
      "activeDirectoryCA":"CA-CA1.centrify.com\\GLOBAL-CA2",
      "cloudOuManagement":true,
      "hasProxy":true,
      "boundMobileForest":"centrify.com",
      "hideMobilePolicyForAD":true
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 3. Get the Plinks

Get information about each policy by invoking the /policy/getniceplinks endpoint:

POST /policy/getniceplinks

{  
   "Args":{  
      "PageNumber":1,
      "PageSize":100000,
      "Limit":100000,
      "SortBy":"",
      "direction":"False",
      "Caching":-1
   }
}

The Results array contains information about each policy:

{  
   "success":true,
   "Result":{  
      "Columns":[  
         {  
            "Name":"Params",
            "IsHidden":false,
            "DDName":null,
            "Title":"Params",
            "DDTitle":null,
            "Description":null,
            "Type":16,
            "Format":null,
            "Width":0,
            "TableKey":null,
            "ForeignKey":null,
            "TableName":null
         },
         ...
      ],
      "RevStamp":"636537274890000000",
      "Count":28,
      "Results":[  
         {  
            "Entities":[  
               {  
                  "Type":"PolicyLink",
                  "Key":"/Policy/Default Policy",
                  "IsForeignKey":false
               }
            ],
            "Row":{  
               "Params":[  

               ],
               "ID":"/Policy/Default Policy",
               "EnableCompliant":true,
               "I18NDescriptionTag":"_I18N_DefaultGlobalPolicyDescriptionTag",
               "Description":"DO NOT DISABLE Login MFA IN THIS POLICY for unknown devices.",
               "LinkType":"Global",
               "PolicySet":"/Policy/Default Policy"
            }
         },
         ...
      ],
      "FullCount":28,
      "ReturnID":"",
      "IsAggregate":false
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 4. Get the Policy Block

Using the policies returned in the previous response, determine the policy that you want to add a challenge policy to, and then invoke the /Policy/getpolicyblock endpoint, passing the ID via the name field in the body:

POST /policy/getpolicyblock

{  
   "name":"/Policy/Default Policy"
}

The response contains information about the policy:

{  
   "success":true,
   "Result":{  
      "Description":"DO NOT DISABLE Login MFA IN THIS POLICY for unknown devices.",
      "PolicyModifiers":[  

      ],
      "Settings":{  
         "/Mobile/Software/Policies/Centrify/Common/AllowNotificationOnMutipleDevices":true,
         "/Core/Authentication/IwaSatisfiesAllMechs":false,
         "/Core/Authentication/SecurityQuestionAnswerMinLength":3,
         "/Core/Authentication/IwaSetKnownEndpoint":true,
         "/Core/MfaRestrictions/BlockMobileMechsOnMobileLogin":false,
         "/Core/PasswordReset/AccountUnlockAuthProfile":"e4eeeeee-2e9e-4567-b9e2-a568360c8eb7",
         "/Core/Authentication/ZsoSatisfiesAllMechs":false,
         "/Core/Authentication/AdminSecurityQuestionsPerUser":0,
         "/Core/Security/CDS/ExternalMFA/ShowQRCodeForSelfService":true,
         "/Core/Authentication/ChallengeDefinitionId":"0d799995-ca79-43df-9355-fdf12394965b",
         "/Core/Authentication/ZsoSetKnownEndpoint":true,
         "PasswordResetEnabled":true,
         "/Mobile/Software/Policies/Centrify/Common/Restrictions/TrackLocationHistory":true,
         "/Core/PasswordReset/Max":10,
         "/Core/PasswordReset/PasswordResetADEnabled":true,
         "/Mobile/EnrollRules/Common/AllowJailBrokenDevices":true,
         "/Core/PasswordReset/PasswordResetIdentityCookieOnly":false,
         "/Core/Security/CDS/LockoutPolicy/Threshold":5,
         "/Core/PasswordReset/UseADAdmin":false,
         "AuthenticationEnabled":true,
         "/Core/PasswordReset/MaxTime":60,
         "/Core/PasswordReset/PasswordResetEnabled":true,
         "/Mobile/DeviceManagement/UseCentrifyAsMdm":false,
         "/Core/Security/CDS/ExternalMFA/UiPrompt":"OATH OTP Client",
         "/Core/Authentication/AuthenticationRules":{  
            "_UniqueKey":"Condition",
            "_Value":[  
               {  
                  "Conditions":[  
                     {  
                        "Prop":"IdentityCookie",
                        "Op":"OpExists"
                     }
                  ],
                  "ProfileId":"44bd658e-defc-4d69-b6de-3dc0d6812f9b"
               }
            ],
            "Enabled":true,
            "_Type":"RowSet"
         },
         "/Core/Security/CDS/ExternalMFA/ShowQRCode":true,
         "/Core/Authentication/AuthenticationRulesDefaultProfileId":"cfefffff-9bf7-4569-895d-9dfbb3a9e8d7",
         "/Core/PasswordReset/PasswordResetAuthProfile":"a7dddddd-fe4e-4f37-a885-2176beb4a501",
         "/Mobile/EnrollRules/Common/AllowEnrollment":true,
         "/Core/Authentication/ConfigureSecurityQuestions":true,
         "/Core/PasswordReset/AccountUnlockADEnabled":false,
         "/Core/Authentication/UserSecurityQuestionsPerUser":1,
         "/Core/Authentication/CookieAllowPersist":false,
         "/Core/PasswordReset/AccountUnlockEnabled":true,
         "/Core/Authentication/AuthenticationRulesHighAuthRequestedProfileId":"12222222-9aad-4e49-8e23-1e4561d9b7c3",
         "/Core/PasswordReset/AccountUnlockIdentityCookieOnly":false,
         "/Core/Authentication/NoMfaMechLogin":false,
         "/Core/Authentication/AllowIwa":true,
         "/Core/Authentication/AllowZso":true
      },
      "Path":"/Policy/Default Policy",
      "RiskAnalysisLevels":{  
         "Levels":[  
            {  
               "Name":"Normal",
               "TranslatedName":"None Detected"
            },
            {  
               "Name":"Low",
               "TranslatedName":"Low"
            },
            {  
               "Name":"Med",
               "TranslatedName":"Medium"
            },
            {  
               "Name":"High",
               "TranslatedName":"High"
            },
            {  
               "Name":"Unknown",
               "TranslatedName":"Undetermined"
            }
         ]
      },
      "AuthProfiles":[  
         {  
            "Uuid":"12222222-9aad-4e49-8e23-1e4561d9b7c3",
            "Name":"Default New Device Login Profile",
            "DurationInMinutes":720,
            "Challenges":[  
               "UP"
            ],
            "AdditionalData":{  

            }
         },
         {  
            "Uuid":"a7dddddd-fe4e-4f37-a885-2176beb4a501",
            "Name":"Default Password Reset Profile",
            "DurationInMinutes":720,
            "Challenges":[  
               "OTP,SMS,EMAIL,OATH"
            ],
            "AdditionalData":{  

            }
         },
         ...
      ],
      "RevStamp":"636486318310000000",
      "Version":6
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 5. Add the Challenge Policy

Add a challenge policy by invoking the /Policy/AddAuthPolicyModifier endpoint, setting the PolicyModifier body parameter to the name of the new challenge policy:

POST /Policy/AddAuthPolicyModifier

{  
   "PolicyModifier":"test1"
}

The success field in the response indicates if the request was successful:

{  
   "success":true,
   "Result":null,
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 6. Save the Policy Block

Save the policy block by invoking the /policy/savepolicyblock3 endpoint and passing the information returned in the response to the /policy/getpolicyblock above:

POST /policy/savepolicyblock3

{  
   "policy":{  
      "Description":"DO NOT DISABLE Login MFA IN THIS POLICY for unknown devices.",
      "PolicyModifiers":[  

      ],
      "Settings":{  
         "/Mobile/Software/Policies/Centrify/Common/AllowNotificationOnMutipleDevices":true,
         "/Core/Authentication/IwaSatisfiesAllMechs":false,
         "/Core/Authentication/SecurityQuestionAnswerMinLength":3,
         "/Core/Authentication/IwaSetKnownEndpoint":true,
         "/Core/MfaRestrictions/BlockMobileMechsOnMobileLogin":false,
         "/Core/PasswordReset/AccountUnlockAuthProfile":"e4eeeeee-2e9e-4567-b9e2-a568360c8eb7",
         "/Core/Authentication/ZsoSatisfiesAllMechs":false,
         "/Core/Authentication/AdminSecurityQuestionsPerUser":0,
         "/Core/Security/CDS/ExternalMFA/ShowQRCodeForSelfService":true,
         "/Core/Authentication/ChallengeDefinitionId":"0d799995-ca79-43df-9355-fdf12394965b",
         "/Core/Authentication/ZsoSetKnownEndpoint":true,
         "PasswordResetEnabled":true,
         "/Mobile/Software/Policies/Centrify/Common/Restrictions/TrackLocationHistory":true,
         "/Core/PasswordReset/Max":10,
         "/Core/PasswordReset/PasswordResetADEnabled":true,
         "/Mobile/EnrollRules/Common/AllowJailBrokenDevices":true,
         "/Core/PasswordReset/PasswordResetIdentityCookieOnly":false,
         "/Core/Security/CDS/LockoutPolicy/Threshold":5,
         "/Core/PasswordReset/UseADAdmin":false,
         "AuthenticationEnabled":true,
         "/Core/PasswordReset/MaxTime":60,
         "/Core/PasswordReset/PasswordResetEnabled":true,
         "/Mobile/DeviceManagement/UseCentrifyAsMdm":false,
         "/Core/Security/CDS/ExternalMFA/UiPrompt":"OATH OTP Client",
         "/Core/Authentication/AuthenticationRules":{  
            "_UniqueKey":"Condition",
            "_Value":[  
               {  
                  "Conditions":[  
                     {  
                        "Prop":"IdentityCookie",
                        "Op":"OpExists"
                     }
                  ],
                  "ProfileId":"44bd658e-defc-4d69-b6de-3dc0d6812f9b"
               }
            ],
            "Enabled":true,
            "_Type":"RowSet"
         },
         "/Core/Security/CDS/ExternalMFA/ShowQRCode":true,
         "/Core/Authentication/AuthenticationRulesDefaultProfileId":"cfea9de5-9bf7-4569-895d-9dfbb3a9e8d7",
         "/Core/PasswordReset/PasswordResetAuthProfile":"a7dddddd-fe4e-4f37-a885-2176beb4a501",
         "/Mobile/EnrollRules/Common/AllowEnrollment":true,
         "/Core/Authentication/ConfigureSecurityQuestions":true,
         "/Core/PasswordReset/AccountUnlockADEnabled":false,
         "/Core/Authentication/UserSecurityQuestionsPerUser":1,
         "/Core/Authentication/CookieAllowPersist":false,
         "/Core/PasswordReset/AccountUnlockEnabled":true,
         "/Core/Authentication/AuthenticationRulesHighAuthRequestedProfileId":"12222222-9aad-4e49-8e23-1e4561d9b7c3",
         "/Core/PasswordReset/AccountUnlockIdentityCookieOnly":false,
         "/Core/Authentication/NoMfaMechLogin":false,
         "/Core/Authentication/AllowIwa":true,
         "/Core/Authentication/AllowZso":true,
         "/Core/test1/AuthenticationEnabled":true,
         "/Core/test1/Authentication/AuthenticationRules":{  
            "_Type":"RowSet",
            "Enabled":true,
            "_UniqueKey":"Condition",
            "_Value":[  
               {  
                  "Conditions":[  
                     {  
                        "Prop":"DateRange",
                        "Op":"OpBetween",
                        "Val":"L,02/23/2018,02/28/2018"
                     }
                  ],
                  "ProfileId":"cfea9de5-9bf7-4569-895d-9dfbb3a9e8d7"
               }
            ]
         },
         "/Core/test1/Authentication/AuthenticationRulesDefaultProfileId":"cfefffff-9bf7-4569-895d-9dfbb3a9e8d7",
         "/Core/test1/Authentication/NoMfaMechLogin":false
      },
      "Path":"/Policy/Default Policy",
      "RiskAnalysisLevels":{  
         "Levels":[  
            {  
               "Name":"Normal",
               "TranslatedName":"None Detected"
            },
            {  
               "Name":"Low",
               "TranslatedName":"Low"
            },
            {  
               "Name":"Med",
               "TranslatedName":"Medium"
            },
            {  
               "Name":"High",
               "TranslatedName":"High"
            },
            {  
               "Name":"Unknown",
               "TranslatedName":"Undetermined"
            }
         ]
      },
      "AuthProfiles":[  
         {  
            "Uuid":"122f46ae-9aad-4e49-8e23-1e4561d9b7c3",
            "Name":"Default New Device Login Profile",
            "DurationInMinutes":720,
            "Challenges":[  
               "UP"
            ],
            "AdditionalData":{  

            }
         },
         ...
      ],
      "RevStamp":"636486318310000000",
      "Version":6,
      "Newpolicy":false
   },
   "plinks":[  
      {  
         "Params":[  
            "Device|@Active Devices"
         ],
         "ID":"/Policy/louie1",
         "EnableCompliant":true,
         "Description":"",
         "LinkType":"Collection",
         "PolicySet":"/Policy/louie1"
      },
      {  
         "Params":[  
            "52577777_7f2f_4654_97f5_3123dfc5d5c7"
         ],
         "ID":"/Policy/RichPolicy",
         "EnableCompliant":true,
         "Description":"",
         "LinkType":"Role",
         "PolicySet":"/Policy/RichPolicy"
      },
      {  
         "Params":[  
            "8a666666_ec81_4f52_86b7_9377d49c217b"
         ],
         "ID":"/Policy/U2F Login Policy",
         "EnableCompliant":true,
         "Description":"",
         "LinkType":"Role",
         "PolicySet":"/Policy/U2F Login Policy"
      },
      ...
   ]
}

The success field in the response indicates if the request was successful and the RevStamp field indicates the revision of the new policy block that was created:

{  
   "success":true,
   "Result":{  
      "RevStamp":"636549980660000000"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Using the Challenge for MFA in an OAuth Client

Step 1. Start the Authentication

Start the normal authentication process by invoking the /security/startauthentication endpoint:

POST /security/startauthentication

{
    "User":  "[email protected]",
    "Version":  "1.0"
}

The response contains authentication challenges:

{  
   "success":true,
   "Result":{  
      "ClientHints":{  
         "PersistDefault":false,
         "AllowPersist":false,
         "AllowForgotPassword":true
      },
      "Version":"1.0",
      "SessionId":"N_XRw-zRM0GUZOA8vdOnWnT...",
      "Challenges":[  
         {  
            "Mechanisms":[  
               {  
                  "AnswerType":"Text",
                  "Name":"UP",
                  "PromptMechChosen":"Enter Password",
                  "PromptSelectMech":"Password",
                  "MechanismId":"nOt4E8G9rUybPu_ph4t..."
               }
            ]
         }
      ],
      "Summary":"NewPackage",
      "TenantId":"AAA1234"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 2. Advance the Authentication

Invoke the /security/advanceauthentication endpoint for each challenge. In this example a password is being provided for a password challenge:

POST /security/advanceauthentication

{
    "MechanismId":  "nOt4E8G9rUybPu_ph4tTG-0P...",
    "Answer":  "abcd1234",
    "SessionId":  "N_XRw-zRM0GUZOA8vdOnW...",
    "TenantId":  "AAA1234",
    "PersistentLogin":  false,
    "Action":  "Answer"
}

The success field in the response indicates if the request was successful:

{  
   "success":true,
   "Result":{  
      "SystemID":"AAA1234",
      "DisplayName":"J N",
      "EmailAddress":"[email protected]",
      "CustomerID":"AAA1234",
      "AuthLevel":"Normal",
      "PodFqdn":"corp.my-dev.centrify.com",
      "Auth":"F67AFC...",
      "User":"[email protected]",
      "UserDirectory":"AdProxy",
      "Summary":"LoginSuccess",
      "UserId":"128cadec-b5f5-4995-a5...",
      "SourceDsType":"AdProxy"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 3. Start the Application

Invoke the endpoint corresponding to your application. Construct the endpoint URL by concatenating /token/ and the name of your application, and then pass the application-specific parameters as a text string in the body:

POST /oauth2/token/_genericmfa

scope=GenericMFA&grant_type=client_credentials

The response contains application-specific information. In the example below, the access_token field contains a new access token to use in the next request:

{  
   "access_token":"eyJhb...",
   "token_type":"Bearer",
   "expires_in":31536000,
   "scope":"GenericMFA"
}

Step 4. Specify the Challenge Policy

Invoke the /security/OnDemandChallenge endpoint specifying the name of the user to authenticate on behalf of in the User field, and the name of the challenge policy in the PolicyModifier field:

POST /security/OnDemandChallenge

{
    "User":  "[email protected]",
    "arguments":  null,
    "PolicyModifier":  "test1"
}

Note: the on-demand challenge only works with the Client Credentials Flow.

The response contains the set of challenges associated with that challenge policy. In the example below, there are two challenges: a password challenge and an Oob verification code challenge which can be sent either by email or SMS:

{  
   "success":true,
   "Result":{  
      "ClientHints":{  
         "PersistDefault":false,
         "AllowPersist":false,
         "AllowForgotPassword":true
      },
      "Version":"1.0",
      "SessionId":"-AW5S9HtHGv...",
      "Challenges":[  
         {  
            "Mechanisms":[  
               {  
                  "AnswerType":"Text",
                  "Name":"UP",
                  "PromptMechChosen":"Enter Password",
                  "PromptSelectMech":"Password",
                  "MechanismId":"UFx-ivi..."
               }
            ]
         },
         {  
            "Mechanisms":[  
               {  
                  "AnswerType":"StartTextOob",
                  "Name":"EMAIL",
                  "PromptMechChosen":"Click the link in the email sent to [email protected]",
                  "PromptSelectMech":"Email... @centrify.com",
                  "PartialAddress":"centrify.com",
                  "MechanismId":"UuWMQ3CAoU..."
               },
               {  
                  "AnswerType":"StartTextOob",
                  "Name":"SMS",
                  "PartialDeviceAddress":"4660",
                  "PromptMechChosen":"Sending a text to mobile phone ending... 4660. Enter the code or click the link in the message to proceed with authentication.",
                  "PromptSelectMech":"SMS... XXX-1234",
                  "MechanismId":"oTE_Oxjdqk..."
               }
            ]
         }
      ],
      "Summary":"NewPackage",
      "TenantId":"AAA1234"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

Step 5. Advance the Authentication on Behalf of the User

Invoke the /security/advanceauthentication endpoint for each of the challenges returned from the /security/OnDemandChallenge endpoint.

The following example provides the password for the first challenge:

POST /security/advanceauthentication

{
    "MechanismId":  "UFx-iviXi_EoET50...",
    "Answer":  "123abcd",
    "SessionId":  "-AW5S9HtHGv5NK...",
    "TenantId":  "AAA1234",
    "PersistentLogin":  false,
    "Action":  "Answer"
}

The Summary field in the response indicates that the next challenge is to be started:

{  
   "success":true,
   "Result":{  
      "Summary":"StartNextChallenge"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

The next example starts the Oob challenge to send a verification code to the user's device via SMS:

POST /security/advanceauthentication

{
    "TenantId":  "AAA1234",
    "MechanismId":  "oTE_OxjdqkGR...",
    "PersistentLogin":  false,
    "Action":  "StartOOB",
    "SessionId":  "-AW5S9HtHGv5NKIfG..."
}

The Summary field in the response indicates that the Oob verification code has been sent and that Centrify is waiting for the user to provide that code:

{  
   "success":true,
   "Result":{  
      "Summary":"OobPending"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

In the final example below, the code is sent to Centrify via the Answer field:

POST /security/advanceauthentication

{
    "MechanismId":  "oTE_OxjdqkGRzbQPdIPvG4A...",
    "Action":  "Answer",
    "SessionId":  "-AW5S9HtHGv5NKIfGA3...",
    "Answer":  "123456789",
    "TenantId":  "AAA1234",
    "PersistentLogin":  false
}

The success field in the response indicates that the challenge was successfully fulfilled:

{  
   "success":true,
   "Result":{  
      "SystemID":"AAA1234",
      "DisplayName":"J N",
      "EmailAddress":"[email protected]",
      "CustomerID":"AAA1234",
      "AuthLevel":"High",
      "PodFqdn":"corp.my-dev.centrify.com",
      "User":"[email protected]",
      "UserDirectory":"AdProxy",
      "Summary":"LoginSuccess",
      "UserId":"128cadec-b5f5-49...7",
      "SourceDsType":"AdProxy"
   },
   "Message":null,
   "MessageID":null,
   "Exception":null,
   "ErrorID":null,
   "ErrorCode":null,
   "InnerExceptions":null
}

The client has now successfully logged the user in using MFA from a challenge policy.

Try the API in Postman:
Try the API in Postman.
Click here for help with using our sample Postman collection.