Gigya Job Openings

TFA Library For Android SDK 4.x

Skip to end of metadata
Go to start of metadata

Description

The Android TFA package provides the ability to integrate native Two Factor Authentication flows within your Android application without using the ScreenSets feature.

Current supported TFA providers are: 

  • gigyaPhone
  • gigyaEmail
  • gigyaPush
  • gigyaTotp

 

In order to use Two Factor Authentication for your site please please read:

Risk Based Authentication

 

Integration

In order to integrate the Gigya TFA package you will need to download the latest library from our download site and add the file to your app/lib/ folder.

After adding the library, update your application build.gradle file accordingly.

implementation files('libs/gigya-android-tfa-1.0.1.aar')

The Android TFA package is not a stand alone library. Please make sure you have have already integrated the Gigya Android SDK v4.x.

 

Two Factor Authentication interruptions

When using login/register flows, you are able to override two additional callback methods within the GigyaLoginCallback class:

@Override
public void onPendingTwoFactorRegistration(@NonNull GigyaApiResponse response, @NonNull List<TFAProviderModel> inactiveProviders, @NonNull TFAResolverFactory resolverFactory) {
    // The login/register flow was interrupted with error 403102 (Account Pending TFA Registration)
}
 
@Override
public void onPendingTwoFactorVerification(@NonNull GigyaApiResponse response, @NonNull List<TFAProviderModel> activeProviders, @NonNull TFAResolverFactory resolverFactory) {
    // The login/register flow was interrupted with error 403101 (Account Pending TFA Verification)
}

These callbacks are called interruption callbacks. Their main purpose is to inform the client that a Two Factor Authentication interruption has happened. In addition they provide the user with the relevant data needed to resolve the interruption in the same context they were initiated.

 

Initial interruption data

response: GigyaApiRespone - The initial interruption response received by the login/register attempt.
inactiveProviders: List<TFAProviderModel> - A list containing the Two Factor Authentication providers available for registration.
activeProviders: List<TFAProviderModel> - A list containing the registered Two Factor Authentication providers for this account.
resolverFactory: TFAResolverFactory - A provided factory class which allows you to fetch the appropriate resolver class in order to continue the login/register flow.

Notes:

  • The TFA package contains various Fragment classes which you can use in order to resolve various Two Factor Authentication flows. All of which are implemented in the provided sample application.
  • All resolver flows will end with redirecting the finalized logged-in/registered account to the original "onSuccess" callback. In addition, at the end of each successful flow an "onResolved" callback will be called in order to give an optional logic check point if any other application tasks are needed to be performed.

 

Email Verification

Resolving email verification Two Factor Authentication is done using the RegisteredEmailsResolver class.

Email verification requires you to have a valid registered email account.

Code example for email verification flow. Note that this is just a partial representation of the flow and will require additional UI intervention. A complete sample is available in the provided TFAEmailVerificationFragment class.

final RegisteredEmailsResolver registeredEmailResolver = resolverFactory.getResolverFor(RegisteredEmailsResolver.class)
registeredEmailResolver.getRegisteredEmails(new RegisteredEmailsResolver.ResultCallback() {
    @Override
    public void onRegisteredEmails(List<EmailModel> registeredEmailList) {
        // Populate registered emails display list.
        // Once selected call:
        registeredEmailResolver.sendEmailCode(selectedEmail, ...)
    }
 
    @Override
    public void onEmailVerificationCodeSent(IVerifyCodeResolver verifyCodeResolver) {
        // Email verification code was successfully sent to provided email address
        // Once code is available call:
        verifyCodeResolver.verifyCode(GigyaDefinitions.TFAProvider.EMAIL, verificationCode, false, new VerifyCodeResolver.ResultCallback() {
            @Override
            public void onResolved() {
                // Flow completed.
            }
  
            @Override
            public void onInvalidCode() {
                // Invalid code inserted. Try again.
            }  
  
            @Override
            public void onError(GigyaError error) {
                // handle error.
            }
        );
    }
 
    @Override
    public void onError(GigyaError error) {
        // Handle error.
    }
});

 

 

 

Phone Registration

Resolving phone Two Factor Authentication registration is done using the RegisterPhoneResolver class.

Code example for phone registration flow. Note that this is just a partial representation of the flow and will require additional UI intervention. A complete sample is available in the provided TFAPhoneRegistrationFragment class.

final RegisterPhoneResolver registerPhoneResolver = resolverFactory.getResolverFor(RegisterPhoneResolver.class)
registerPhoneResolver.registerPhone(phoneNumber, new RegisterPhoneResolver.ResultCallback() {
  
    @Override
    public void onVerificationCodeSent(IVerifyCodeResolver verifyCodeResolver) {
        // Verification code was sent to registered phone number. At this point you should update your UI to support verification input.
        // After UI has been updated and the verification code is available, you are able to use:
        verifyCodeResolver.verifyCode(GigyaDefinitions.TFAProvider.PHONE, verificationCode, false /* set true to remember device */ , new VerifyCodeResolver.ResultCallback() {
            @Override
            public void onResolved() {
                // Flow completed.
            }
  
            @Override
            public void onInvalidCode() {
                // Invalid code inserted. Try again.
            }  
  
            @Override
            public void onError(GigyaError error) {
                // handle error.
            }
        );
    }
  
    @Override
    public void onError(GigyaError error) {
        // Handle error.
    }
  
});

 

 

Phone Verification

Resolving phone Two Factor Authentication verification is done using the RegisteredPhonesResolver class.

Code example for phone verification flow. Note that this is just a partial representation of the flow and will require additional UI intervention. A complete sample is available in the provided TFAPhoneVerificationFragment class.

final RegisteredPhonesResolver registeredPhonesResolver = resolverFactory.getResolverFor(RegisteredPhonesResolver.class)
registeredPhonesResolver.getPhoneNumbers(new RegisteredPhonesResolver.ResultCallback() {
     
    @Override
    public void onRegisteredPhones(List<RegisteredPhone> registeredPhonesList) {
        // Display list of registered phones to the user so he will be able to choose where to send verification code sms/voice call.
        // After user chooses call:
        registeredPhonesResolver.sendVerificationCode(...);
    }
  
    @Override
    public void onVerificationCodeSent(IVerifyCodeResolver verifyCodeResolver) {
        // Verification code successfully sent.
        // You are now able to verify the code received calling:
        verifyCodeResolver.verifyCode(GigyaDefinitions.TFAProvider.PHONE, verificationCode, false /* set true to remember device */ , new VerifyCodeResolver.ResultCallback() {
            @Override
            public void onResolved() {
                // Flow completed.
            }
  
            @Override
            public void onInvalidCode() {
                // Invalid code inserted. Try again.
            }  
  
            @Override
            public void onError(GigyaError error) {
                // handle error.
            }
        );
    }
  
    @Override
    public void onError(GigyaError error) {
        // handle error.
    }
});

 

 

 

 

TOTP Registration

Resolving TOTP Two Factor Authentication registration is done using the RegisterTOTPResolver class.

Code example for TOTP registration flow. Note that this is just a partial representation of the flow and will require additional UI intervention. A complete sample is available in the provided TOTPRegistrationFragment class.

final RegisterTOTPResolver registerTOTPResolver = resolverFactory.getResolverFor(RegisterTOTPResolver.class)
registerTOTPResolver.registerTOTP(new RegisterTOTPResolver.ResultCallback() {
     
    @Override
    public void onQRCodeAvailable(@NonNull String qrCode, IVerifyTOTPResolver verifyTOTPResolver) {
        // Base64 encoded QR code is available. Decode it to a bitmap and display for the user to scan.
        // Once the user scans the code and a verification code is available via the authenticator application you are able to call:
        verifyTOTPResolver.verifyTOTPCode(verificationCode, false /* or true to save device */, new VerifyTOTPResolver.ResultCallback() {
                     
            @Override
            public void onResolved() {
                // Flow completed.
            }  
     
            @Override
            public void onInvalidCode() {
                // Verification code invalid. Display error and try again.
            }
             
            @Override
            public void onError(GigyaError error) {
                // Handle error.
            }              
  
        });
    }
     
    @Override
    public void onError(GigyaError error) {
        // Handle error.
    }
  
});

 

 

TOTP Verification

Resolving TOTP Two Factor Authentication verification is done using the VerifyTOTPResolver class.

Code example for TOTP verification flow. Note that this is just a partial representation of the flow and will require additional UI intervention. A complete sample is available in the provided TOTPVerificationFragment class.

final VerifyTOTPResolver verifyTOTPResolver = resolverFactory.getResolverFor(VerifyTOTPResolver.class) 
// At this point the code is already available to the user using his preferred authenticator application.
verifyTOTPResolver.verifyTOTPCode(verificationCode, false /* true for to save device */, new VerifyTOTPResolver.ResultCallback() {
         
    @Override
    public void onResolved() {
        // Flow completed. 
    }
  
    @Override
    public void onInvalidCode() {
        // Verification code invalid. Display error and try again.
    }
             
    @Override
    public void onError(GigyaError error) {
        // Handle error.
    }  
  
});

 

 

Push TFA

The push TFA feature allows you to secure your login using push notifications to any registered devices. 

RBA Push Notifications

This feature currently uses all registered mobile devices to verify any login process made from a website for a specific account.

*Mobile login with push TFA is not currently available.

 

Messaging service

In order to add the push TFA feature to your application you will need a working push notification/messaging service.

Currently we support only Google Firebase.

Add the following dependencies to your build.gradle file:

implementation 'com.google.firebase:firebase-core:16.0.9'
implementation 'com.google.firebase:firebase-messaging:18.0.0'

 

Using Google Firebase

An active Firebase account is needed in order to integrate the push TFA service.

Instructions on how to add Firebase into your Android application can be found here: https://firebase.google.com/docs/android/setup

It is not possible to add a registered Google project into a running Firebase project (even if you have just opened a new one). If you already have a registered Google project you will need to link it to Firebase.

To do this, first make sure you are logged in with the same account your Android project is registered to and then link it by choosing the project from your registered projects when creating a new Firebase project.

 

Setting up your application to use cloud messaging

Once you have your Firebase up and running, you are able to register your application in the Cloud Messaging tab of your project Settings page.

  1. Go to your Firebase console. select your project and open project settings as shown:




  2. Select the "Cloud Messaging" tag and copy your Server key.



  3. Use the copied Server key and update your CDC console RBA settings.

Adding Gigya's messaging service

  1. Adding the messaging service
    1. The Android SDK provides a GigyaFirebaseMessagingService class for you. In order to integrate it please add the following to your AndroidManifest.xml.

      <service
          android:name="com.gigya.android.sdk.tfa.push.firebase.GigyaFirebaseMessagingService"
          android:exported="false">
          <intent-filter>
              <action android:name="com.google.firebase.MESSAGING_EVENT" />
          </intent-filter>
      </service>

      Our GigyaFirebaseMessaingService extends the provided FIrebaseMessaingService. If your application already uses the FirebaseMessagingService your will you will need to make your class extend the GigyaFirebaseMessaingService.

      In order for all flows to remain intact make sure to call the relevant super methods:

      @Override
      public void onNewToken(String newToken) {
          // Calling the super method to enable the Gigya messaging flow.
          super.onNewToken(newToken);
      }
      
      @Override
      public void onMessageReceived(RemoteMessage remoteMessage) {
          // Calling the super method to enable the Gigya messaging flow.
          super.onMessageReceived(remoteMessage);
      }
  2. Adding the TFAPushReceiver & the relevant content activity
    1. The push TFA notification contains a content pending intent (setContentIntent) which will trigger an Activity to open in order to handle the notification content. You will have to declare that activity in your AndroidManifest.xml. The Android SDK already provides you with a template PushTFAActivity class which handles the content intent for you and will display the relevant action UI & handle the selection.

    2. In order to use the provided PushTFAActivity class please add the following to your AndroidManifest.xml file:

      <activity
          android:name="com.gigya.android.sdk.tfa.ui.PushTFAActivity"
          android:excludeFromRecents="true"
          android:launchMode="singleTask"
          android:taskAffinity=""
          android:theme="@style/Theme.AppCompat.Translucent" />
    3. Additionally, all action-based push notifications will add the relevant buttons to the notification body. In order to allow the SDK to handle these actions please register the following Broadcast Receiver:

      <receiver
          android:name="com.gigya.android.sdk.tfa.push.TFAPushReceiver"
          android:exported="false">
          <intent-filter>
              <action android:name="com.gigya.android.sdk.tfa.push_approve" />
              <action android:name="com.gigya.android.sdk.tfa.push_deny" />
          </intent-filter>
      </receiver>

Available customization options

The Android SDK provides some customization options for you if you wish to add a your personal touch to the notificaitons or the content activity.

In order to apply customization you will have to extend the GigyaFirebaseMessaingService class with your own custom service, making sure to register your own service in the AndroidManifest.xml file instead of the GigyaFirebaseMessagingService class.

Available customization overrides:

public class CustomMessagingService extends GigyaFirebaseMessagingService {
 
    @Override
    public void onNewToken(String newToken) {
        super.onNewToken(newToken);
    }
 
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        super.onMessageReceived(remoteMessage);
    }
 
    @Override
    protected int getSmallIcon() {
        // Return your customized notification small icon. This cannot be null!!
    }
 
    @Override
    public Class getCustomActionActivity() {
        // Return your own content activity class. Note that you will have to handle all logic
        // and don't forget to register the activity in the AndroidManifest.xml file.
    }
 
    @Override
    protected int getApproveActionIcon() {
        // Return your customized approve action icon.
    }
 
    @Override
    protected int getDenyActionIcon() {
        // Return your customized deny action icon.
    }
}

 

Push TFA Flow

Opt-In process

In order for a client to opt-in to use the push TFA feature you will need to add the option to opt-in after the user have successfully logged in.

GigyaTFA.getInstance().optInForPushTFA(new GigyaCallback<GigyaApiResponse>() {
    @Override
    public void onSuccess(GigyaApiResponse obj) {
        // Step one of the opt-in process has been completed.
        // Wait for approval push notification and to complete flow.
    }
 
    @Override
    public void onError(GigyaError error) {
        // Handle error.
    }
});

 

Verification push should look as following:

 

Select Approve in order to finalize the opt-in process. 

You should receive another notification to indicate the flow has been successfully completed.

 

Verification process

Once you opt-in to use the Push TFA service your client will login to his account on the website and an approval notification will be sent to all registered devices (which have completed the opt-in process).

The approval push should look as follows:

 

 

Once you choose to approve your client will be logged into the system.

Push TFA messages are sent using PendingIntent.FLAG_CANCEL_CURRENT flag. This is done to avoid approving or disapproving push notification data which may contain invalid tokens.

 

Push TFA authentication with fingerprint encrypted session

Push TFA actions are session dependent. Therefore, when your session in encrypted using a fingerprint, you must authenticate the user in order to complete the notification authentication flow.

The Android TFA library & The Android Biometric libraries are two independent libraries and do not depend on on the other. However, to achieve the right authentication flow please follow these steps:

When using biometric session encryption, your TFA notification will not contain Approve/Deny buttons. Action handing will be done via notification click using an extension of the PushTFAActivity.class.

 

1 Create an Activity extension class for your TFA action handling

You will need to evaluate the session state when your extension activity starts. If the session is encrypted using the "FINGERPRINT" tag. You will first need to unlock it before displaying the action alert.

Additionally, If the session was previously locked it is recommended to lock it again after approving the push action to avoid irregular behaviours.

Example taken from sample application used to combine the biometric support and the push TFA feature.

class BiometricPushTFAActivity : PushTFAActivity() {
 
    // Helper state for locking back the session if was previously unlocked.
    private var shouldLockSessionOnApproval: Boolean = false
 
    // Referencing the biometric library.
    private val biometric: GigyaBiometric = GigyaBiometric.getInstance()
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
 
        evaluateSessionState()
    }
     
    // Override and return false in order the control when the action alert will show.
    override fun alertOnCreate(): Boolean = false
 
    /**
    * Evaluate the current session encryption state.
    */
    private fun evaluateSessionState() {
        when (_tfaLib.sessionEncryption == "FINGERPRINT") {
            true -> {
                if (!biometric.isAvailable) {
                    GigyaLogger.error("BiometricPushTFAActivity",
                            "Session is FINGERPRINT locked but biometric support is not available")
                    finish()
                    return
                }
                if (!biometric.isLocked) {
                    showActionAlert()
                    return
                }
                biometric.unlock(
                        this,
                        GigyaPromptInfo(
                                getString(R.string.tfa_biometric_locked_session_title),
                                getString(R.string.tfa_biometric_locked_session_subtitle),
                                getString(R.string.tfa_biometric_locked_session_description)
                        ),
                        object : IGigyaBiometricCallback {
                            override fun onBiometricOperationSuccess(action: GigyaBiometric.Action) {
                                GigyaLogger.debug("BiometricPushTFAActivity", "onBiometricOperationSuccess: Okay to approve push action")
                                shouldLockSessionOnApproval = true
                                showActionAlert()
                            }
 
                            override fun onBiometricOperationFailed(reason: String?) {
                                GigyaLogger.debug("BiometricPushTFAActivity", "onBiometricOperationFailed: - $reason - Available for retry")
 
                            }
 
                            override fun onBiometricOperationCanceled() {
                                GigyaLogger.debug("BiometricPushTFAActivity", "onBiometricOperationFailed: Push action is lost. Will call onDeny")
                                onDeny()
                            }
                        }
                )
            }
            false -> {
                showActionAlert()
            }
        }
    }
 
    /**
    * Overriding the approval action.
    */
    override fun onApprove(extras: Bundle?) {
        super.onApprove(extras)
        if (shouldLockSessionOnApproval) {
            shouldLockSessionOnApproval = false
            if (biometric.isAvailable) {
                biometric.lock(object : IGigyaBiometricOperationCallback {
                    override fun onBiometricOperationSuccess(action: GigyaBiometric.Action) {
                        GigyaLogger.debug("BiometricPushTFAActivity", "onBiometricOperationSuccess: ")
                    }
 
                    override fun onBiometricOperationFailed(reason: String?) {
                     GigyaLogger.error("BiometricPushTFAActivity ", "onBiometricOperationFailed: Session will remain unlocked")
                    }
                 
                })
            }
        }
    }
 
}

 

2 Create a custom extension class for the GigyaFirebaseMessagingService class

An extension service class is needed in order to define your custom TFA activity.

class GigyaFirebaseMessagingExt : GigyaFirebaseMessagingService() {
 
    override fun getCustomActionActivity(): Class<*> {
        return BiometricPushTFAActivity::class.java
    }
}

Don't forget to correctly declare your extension classes in your AndroidManifest.xml.

Example taken from the provided sample application:

<activity
    android:name=".ui.BiometricPushTFAActivity"
    android:excludeFromRecents="true"
    android:launchMode="singleTask"
    android:taskAffinity=""
    android:theme="@style/Theme.AppCompat.Translucent" />
  
<service
    android:name="GigyaFirebaseMessagingExt"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

 

Additional Information

Risk Based Authentication

 

 

 

 

 

 

  • No labels