Implementing MFA Authentication with Descope Backend SDKs
Install SDK
npm i --save @descope/node-sdkpip3 install descopego get github.com/descope/go-sdk// Include the following in your `pom.xml` (for Maven)
<dependency>
<artifactId>java-sdk</artifactId>
<groupId>com.descope</groupId>
<version>sdk-version</version> // Check https://github.com/descope/descope-java/releases for the latest versions
</dependency>gem install descopeImport and initialize Management SDK
import DescopeClient from '@descope/node-sdk';
const managementKey = "xxxx"
try{
// baseUrl="<URL>" // When initializing the Descope clientyou can also configure the baseUrl ex: https://auth.company.com - this is useful when you utilize a custom domain within your Descope project.
const descopeClient = DescopeClient({ projectId: '__ProjectID__', managementKey: managementKey });
} catch (error) {
// handle the error
console.log("failed to initialize: " + error)
}from descope import (
REFRESH_SESSION_TOKEN_NAME,
SESSION_TOKEN_NAME,
AuthException,
DeliveryMethod,
DescopeClient,
AssociatedTenant,
RoleMapping,
AttributeMapping
)
management_key = "xxxx"
try:
# You can configure the baseURL by setting the env variable Ex: export DESCOPE_BASE_URI="https://auth.company.com - this is useful when you utilize a custom domain within your Descope project."
descope_client = DescopeClient(project_id='__ProjectID__', management_key=management_key)
except Exception as error:
# handle the error
print ("failed to initialize. Error:")
print (error)import "github.com/descope/go-sdk/descope"
import "github.com/descope/go-sdk/descope/client"
import "fmt"
// Utilizing the context package allows for the transmission of context capabilities like cancellation
// signals during the function call. In cases where context is absent, the context.Background()
// function serves as a viable alternative.
// Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
import (
"context"
)
managementKey = "xxxx"
// DescopeBaseURL // within the client.Config, you can also configure the baseUrl ex: https://auth.company.com - this is useful when you utilize a custom domain within your Descope project.
descopeClient, err := client.NewWithConfig(&client.Config{ProjectID:"__ProjectID__", managementKey:managementKey})
if err != nil {
// handle the error
log.Println("failed to initialize: " + err.Error())
}import com.descope.client;
// Initialized after setting the DESCOPE_PROJECT_ID env var (and optionally DESCOPE_MANAGEMENT_KEY)
var descopeClient = new DescopeClient();
// ** Or directly **
var descopeClient = new DescopeClient(Config.builder()
.projectId("__ProjectID__")
.managementKey("management-key")
.build());require 'descope'
descope_client = Descope::Client.new(
{
project_id: '__ProjectID__',
management_key: 'management_key'
}
)Sign-Up, Sign-in, or Sign-Up-Or-In
The next step after adding the Descope backend SDK within your application is to utilize one of the Sign-Up, Sign-in, or Sign-Up-Or-In functions for the supported authentication methods. Once you have successfully received a JWT from the authentication method, you should store it for the next step in the MFA process.
MFA the user's authentication
Now that you have a valid JWT for your authenticated user, you can utilize Sign-in or Sign-Up-Or-In for one of the supported
authentication methods, adding the user Login Options. This example will focus on the mfa parameter
of the Login Options; however, for further details on Login Options, navigate here.
The below example implements MFA authentication via OTP Sign-In after the user successfully signed up via TOTP Sign-Up. After a successful MFA sign-in, you will need to process the verification code via OTP Verify. After verifying, the user will then have MFA authentication.
// Args:
// deliveryMethod: Delivery method to use to send OTP. Supported values include "email", "voice, or "sms"
const deliveryMethod = "email"
// loginId: email or phone - email or phone - the loginId for the user
const loginId = "email@company.com"
// loginOptions: login options for MFA, stepup, or custom claims. Ex: {stepup: true, mfa: false, customClaims: {}}
const loginOptions = {mfa: true}
// token: refresh token from the successful sign-in of the user
const token = "xxxx"
var resp = await descopeClient.otp.signIn[delivery_method](loginId, loginOptions, token);
if (!resp.ok) {
console.log("Failed to initialize mfa flow")
console.log("Status Code: " + resp.code)
console.log("Error Code: " + resp.error.errorCode)
console.log("Error Description: " + resp.error.errorDescription)
console.log("Error Message: " + resp.error.errorMessage)
}
else {
console.log("Successfully initialized mfa flow")
console.log(resp.data)
}# Args:
# delivery_method: Delivery method to use to send OTP. Supported values include DeliveryMethod.SMS, DeliveryMethod.Voice, or DeliveryMethod.EMAIL
delivery_method = DeliveryMethod.EMAIL
# login_id: email or phone - email or phone - the loginId for the user
login_id = "email@company.com"
# login_options (LoginOptions): login options for MFA, stepup, or custom claims. Ex: LoginOptions(stepup: True, mfa: False, customClaims: {})
login_options = LoginOptions(mfa=True)
# refresh_token: refresh token from the successful sign-in of the user
refresh_token = "xxxxx"
try:
resp = descope_client.otp.sign_in(method=delivery_method, login_id=login_id, login_options=login_options, refresh_token=refresh_token)
print ("Successfully initialized MFA flow")
except AuthException as error:
print ("Failed to initialize MFA flow")
print ("Status Code: " + str(error.status_code))
print ("Error: " + str(error.error_message))// Args:
// ctx: context.Context - Application context for the transmission of context capabilities like
// cancellation signals during the function call. In cases where context is absent, the context.Background()
// function serves as a viable alternative.
// Utilizing context within the Descope GO SDK is supported within versions 1.6.0 and higher.
ctx := context.Background()
// deliveryMethod: Delivery method to use to send OTP. Supported values include descope.MethodEmail, descope.MethodVoice, or descope.MethodSMS
deliveryMethod := descope.MethodEmail
// loginID: email or phone - the loginId for the user
loginID := "email@company.com"
// r: HttpRequest for the update call. This request should contain refresh token for the authenticated user.
// loginOptions: Optional login options for MFA, stepup, or custom claims.
loginOptions := &descope.LoginOptions{mfa: true}
err := descopeClient.Auth.OTP().SignIn(ctx, deliveryMethod, loginID, r, loginOptions)
if (err != nil){
fmt.Println("Failed to initialize MFA flow: ", err)
} else {
fmt.Println("Successfully initialized MFA flow")
}
// Every user must have a loginID. All other user information is optional
String loginId = "email@company.com";
User user = User.builder()
.name("Joe Person")
.phone("+15555555555")
.email(loginId)
.build();
var loginOptions = LoginOptions.builder()
.mfa(true)
.build();
OTPService otps = descopeClient.getAuthenticationServices().getOtpService();
try {
String maskedAddress = otps.signIn(DeliveryMethod.EMAIL, loginId, loginOptions);
} catch (DescopeException de) {
// Handle the error
}