Contents
Once the SDK is setup and the current device is linked, we can now manage Auth Requests
. If you have not completed the basic integration steps found in the Authentication Management module, then please do so before continuing.
When an end-user is requesting authorization, use the AuthRequestManager to handle the operational flow.
A typical operational flow would be as follows:
AuthMethod
factors required by the AuthRequestManager
.AuthRequestResponse
to continue.Note
If using a conditional geofence policy, the first call to retrieve the auth methods to verify will only contain the geofencing auth method. Make another call to retrieve the auth methods to verify after successfully verifying the geofence to retrieve the resulting policy’s required auth methods (if any).
For example:
private final AuthRequestResponseEvent authRequestResponseEvent = new AuthRequestResponseEvent() {
@Override
public void onSuccess(@NonNull AuthRequestResponse authRequestResponse) {
final AuthRequestResponse.Result result = authRequestResponse.getResult();
if (result == AuthRequestResponse.Result.APPROVED) {
// auth request was successfully verified and approved
} else if (result == AuthRequestResponse.Result.DENIED) {
// auth request was was denied by the user
} else {
// auth request failed verification, check failure
final Failure failure = authRequestResponse.getFailure();
}
}
@Override
public void onFailure(@NonNull Exception e) {
// failed to get the response, check exception
}
};
private final AuthRequestPushReceivedEvent authRequestPushReceivedEvent = new AuthRequestPushReceivedEvent() {
@Override
public void onSuccess(@Nullable Void aVoid) {
// an auth request push event was received. calling checkForAuthRequest() should now give a valid pending auth request
checkForPendingAuthRequest();
}
@Override
public void onFailure(@NonNull Exception e) {
// failed to get the auth request push event, check exception
}
};
private final GetAuthRequestEventCallback getAuthRequestEventCallback = new GetAuthRequestEventCallback() {
@Override
public void onSuccess(@Nullable AuthRequest result) {
if (result != null) {
startAuthFlow(result);
}
}
@Override
public void onFailure(@NonNull Exception e) {
// failed to get the auth request, check exception
}
};
@Override
public void onResume() {
super.onResume();
authRequestManager.registerForEvents(authRequestPushReceivedEvent, authRequestResponseEvent);
}
@Override
public void onPause() {
authRequestManager.registerForEvents(authRequestPushReceivedEvent, authRequestResponseEvent);
super.onPause();
}
private void checkForPendingAuthRequest() {
if (!AuthenticatorManager.instance.isDeviceLinked()) {
return;
}
authRequestManager.checkForAuthRequest(getAuthRequestEventCallback);
}
private void startAuthFlow(AuthRequest authRequest) {
// You may deny the auth request anytime by supplying a DenialReason to
// authRequestManager.denyAndSend(authRequest, denialReasonObject);
// accepting the request will automatically send the response if the conditions
// for the policy were not met
final boolean failedPolicy = authRequestManager.acceptAndSendIfFailed(authRequest);
if (!failedPolicy) {
// get the auth methods requiring verification for this auth request
final List<Factor> methodsToVerify = authRequestManager.getAuthMethodsToVerify(authRequest);
// verify the auth methods
verifyMethods(methodsToVerify);
}
}
private void verifyAuthMethods(List<AuthMethod> authMethodsToVerify) {
for (AuthMethod authMethod : authMethodsToVerify) {
verifyAuthMethod(authMethod);
}
}
private void verifyAuthMethod(AuthMethod authMethod) {
switch (authMethod) {
case PIN_CODE:
verifyPinCode();
break;
case CIRCLE_CODE:
verifyCircleCode();
break;
case LOCATIONS:
verifyLocations();
break;
case BIOMETRIC:
verifyBiometric();
break;
case WEARABLES:
verifyWearables();
break;
case GEOFENCING:
verifyGeofence();
break;
}
}
private void verifyGeofence() {
// verify that Manifest.permission.ACCESS_FINE_LOCATION is granted prior to this call
GeofencesManager geofencesManager = AuthMethodManagerFactory.getGeofencesManager();
geofencesManager.verifyGeofencesForAuthRequest(currentAuthRequest, new AuthMethodAuthRequestVerificationCallback() {
@Override
public void onVerificationSuccess(final boolean authRequestWasSent) {
// To check if this was a conditional geofence, then make sure to call authRequestManager.getAuthMethodsToVerify(currentAuthRequest).
// If this list is different, from the prior call to it, then it was a condition geofence.
}
@Override
public void onVerificationFailure(final boolean authRequestWasSent,
final @NonNull AuthMethodFailure failure,
final boolean unlinkTriggered,
final boolean unlinkWarningTriggered,
final @Nullable Integer attemptsRemaining) {
// failed to verify the remote geofence location, check failure
}
});
}
private void verifyPinCode(String pinCode) {
PINCodeManager pinCodeManager = AuthMethodManagerFactory.getPINCodeManager();
// retrieve pincode from user prior to this call
pinCodeManager.verifyPINCodeForAuthRequest(pinCode, currentAuthRequest, new AuthMethodAuthRequestVerificationCallback() {
@Override public void onVerificationSuccess(boolean b) {
verifiedAuthMethod(AuthMethod.PIN_CODE);
}
@Override public void onVerificationFailure(boolean b, @NonNull AuthMethodFailure authMethodFailure, boolean b1, boolean b2, @Nullable Integer integer) {
showToast("Failed to verify PIN Code. " + integer + " attempts remaining");
}
});
}
...
private void sendResponse(AuthRequest authRequest) {
// once all factors are verified, send the response for the auth request
authRequestManager.send(authRequest);
}
-(void)checkForAuthRequest
{
[[LKCAuthRequestManager sharedManager] checkAuthRequestWithCompletion:^(LKCAuthRequestDetails *requestDetails, NSError *error) {
if(requestDetails != nil)
{
// If Auth Request Details is nil then there is no pending Auth Request
// Otherwise start the authorization flow
[self startAuthFlow];
}
else
{
// Check error returned
}
}];
}
-(void)startAuthFlow
{
BOOL failedPolicy = [[LKCAuthRequestManager sharedManager] acceptAndSendIfFailed];
if(!failedPolicy)
{
// Get and verify necessary Auth Methods
NSArray *methods = [[LKCAuthRequestManager sharedManager] getMethodsToVerify];
[self verifyMethods:methods];
}
else
{
// Auth Request Failed due to Policy or Configuration
}
}
-(void)verifyMethods:(NSArray*)methods
{
for(int i = 0; i < [methods count]; i++)
{
[self verifyMethod:[methods[i] intValue]];
}
}
-(void)verifyMethod:(AuthMethodType)method
{
switch (method) {
case PINCODE:
{
[self verifyPINCode];
break;
}
case CIRCLECODE:
{
[self verifyCircleCode];
break;
}
case LOCATIONS:
{
[self verifyLocations];
break;
}
case WEARABLES:
{
[self verifyWearables];
break;
}
case FINGERPRINTSCAN:
{
[self verifyFingerprintScan];
break;
}
case FACESCAN:
{
[self verifyFaceScan];
break;
}
default:
break;
}
}
-(void)verifyPINCode
{
[LKCPINCodeManager verifyPINCode:@"1234" forAuthRequest:authRequestObject withCompletion:^(BOOL success, NSError *error, BOOL autoUnlinkWarningThresholdMet, int attemptsRemaining) {
if(success)
{
// PIN Code verification successful
}
else
{
// Check error
}
}];
}
-(void)sendResponse
{
// Once all Auth Methods are verified, send response
[[LKCAuthRequestManager sharedManager] sendWithCompletion:^(NSError *error) {
if(error != nil)
{
// Response successful
}
else
{
// Check error
}
}];
}
func checkForAuthRequest()
{
LKCAuthRequestManager.shared()?.checkAuthRequest(completion: { (authRequest, error) in
if(authRequest != nil)
{
// If Auth Request Details is nil then there is no pending Auth Request
// Otherwise start the authorization flow
self.startAuthFlow()
}
else
{
// Check error returned
}
})
}
func startAuthFlow()
{
if(!(LKCAuthRequestManager.shared()?.acceptAndSendIfFailed())!)
{
// Get and verify Auth Methods
var methods = LKCAuthRequestManager.shared()?.getMethodsToVerify() as! NSArray
self.verifyMethods(methods)
}
else
{
// Auth Request Failed due to Policy or Configuration
}
}
func verifyMethods(_ methods: NSArray)
{
for method in methods
{
self.verifyMethod(method as! AuthMethodType)
}
}
func verifyMethod(_ method: AuthMethodType)
{
switch method {
case PINCODE:
self.verifyPINCode()
break
case CIRCLECODE:
self.verifyCirlceCode()
break
case LOCATIONS:
self.verifyLocations()
break
case WEARABLES:
self.verifyWearables()
break
case FINGERPRINTSCAN:
self.verifyFingerprintScan()
break
case FACESCAN:
self.verifyFaceScan()
break
default: break
}
}
func verifyPINCode()
{
LKCPINCodeManager.verifyPINCode("1234", forAuthRequest: authRequestObject) { (success, error, autoUnlinkWarningThresholdMet, attemptsRemaining) in
if(success)
{
// PIN Code verification successful
}
else
{
// Check error
}
}
}
func sendResponse()
{
// Once all Auth Methods are verified, send response
LKCAuthRequestManager.shared()?.send(completion: { (error) in
if(error != nil)
{
// Response successful
}
else
{
// Check error
}
})
}
This manager is responsible for handling auth auth request and should be the entry point to your request flows.
public interface AuthRequestManager {
// Use this variable to retrieve the NonNull TruValidate Multifactor Authentication implementation of this class, acts like a singleton for this interface.
@NonNull AuthRequestManager instance = InternalAuthRequestManager.getInstance();
// Use this method to check with the TruValidate Multifactor Authentication API if there is a pending {@link AuthRequest}
// You can cancel this operation by calling Disposable.dispose()
@NonNull Disposable check(final @Nullable GetAuthRequestEventCallback getAuthRequestEventCallback);
// Use this method to accept the policy, whether immediate failure, pending AuthMethod approval,
// or ready to send, with the corresponding AuthRequest
// In the event that the user auto-failed the policy the response will be sent immediately, otherwise
// implementors should continue forth by calling getAuthMethodsToVerify(AuthRequest) and verifying the AuthMethods
// using the corresponding managers before calling send(AuthRequest).
// Though this method is async, we do not allow cancelling the operation of sending the {@link AuthRequest}
boolean accept(final @NonNull AuthRequest authRequest);
// Use this method to send the response for an AuthRequest after it has been verified that
// all AuthMethods retrievable via getAuthMethodsToVerify(AuthRequest) have been successfully verified
// Though this method is async, we do not allow cancelling the operation of sending the AuthRequest
// In the event that the user failed one of the AuthMethods while verifying do not call this method, the response
// will have already been sent.
void send(final @NonNull AuthRequest authRequest);
// Use this method to deny and send the response for an {@link AuthRequest}
// Though this method is async, we do not allow cancelling the operation of sending the {@link AuthRequest}
void deny(final @NonNull AuthRequest authRequest, final @Nullable DenialReason denialReason) throws DenialReasonExpectedException;
// Use this method after having called accept(AuthRequest) to get the AuthMethods that are
// required to be verified by the user before sending the response for the provided AuthRequest
@NonNull List<AuthMethod> getAuthMethodsToVerify(final @NonNull AuthRequest authRequest);
// Register for events pertaining this manager class.
// Permitted events are all those located within the com.launchkey.android.authenticator.sdk.core.auth_request_management.event_callback package
void registerForEvents(final @NonNull Event... events);
// Unregister for events pertaining this manager class.
// Permitted events are all those located within the com.launchkey.android.authenticator.sdk.core.auth_request_management.event_callback package
void unregisterForEvents(final @NonNull Event... events);
}
// check and get a pending auth request
[[LKCAuthRequestManager sharedManager] checkAuthRequestWithCompletion:^(LKCAuthRequestDetails *requestDetails, NSError *error) {
..
}];
// get the locally cached auth request
LKCAuthRequestDetails *authRequestObject = [[LKCAuthRequestManager sharedManager] getPendingAuthRequest];
// get the auth methods required for verification
NSArray *methods = [[LKCAuthRequestManager sharedManager] getMethodsToVerify];
// accept an auth request
BOOL acceptAuthRequest = [[LKCAuthRequestManager sharedManager] acceptAndSendIfFailed];
// deny an auth request
[[LKCAuthRequestManager sharedManager] denyAndSendWithReasonID:@"denialReasonID" WithCompletion:^(NSError *error) {
..
}];
// send a response for an auth request
[[LKCAuthRequestManager sharedManager] sendWithCompletion:^(NSError *error) {
..
}];
// check and get a pending auth request
LKCAuthRequestManager.shared()?.checkAuthRequest(completion: { (authRequestObject, error) in
..
})
// get the locally cached auth request
var authRequest = LKCAuthRequestManager.shared()?.getPendingAuthRequest() as! LKCAuthRequestDetails
// get the auth methods required for verification
var methods = LKCAuthRequestManager.shared()?.getMethodsToVerify() as! NSArray
// accept an auth request
LKCAuthRequestManager.shared()?.acceptAndSendIfFailed()
// deny an auth request
LKCAuthRequestManager.shared()?.denyAndSend(withReasonID: "denialReasonID", withCompletion: { (error) in
..
})
// send a response for an auth request
LKCAuthRequestManager.shared()?.send(completion: { (error) in
..
})
An AuthRequest
object is a data class holding all the information needed to display to an end-user about a request. An AuthRequest
contains the following accessor methods:
public class AuthRequest {
// return the unique identifier of an Auth Request.
public @NonNull String getId();
// return true if more details have been provided on the Auth Request, false otherwise.
public boolean hasContext();
// return details on the Auth Request.
public @NonNull String getContext();
// return title of the Auth Request.
public @NonNull String getTitle();
// return the timestamp in milliseconds at which point this Auth Request expires.
public long getExpiresAtMillis();
// return the timestamp in milliseconds at which point this Auth Request was created.
public long getCreatedAtMillis();
// return Service Profile model object representing the Service that initiated
// this Auth Request. Currently only holds the Service's name.
public @NonNull ServiceProfile getServiceProfile();
// return Array of DenialReason model objects which currently only holds the
// denial reason's id and message.
public @NonNull DenialReason[] getDenialReasons();
public AuthRequest createCopy();
}
@interface LKCAuthRequestDetails : NSObject
// The unique identifier of an Auth Request
@property(strong, nonatomic) NSString *authRequestID;
// The title of the Auth Request
@property(strong, nonatomic) NSString *title;
// The unique identifier of the Service that created the Auth Request
@property(strong, nonatomic) NSString *serviceID;
// The timestamp in milliseconds at which point the Auth Request expires
@property(strong, nonatomic) NSString *expiresAtTime;
// The timestamp in milliseconds at which point the Auth Request was created
@property(strong, nonatomic) NSString *createdAtTime;
// return details on the Auth Request
@property(strong, nonatomic) NSString *context;
// The icon of the Service that created the Auth Request
@property(strong, nonatomic) NSString *serviceIcon;
// The array of Denial Reasons which includes the
// denial reason's id and reason
@property(strong, nonatomic) NSArray *denialReasons;
You are now all setup with auth request management. It is recommended that you read Auth Request Management Events to handle all events regarding this module.
TransUnion links to user contributed code as a resource to its community. TransUnion does not in any way guarantee or warrant the quality and security of these code bases. User contributed code is supported by the creators. If you do find a link from the site to user contributed code that is malicious or inappropriate in any way, please report that link to TransUnion immediately and we will investigate the claim. Submit any issue to TransUnion support at https://transunion.com/support. ×