Android Authenticator SDK v2 Integration

Setup for Android Studio

To setup the Authenticator SDK in your Android Studio project:

  1. Download the Authenticator SDK v2 for Android Studio

  2. Open your project in Android Studio and navigate to File -> New Module, and then select Import .JAR or .AAR Package from the More Modules list, and click Next. Then browse for the file, select it, and click Finish.

  3. The SDK should now be a part of your project as a module, but in order to make it a dependency for your service, navigate to File -> Project Structure and select the implementing service in the list of modules (e.g. app), and then navigate to the Dependencies tab. Add the module by clicking the plus button (+) and select Module Dependency. Select the library module which should now appear in the list and press OK, followed by OK once more to update the dependencies, and clean your project to include the build.gradle file.

  4. Lastly, make sure the service has all of the required libraries for the SDK to work properly. Your app

    module’s build.gradle file should look like this:

dependencies {
        ...
        compile fileTree(dir: 'libs', include: ['*.jar'])
        compile 'com.squareup.okhttp3:okhttp:3.3.1'
        compile 'com.android.support:support-v4:23.1.1'
        compile 'com.android.support:appcompat-v7:23.1.1'
        compile 'com.android.support:design:23.1.1'
        compile 'com.android.support:cardview-v7:23.1.1'
        compile 'com.google.android.gms:play-services-base:8.3.0'
        compile 'com.google.android.gms:play-services-location:8.3.0'
        compile 'com.google.android.gms:play-services-maps:8.3.0'
        compile 'com.google.android.gms:play-services-gcm:8.3.0'
        compile 'de.hdodenhof:circleimageview:1.3.0'
        compile 'com.cocosw:bottomsheet:1.2.0@aar'
        compile 'com.squareup.picasso:picasso:2.5.2'
        compile 'com.nineoldandroids:library:2.4.0'
        compile project(':lk-wl-sdk')
}

Note

If running into issues, make sure to update your Build Tools.

Note

Since push notifications are a central part of the LaunchKey authenticator experience, make sure the Google Play Services plugin is applied to the app-level build.gradle file.

Initialize the Authenticator SDK

In order to initialize the Authenticator SDK Manager, it needs to be instantiated first:

WhiteLabelManager mWhiteLabelManager = WhiteLabelManager.getInstance();

Then call its .init(WhiteLabelConfig) method passing the config object, explained in the following step.

Note

We recommend that the Authenticator SDK Manager is initialized in the starting Activity or service-level class before any other calls are made.

Configuration Options

The Authenticator SDK provides multiple configuration options to customize the branding, aesthetics, and security. This is accomplished through a configuration object. To modify the default configuration options, instantiate a WhiteLabelConfig.Builder object, and call a series of chained methods with your desired configuration before calling the build() method which will return the complete configuration object to be passed to the .init() method of WhiteLabelManager.

Instantiate the configuration object like this (explanation of options afterwards) v2.0+:

WhiteLabelConfig config =
    new WhiteLabelConfig.Builder(Context)
    .sdkKey(String)                     // or .sdkKeyRes(int)
    .sslPinning(boolean)
    .themeColorPrimary(int)             // or .themeColorPrimaryRes(int)
    .themeColorPrimaryTextAndIcons(int) // or .themeColorPrimaryTextAndIconsRes(int)
    .themeColorSecondary(int)           // or .themeColorSecondaryRes(int)
    .themeColorBackgrounds(int)         // or .themeColorBackgroundsRes(int)
    .build();

mWhiteLabelManager.init(config);

Instantiate the configuration object on v2.2+:

WhiteLabelConfig config
    new WhiteLabelConfig.Builder(Context, sdkKey[Res])
    ...

SDK Key (Required)

.sdkKey(String)
.sdkKeyRes(int)

The Authenticator SDK Key is provided on Dashboard under the directory that contains one or more LaunchKey Authenticator services. It can be easily passed to the WhiteLabelConfig.Builder object as the actual string or even as a String resource reference.

Primary Color

.themeColorPrimary(int)
.themeColorPrimaryRes(int)

The primary color is the most widely used color as the ActionBar/Toolbar color across all screens. Pass the color value to the first method (e.g. Color.BLACK) or the resource reference of the color to the second one (e.g. R.color.my_brand_blue).

Primary Text And Icons Color

.themeColorPrimaryTextAndIcons(int)
.themeColorPrimaryTextAndIconsRes(int)

The primary text and icons color is the color used for the texts and icons in the ActionBar/Toolbar across all screens. Pass the color value to the first method (e.g. Color.BLACK) or the resource reference of the color to the second one (e.g. R.color.my_brand_blue).

Secondary Color

.themeColorSecondary(int)
.themeColorSecondaryRes(int)

The secondary color is used on important links, widgets, and actionable components. Pass the color value to the first method (e.g. Color.BLACK) or the resource reference of the color to the second one (e.g. R.color.my_brand_blue).

Backgrounds Color

.themeColorBackgrounds(int)
.themeColorBackgroundsRes(int)

The backgrounds color is used on just a few screens to keep the service branding consistent while keeping the other screens with an appropriate level of contrast. Pass the color value to the first method (e.g. Color.BLACK) or the resource reference of the color to the second one (e.g. R.color.my_brand_blue).

Custom Font

.customFont(String)

The Authenticator SDK (v2.1 and up) allows implementers to provide a .TTF to apply custom fonts to the Views contained in the SDK. The provided string is the path to the .TTF file within the resource "Assets" folder. Example:

...
.customFont("fonts/my_font.ttf")        //.TTF file located in "app/src/main/assets/fonts/my_font.ttf"
...

Note

The Authenticator SDK will apply the font to its own Views so it does not disrupt the implementing service. It's up to the service to handle the Views not part of the Authenticator SDK.

SSL Pinning (Extra Security)

.sslPinning(boolean)

The Authenticator SDK uses SSL for network communication to the LaunchKey Platform API to ensure secure data transmission. However, to protect against eavesdropping and ensure that man-in-the-middle attacks cannot occur over this connection, you can enable SSL pinning which will verify the hostname and SSL certificate returned from the Platform API handshake exactly matches those that are bundled in your Mobile App. If the certificate cannot be verified, all connections to the Platform API are terminated. To turn SSL pinning ON, include the .sslPinning() method in your configuration object and pass a value (boolean) of true to turn on, or false to explicitly turn it off.

Note

SSL pinning is turned OFF by default.

Warning

SSL pinning should only be enabled if you fully understand the consequences of enabling this feature as connectivity to the LaunchKey Platform API can be interrupted if SSL pinning is not properly configured.

Key Pair Size

.keyPairSize(int)

Starting at v2.3, the Authenticator SDK offers the possibility of setting the size of the key pair generated when linking the device. It can be any valid size value from 2048 up to 4096 bits. The value will be set to the closest valid value if outside of that range and/or invalid. If this is not set in the WhiteLabelConfig object, then the default value will be used (4096). There are constants for common values under WhiteLabelConfig.Builder.KEYSIZE_*. Example:

int keyPairSizeBits = 3072;
//or keyPairSizeBits = WhiteLabelConfig.Builder.KEYSIZE_MEDIUM which represents the same value

WhiteLabelConfig config =
    new WhiteLabelConfig.Builder(...)
    ...
    .keyPairSize(keyPairSizeBits)
    ...
    .build();

Note

We recommend using the default value of 4096 setting a high level of security even if it might take longer to generate on older hardware.

Overriding Endpoint (On-Prem Implementations)

.endpoint(String)

The Authenticator SDK (v2.1 and up) allows implementers to override the endpoint when dealing with an On-Prem approach. Most LaunchKey Authenticator service won't need to make use of this flag. Example:

WhiteLabelConfig config =
    new WhiteLabelConfig.Builder(...)
    ...
    .endpoint("api.your.service.com")
    ...
    .build();

Overriding Endpoint And SSL Pinning

.sslCert(String)

If the two flags above are used to enable SSL Pinning for a custom endpoint, then a certificate has to be provided so the connection can be validated accordingly against that certificate. The flag must have the relative path to the .CRT certificate file within the resource "Assets" folder. Example:

WhiteLabelConfig config =
    new WhiteLabelConfig.Builder(...)
    ...
    .endpoint("api.your.service.com")       // Setting a custom endpoint and...
    .sslPinning(true)                       //...enabling SSL Pinning...
    .sslCert("certs/my_cert.crt")           //...while checking against "app/src/main/assets/certs/my_cert.crt"
    ...
    .build();

Linking a Device

This is the first step your Directory users have to go through in order to link the device with a 7-character alphanumeric linking code provided by your service by entering the code or scanning the QR code.

To display one of the two options, make the following call:

mWhiteLabelManager.displayLinkingUi(Context, int);

Where the int argument represents the method of linking the device. Could be LINKING_METHOD_MANUAL or LINKING_METHOD_SCAN.

The default Views used by the Authenticator SDK (v2.1 and up) will prompt the user to enter a custom name for the device they are linking instead of using a auto-generated one based on the manufacturer and model.

Once the device has been successfully linked, the account status will be updated and the user is notified as the linking UI is dismissed automatically. The status of the device can be checked with the WhiteLabelManager.isDeviceLinked() method.

Note

Your Mobile App can also link the User’s device from within your own custom view using an exposed method WhiteLabelManager.registerUser(...) with a valid linking code, and optionally for v2.1 and up, a custom device name.

Interacting With An Auth Request

The Auth Request UI allows your Directory users to authenticate and respond to auth requests from your service by embedding a Fragment in anywhere it's deemed best for the service.

There are two ways to embed the fragment, just like any other fragment contained part of the Authenticator SDK offered to implementors.

Included via XML:

    ...
    <fragment android:name="...android.whitelabel.sdk.ui.AuthRequestFragment"
    android:id="@+id/fragment_authrequest"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
...

Included at Runtime for fragment transactions:

...
Fragment f = new AuthRequestFragment();
...

Once the fragment has been embedded, if push notifications are set, the View will automatically display the Auth Request. If the user interfacts with your custom UI elements to call upon specific actions on the Auth Request, call the following methods:

  • To deny: AuthRequestFragment.deny().
  • To manually check: WhiteLabelManager.checkWithAuthFragment(...) or directly check with the fragment via AuthRequestFragment.checkForPending().

In Authenticator SDK v2.2.1 and up, if in need of a very simple default toolbar to allow the user to deny an Auth Request (potentially when early in the process of developing the service) call AuthRequestFragment.setToolbarVisible(true) to show it along with a request, which is now hidden by default.

In Authenticator SDK v2.3.2 and up, there will NOT be a default Toast shown when the pending Auth Request has expired or is no longer valid once the end user attempts to respond to it. The subscriber can implement their own UI by checking the error object returned in the new interface defined for Account-level events via WhiteLabelManager.AccountStateListener2.

Example:

WhiteLabelManager.AccountStateListener2 eventListener = new
WhiteLabelManager.AccountStateListener2() {

                @Override
                public void onRequestUpdate(boolean hasPendingRequest) {
                        // do something based on whether there is a pending request or not
                }

                @Override
                public void onAuthenticationSuccess(boolean approved) {
                        // do something after user authenticates and responds to a request
                }

                @Override
                public void onAuthenticationFailure(BaseError error) {
                        ...
                        // invalid or expired
                        if (error instanceof ExpiredAuthRequestError) {
                                /*
                                notify the user of an expired or invalid
                                 Auth Request they are responding to.
                                */
                        }
                }

                @Override
                public void onUnlink() {
                        // check user status and display link
                }

                @Override
                public void onLogout() {
                        // do something when user logs out of active sessions
                }
};

mWhiteLabelManager.addAccountStateListener(eventListener);
...
mWhiteLabelManager.removeAccountStateListener(eventListener);

Note

The Auth Request View will only be displayed if the .isDeviceLinked() method returns true meaning the User has successfully linked their device.

Setting Up Security

The Authenticator SDK provides the User with certain auth-related settings through the Auth Modal (e.g. enable/configure authentication factors, log out, un-link device). To display the Settings View in the Auth Modal, make the following call:

mWhiteLabelManager.displaySecurity(Context);

Note

The Security View will only be displayed if the .isDeviceLinked() method returns true, meaning the User has successfully linked their device.

Check Set Security Factors

In Authenticator SDK v2.2 and up, you can use the following call to check which security factors are set and which are active to be used during an Auth Request.

Example:

    SecurityService.SecurityStatusListener listener = new SecurityService.SecurityStatusListener() {

        @Override
        public void onSecurityStatusUpdate(boolean success, List<SecurityFactor> list, BaseError error) {
            //react differently based on the success flag
            //if successful, list of SecurityFactor objects will retain information on set factors
            //if not successful, check error object based on its type
        }
    }

SecurityService securityService = SecurityService.getInstance(Context);
securityService.getStatus(listener);

After getting a hold of the List<SecurityFactor> object, its .size() method will provide the number of set factors. To check for more information on each of them:

  • Compare SecurityFactor.getFactor() with SecurityService.FACTOR_* constants

    for the type.

  • Compare SecurityFactor.getCategory() with SecurityService.CATEGORY_* constants

    for the category.

  • Get true or false by calling SecurityFactor.isActive(). true

    represents that the factor is not only set but also active and will be verified during an Auth Request.

Listening For Specific Events

To ensure proper interaction between your Mobile App and User, it will be necessary for your Mobile App to listen for specific events from the Authenticator SDK such as successful authentication, failed authentication, successful device linking, User logout, etc.

There are three different sets of events to listen for:

  1. Account-level events via WhiteLabelManager.add/removeAccountStateListener(...)

    which notifies when the SDK has checked for pending requests, a request has been responded or failed to, the device has been unlinked, of sessions have been logged out.

  2. Status events via WhiteLabelManager.add/removeStatusListener(...)

    which notifies when the SDK has checked for active sessions for the implementing service to display custom UI and log out of one or more active sessions by calling WhiteLabelManager.logout(...).

  3. Registration events via listener passed when calling WhiteLabelManager.registerUser(...)

    which notifies when the SDK has started preparing the device for the linking process, is verifying the linking code, and once it succeeds or fails.

Example:

WhiteLabelManager.AccountStateListener2 eventListener = new
WhiteLabelManager.AccountStateListener2() {

        @Override
        public void onRequestUpdate(boolean hasPendingRequest) {
            // do something based on whether there is a pending request or not
        }

        @Override
        public void onAuthenticationSuccess(boolean approved) {
            // do something after user authenticates and responds to a request
        }

        @Override
        public void onAuthenticationFailure(BaseError error) {
                            // do something after it failed responding to a request
        }

        @Override
        public void onUnlink() {
            // check user status and display link
        }

        @Override
        public void onLogout() {
            // do something when user logs out of active sessions
        }
};

mWhiteLabelManager.addAccountStateListener(eventListener);
...
mWhiteLabelManager.removeAccountStateListener(eventListener);

WhiteLabelManager.AccountStateListener has been deprecated with the new implementation WhiteLabelManager.AccountStateListener2 in Authenticator SDK v2.3.2 for Android.

Listeners are added and removed from a list of interested parties, so an appropriate approach is to add the listeners during the onResume() method of an Activity or Fragment, and then remove them in onPause() otherwise your service might crash if it's attempting to update the UI when an event is triggered and the View does not exist anymore.

Authorizations List - Optional

While most LaunchKey Authentication implementations will work with just one service, there is always the possibility of having more than one. If that is the case, the authorizations list will come in handy to manage several active sessions and transactions.

There are two ways to go about it:

  1. Easiest: Embed the optional AuthorizationsFragment to display all transactions

    and active sessions. They can also be logged out or cleared by swiping them to either side, notifying the user once confirmed by the server.

    Included via XML:

    ...
    <fragment android:name="...android.whitelabel.sdk.ui.fragment.AuthorizationsFragment"
    android:id="@+id/fragment_authorizations"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
    ...
    

    Included at Runtime for fragment transactions:

    ...
    Fragment f = new AuthorizationsFragment();
    ...
    
  2. Customizable: The most customizable way is to instance the AuthorizationsCenter object via

    AuthorizationsCenter.getInstance() and fetch the updated list of Service objects to implement a fully-custom interface. AuthorizationsCenter allows you to manage all active sessions and transactions associated to the current directory username.

    In order to do that, these steps must be followed: Register listener, refresh to process updated list, call upon any Log Out methods, and unregister listener.

    Example for v2.0+:

    AuthorizationsCenter.AuthorizationsListener authorizationsListener = new AuthorizationsListener {
    
            @Override
            public void onAuthorizationsListUpdate(boolean successful, List<Application> applications, boolean localDelivery) {
                    //update UI with given successful and localDelivery flags, and list of active sessions with the list of service objects
            }
    
            @Override
            public void onApplicationLogOut(boolean successful, boolean wasForced, Application application) {
                    //notify the user a single service might have been logged out, check successful flag
            }
    
            @Override
            public void onAllApplicationsLogOut(boolean successful, boolean includingTransactions) {
                    //notify the user a "clear all" operation might have been made, check successful flag
            }
    };
    
    AuthorizationsCenter authorizationsCenter = AuthorizationsCenter.getInstance();
    ...
    authorizationsCenter.addListener(authorizationsListener);
    ...
    authorizationsCenter.refresh();
    ...
    boolean includingTransactions = true;
    authorizationsCenter.logOutAllApplications(includingTransactions, authorizationsListener);
    ...
    authorizationsCenter.removeListener(authorizationsListener);
    

    Example for v2.2+: Improved error handling in callbacks.

    AuthorizationsListener2 authorizationsListener = new AuthorizationsListener2 {
    
            @Override
            public void onAuthorizationsListUpdate(boolean successful, List<Application> applications, boolean localDelivery, BaseError error) {
                    //update UI with given successful and localDelivery flags, and list of active sessions with the list of service objects
                    //if successful is false, the BaseError object can be checked to react differently based on the type
            }
    
            @Override
            public void onApplicationLogOut(boolean successful, boolean wasForced, Application application, BaseError error) {
                    //notify the user a single service might have been logged out, check successful flag
                    //if successful is false, the BaseError object can be checked to react differently based on the type
            }
    
            @Override
            public void onAllApplicationsLogOut(boolean successful, boolean includingTransactions, BaseError error) {
                    //notify the user a "clear all" operation might have been made, check successful flag
                    //if successful is false, the BaseError object can be checked to react differently based on the type
            }
    };
    
    ...
    //same AuthorizationCenter calls for adding and removing the new listener
    ...
    

Note

Check the Error Handling (v2.2+) section for an explanation on the BaseError objects returned in v2.2+ calls.

Interacting With Time-based One-Time Passwords - Optional

The Authenticator SDK allows you support Time-based One-Time Passwords (TOTPs) in your White Label service by making use of the OtpCenter manager. There are two ways of making use of TOTPs:

  1. Easiest: Embed the optional TotpsFragment to display all TOTPs along with an

    exposed method showAddOptions() to let the user add the service, account, and secret by manually-entering that information or scanning a valid QR code.

  2. Customizable: Instance the OtpCenter object via

    OtpCenter.getInstance() and fetch the updated list of Otp objects in OtpList to implement a fully-custom interface. Call upon OtpCenter's static method getTokenForOtp(Otp) to generate its token, and newFromUri(String) to generate a new one from the URI.

    Example:

    OtpCenter.OtpLoaderListener loader = OtpCenter.OtpLoaderListener {
    
            @Override
            public void onOtpsLoaded(OtpList otpList) {
                    List<Otp> otps = otpList.otps;
                    //update UI with list of Otp devices: otps
            }
    };
    
    OtpCenter otpCenter = OtpCenter.getInstance(Context);
    otpCenter.getOtps(loader);
    ...
    //every 30 seconds
    String token = OtpCenter.getTokenForOtp(singleOtp);
    ...
    //create a new OTP
    Otp newOtp = OtpCenter.newFromUri(otpUri);
    addNewOtpToOtpList(newOtp);
    

Warning

If implementing a custom user interface, then it is your responsibility to automatically refresh the codes from the TOTPs since they are only valid for 30 seconds!

Interacting With Linked Devices - Optional

All directory users have the possibility of linking more than one device with valid linking codes, and to allow them to manage their devices, the Authenticator SDK offers the DeviceCenter manager to list all linked devices and even unlink the current device. There are two ways to make that happen:

  1. Easiest: Embed the optional DevicesFragment to display all devices by name

    including the current one, which they can unlink. That way DeviceCenter will not be necessarily used since the Fragment will handle action on devices.

  2. Customizable: Instance the DeviceCenter object via

    DeviceCenter.getInstance() and fetch the updated list of Device objects to implement a fully-custom interface. Starting with v2.1, DeviceCenter can unlink other devices under the current username by calling DeviceCenter.unlink(...) and passing the Device object to unlink as one of the arguments.

    In order to do that, three steps must be followed: Register listener, refresh to process updated list asynchronously, and unregister listener.

    Example for v2.0+:

    DeviceCenter.DevicesListener devicesListener = new DeviceCenter.DevicesListener {
    
            @Override
            public void onDevicesUpdate(List<Device> devices) {
                    //update UI with list of Device objects
                    //check each Device object like Device.getStatus() against Device.STATUS_* constants.
            }
    
            @Override
            public void onDeviceUnlink(boolean wasUnpaired, int cause) { ... }
    };
    
    DeviceCenter deviceCenter = DeviceCenter.getInstance();
    ...
    deviceCenter.addListener(devicesListener);
    ...
    deviceCenter.refresh();
    ...
    deviceCenter.removeListener(devicesListener);
    

    Example for v2.2+: Improved error handling in callbacks.

    DeviceCenter.DevicesListener2 devicesListener = new DeviceCenter.DevicesListener2 {
    
            @Override
            public void onDevicesUpdate(boolean successful, List<Device> devices, BaseError error) {
                    //update UI with list of Device objects
                    //check each Device object like Device.getStatus() against Device.STATUS_* constants.
                    //if successful is false, the BaseError object can be checked to react differently based on the type
            }
    
            @Override
            public void onDeviceUnlink(boolean wasUnlinked, BaseError error) {
                    //update UI with list of Device objects
                    //if wasUnlinked is false, the BaseError object can be checked to react differently based on the type
            }
    };
    
    ...
    //same DeviceCenter calls for adding and removing the new listener
    ...
    

Note

Check the Error Handling (v2.2+) section for an explanation on the BaseError objects returned in v2.2+ calls.

Interacting With Logs - Optional

All directory users have a list of logs based on their response to authorizations generated by services. These contain information on the service used for the auth request, time of response, whether it was approved or not if it was a session request, extra information aka "Context", etc. The Authenticator SDK offers the LogCenter manager to list all log entries associated with the current directory username.

There are two ways to make that happen:

  1. Easiest: Embed the optional LogsFragment to display all log entries without the need

    of LogCenter.

  2. Customizable: Instance the LogCenter object via

    LogCenter.getInstance() and fetch the updated list of Log objects to implement a fully-custom interface.

    In order to do that, three steps must be followed: Register listener, refresh to process updated list asynchronously, and unregister listener.

    Example for v2.0+:

    LogCenter.LogsListener logsListener = new LogCenter.LogsListener {
    
            @Override
            public void onLogsUpdate(List<Log> logs) {
                    //update UI with list of Log objects
            }
    };
    
    LogCenter logsCenter = LogCenter.getInstance();
    ...
    logsCenter.addListener(logsListener);
    ...
    logsCenter.refresh();
    ...
    logsCenter.removeListener(logsListener);
    

    Example for v2.2+: Improved error handling in callbacks.

    LogCenter.LogsListener2 logsListener = new LogCenter.LogsListener2 {
    
            @Override
            public void onLogsUpdate(boolean successful, List<Log> logs, BaseError error) {
                    //update UI with list of Log objects
                    //if successful is false, the BaseError object can be checked to react differently based on the type
            }
    };
    
    ...
    //same LogCenter calls for adding and removing the new listener
    ...
    

Note

Check the Error Handling (v2.2+) section for an explanation on the BaseError objects returned in v2.2+ calls.

Error Handling (v2.2+)

With the Authenticator SDK v2.2 and up, there's an improved error handling for implementers. The BaseError objects is returned in many of the callbacks when interacting with the LaunchKey APIs from which all error objects are derived. Here's a comprehensive list of all error objects:

  1. BaseError: Base class of all error objects. Errors returned in the raw class are considered unknown/unexpected, so attempting to react to the other error objects first it's recommended before assuming it's a sole BaseError object.
  2. NoInternetConnectivityError: Error object representing the obvious lack of Internet connectivity on the device. This will allow the implementing app to either make extra connectivity checks and then try again, or notify the user of the current connectivity conditions.
  3. DeviceNotLinkedError: Error object returned when the device is required to be linked before performing the requested action.
  4. InvalidLinkingCodeError: Error object returned when attempting to link the device with an incorrect or expired linking code via WhiteLabelManager.registerUser(...). Keep in mind that the linking code will not make sense to the directory involved if the Authenticator SDK key is wrong, so always double check that the SDK key matches the one given by Dashboard.
  5. GcmSetupError: Error object returned when attempting to link the device via WhiteLabelManager.registerUser(...) with a correct linking code but the Google Cloud Messaging (GCM) setup for push notification is failing. Verify the GCM setup is correct and matches your credentials and what's instructed by GCM's official documentation.
  6. ExpiredAuthRequestError: Error object returned when the Auth Request the user is attempting to respond to has already expired.
  7. DeviceNotFoundError: Error object returned when attempting to unlink a Device object that does not exist (this could also happen when attempting to unlink a device that has already been unlinked).
  8. RequestArgumentError: Error object returned when an operation requires a specific argument either by the implementer or even internally in very uncommon conditions.
  9. CommunicationError: Error object returned when it is not an expected response from the Platform API. getCode() method will return the HTTP status code whenever available to properly handle error messages resulting in connectivity errors.

Implementing Push Notifications - Optional

Although optional, we recommend using push notifications in your Mobile App to provide a better user experience. With push notifications, The Platform will push alerts to your User’s device to notify them of pending Auth Requests from your service. To use this feature, follow these steps:

Warning

Push notifications are dependent upon the proper function of the Android push notification system and your user’s mobile carrier. Slowdowns, outages, or other problems may affect the speed and ability of your user’s mobile device to receive push notifications. Therefore, in addition to push requests, it’s highly recommended that you provide a manual option for your user to check for pending Auth Requests within your mobile app.

Additions to Android Manifest

First, you’ll need to make some additions to the AndroidManifest.xml file. Place these permissions on the same level as normal permissions:

<!—- GCM-required package-based permissions —->
<permission android:name="<YOUR PACKAGE>.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="<YOUR PACKAGE>.permission.C2D_MESSAGE" />
<!—- All other GCM-required permissions are part of the SDK manifest and will be merged by Android —->

Then place these within the <application> tag which is part of the same Android Manifest XML file:

<!-- GCM's own service that will handle upcoming push notifications -->
<receiver
    android:name="com.google.android.gms.gcm.GcmReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="<YOUR PACKAGE>" />
    </intent-filter>
</receiver>

<!-- the Authenticator SDK's service to process push notification -->
<service
    android:name="...android.whitelabel.sdk.gcm.GcmNotificationService"
    android:exported="false" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>

<!-- the Authenticator SDK's service to handle the update of the device-level GCM token -->
<service
    android:name="...android.whitelabel.sdk.gcm.GcmInstanceIdListenerService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.android.gms.iid.InstanceID"/>
    </intent-filter>
</service>

<!-- the Authenticator SDK's service to update the server's with the new GCM token -->
<service
    android:name="...android.whitelabel.sdk.gcm.GcmNotificationRegistrar"
    android:exported="false">
</service>

<!-- Google Play Services' required version declaration -->
<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />

Where <YOUR PACKAGE> is your Mobile App’s package (e.g. you.package.here). This code references a couple of SDK classes to process the push notifications that will be sent to your Mobile App.

Generate Server & Android API Keys

Next, you’ll need to generate a Server and Android API Key from the Google Developer Console. To do so, follow these steps:

  1. Go to https://console.developers.google.com and create or open an existing project

  2. Under API Manager, navigate to the Enabled APIs tab to make sure the Google Cloud Messaging for Android API is enabled. If it’s not part of the list, add this API from the Google APIs tab.

  3. Next, to generate the key for the Android app and the server, navigate to Credentials, and then click Create credentials > API key.

  4. Choose Server Key, and then Create, and the list of API keys should be updated with

    the new key for Server Applications and all IPs allowed. More details on the IPs is up to the implementer.

  5. Finally, click Create credentials > API key, and choose Android Key and add required input before clicking Create. The list of API keys should be updated with a new key for Android Applications and its debug/production build certificate fingerprints and package.

Note

Remember, the debug certificate has a different fingerprint so it needs to be included at the time the Android service key is generated to make sure the debug builds also receive push notifications.

Add Android API Key to Android Project

Google Play Services require you in the newer versions to let the Google Play Services plug-in handle the information on the project after you download their Google-generated JSON file google-services.json to place at the application folder ("app" by default).

For more information on the newer implementation of Google Play Services, visit the official website with the guides: https://developers.google.com/cloud-messaging/android/client

If you are indeed using a newer version, skip to the next section. Otherwise, continue reading.

Next, add the Android API Key from the previous step to your Android Project. This will allow your Mobile App to register for Push Notifications from Google Cloud Messaging since your Mobile App will be authorized with the provided package and cert fingerprint.

  1. Open your project

  2. Navigate to the values folder under the res folder and create a new resource file such as whitelabel.xml with a String value that will contain the Project Number from your project overview in the Google Developers Console under the key whitelabel_gcm_sender_id. It should look similar to this:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="whitelabel_gcm_sender_id">123456789012</string>
    </resources>
    

    This key will be automatically retrieved by the Authenticator SDK. It’s also important to make sure that the Project Number string is part of the resources of your project.

Add Server API Key to directory

Next, add the Server API Key to your directory. Log into Dashboard and click on Organizations to navigate to your Organization details page. Finally, click on the relevant group under the directory*s section and add your Server API Key to the *Android Server API Key field.

Intercepting Push Notification to Trigger Auth Request View

Finally, to ensure your service creates the appropriate notification in the status bar at the top to notify the user of an incoming request, a BroadcastReceiver will listen for an event broadcast by the Authenticator SDK internally in the application via LocalBroadcastManager. Make use of the publicly-declared action in WhiteLabelManager.

Example:

BroadcastReceiver requestReceiver = new BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
                //create status bar notification
        }
};

IntentFilter requestFilter = new IntentFilter(WhiteLabelManager.ACTION_EVENT_REQUEST_INCOMING);
LocalBroadcastManager.getInstance(this).registerReceiver(requestReceiver, requestFilter);

Note: This is usually done in the Application-level class

Enable Google Maps for Geo-Fencing

One of the authentication factors available to Users is geo-fencing. Users can define one or many geo-fences, and when enabled, their mobile device will ensure that it’s located within these bounds before allowing authorization to proceed. To configure this factor, your Mobile App will need access to Google Maps. To ensure your Mobile App has this access, do the following:

  1. Navigate to https://console.developers.google.com and modify the project related to your Mobile App.

  2. Enter the project and navigate to APIs under API Manager. Make sure Google Maps Android API v2 is listed in the Enabled APIs tab, and if it isn’t, add it from the Google APIs tab.

  3. Go to Credentials under API Manager. If there is already an Android key generated for your service, skip to step 5

  4. Click Create credentials and choose API key > Android Key. Follow the

    instructions to enter your application’s cert fingerprint and package before clicking Create.

  5. The key generated for your Android app has to be included in your Android Manifest

    within the <application> tag, just before it closes, as a meta-data element like this:

    <meta-data android:name="com.google.android.geo.API_KEY" android:value="API_KEY_HERE" />
    

    Where API_KEY_HERE should be replaced with your Android Key which should look like something similar to AIzaSyBdVl-cTICSwYKrZ95SuvNw7dbMuDt1KG0

With this in place, your Mobile App should now be able to make use of the Google Maps API for Android. The permissions are included in the SDK, but if you experience any problems, refer to the official Getting Started documentation for Google Maps API v2 for Android at https://developers.google.com/maps/documentation/android/start

Performing Actions Directly In Your App - Optional

The Authenticator SDK exposes certain methods involving logging out of active sessions, linking the device (user registration), and device unlinking. With this capability, you can use your own user interface instead of relying on default Views included in the Authenticator SDK.

Checking For Active Sessions

To check for active sessions, from which the user can log out of, a call can be made directly on the manager via WhiteLabelManager.hasActiveSessions(). Note: This method has been deprecated starting v2.2.1 in favor of the existing, recommended approach of registering and unregistering a WhiteLabelManager.SessionListener implementation via WhiteLabelManager.addStatusListener() and WhiteLabelManager.removeStatusListener() respectively. Those calls should be made where it makes sense such as the onResume() and onPause(), onStart() and onStop(), etc. Depends on how the lifecycle of the View is handled.

Example:

WhiteLabelManager.SessionListener sessionListener = new WhiteLabelManager.SessionListener() {

        @Override
        public void onSessionUpdate(boolean hasActiveSessions) {
                //show/hide, enable/disable Views depending on the state to
                // properly convey the current state.
                mLogOutButton.setEnabled(hasActiveSessions);
        }
};
...
mWhiteLabelManager.addStatusListener(sessionListener);
...
mWhiteLabelManager.removeStatusListener(sessionListener);

Logging Out Of Active Sessions

To log out all active sessions for the current User with a default UI, call

mWhiteLabelManager.logOut(Activity/Fragment);

To log out all active sessions for the current User with a custom UI, call the following method with the new LogOutListener object (v2.2+):

    WhiteLabelManager.LogOutListener listener = new WhiteLabelManager.LogOutListener() {

        @Override
        public void onLogOut(boolean success, BaseError error) {
            //dismiss logout dialog
            //react differently with the success flag
            //check error variable if not successful
        }
    }

//show logout dialog

mWhiteLabelManager.logOut(listener);

Note

Check the Error Handling (v2.2+) section for an explanation on the BaseError objects returned in v2.2+ calls.

Unlinking Current Device

To unlink the User’s current device with a default UI, call

mWhiteLabelManager.unlink(Activity/Fragment); //same as calling unlink on current device via DeviceCenter

To unlink the User's current device with custom a custom UI, call the following method with the new UnlinkListener object (v2.2+):

WhiteLabelManager.UnlinkListener listener = new WhiteLabelManager.UnlinkListener() {

    @Override
    public void onUnlink(boolean success, BaseError error) {
        //dismiss unlink dialog
        //react differently with the success flag
        //check error variable if not successful
    }
}

//show unlink dialog

mWhiteLabelManager.unlink(listener);

Note

Check the Error Handling (v2.2+) section for an explanation on the BaseError objects returned in v2.2+ calls.

Device Linking / User Registration

As previously mentioned in the linking section, your Mobile App can also link a device and register a User with your directory. Like linking a device through the included Linking UI, your Mobile App will need to obtain a linking code either by scanning a QR code or by having the User manually enter a 7-character alphanumeric linking code displayed by your external service. Once the linking code is obtained, you can register the User and link their device by calling:

mWhiteLabelManager.registerUser(context, "<LINKING_CODE>", UserRegistrationListener);

Example:

WhiteLabelManager.UserRegistrationListener callback = new
WhiteLabelManager.UserRegistrationListener() {
        @Override
        public void wasSuccess() {
            // notify user of success followed by relevant UI
        }
        @Override
        public void wasFailure(String errorMessage, String errorCode) {
            // notify user of failure and have them retry
        }
}
mWhiteLabelManager.registerUser(context, "abcd123", callback);

Starting with v2.1 there is another method that can be used to provide a custom device name along with a valid linking code to link the device:

mWhiteLabelManager.registerUser(context, "<LINKING_CODE>", "<DEVICE_NAME>", UserRegistrationListener2);

Starting with v2.3, the device name will be stripped of invalid characters. The RegEx used for the linking code and device name will be exposed under WhiteLabelManager.REGEX_* so implementers can optionally include their own error handling, suggestions, or input cleanup before calling the .registerUser(...) function.

Note

Check the Error Handling (v2.2+) section for an explanation on the BaseError objects returned in v2.2+ calls.

Done

The Authenticator SDK has now been configured and added to your Android project. The final step is to integrate the LaunchKey Platform API within your Service using one of the SDKs.

User Contributed

LaunchKey links to user contributed code as a resource to its community. LaunchKey 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 LaunchKey immediately and we will investigate the claim. Submit any issue to LaunchKey support at https://launchkey.com./support. ×