Android

This quickstart guide serves as an integration example for our trusted partners so that you will be able to test and/or evaluate LoginID’s authentication service for your own needs.

This document assumes that you are using Java/Kotlin in your development environment.

It's recommended that you try our demo Android app prior to following this documentation:

Steps to follow

Useful API SDKs

  1. Login

  2. Logout

Create your API keys

The first step to onboard yourself with LoginID is to create your client credentials. This allows your servers to call LoginID services in an authenticated fashion.

Install LoginID SDK for your Build Environment

This section of the documentation is related to the configuration of your Android Studio environment.

Generally, you will need to follow the below steps to install LoginID SDKs:

  1. Create a new Android project or use a pre-existing project, and

  2. Get LoginID package in your Android studio by a) including our repository and b) specifying the latest package name and version to be downloaded.

The LoginID SDK requires min Android 5+ (API 21+) for compatibility. However, the core FIDO2 Client of LoginID SDK will only work with Android 7+ (API 24+) devices.

Add LoginID maven repository and credentials to your Android main project build.gradle. This will let you add the configuration to the code.

allprojects {
repositories{
google()
jcenter()
// ADD maven repository to download LoginSDK
maven {
url "https://sdk.dev.loginid.io/repository/maven-releases/"
}
}
}

Add the following packages to your Android app module build.gradle dependencies

implementation 'login.api.native:android-sdk:0.91.37'

Getting Started with LoginID API SDK:

To see an overview of the Android API SDK, please see:

Configure LoginID API

This is the initialization process for our SDK allowing you to inject API keys through the SDK so LoginID can recognize you as a client by passing below parameters:

LoginApi.client().configure(Context context, String clientId, String baseURL)

Using the above parameters, LoginID will then be able to recognize all subsequent calls without the need for clients to re-enter information going forward.

As a pre-requisite, you need to configure the SDK with your client API key and baseURL obtained from LoginID's developer console. This API must be called before any other APIs. You should call this API within your custom Application's onCreate() method. You can find more information on the process of creating a custom application on Understanding the Android Application Class.

Kotlin
Java
Kotlin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// clientId example 032690b3-9bc4-4602-87c1-60c1fae782f2
val clientId = "<your client api key>"
// baseURL example https://060ce487-b934-43d0-a925-b66e80c7532.native-api.auth.company.id
val baseURL = "<your base url>"
LoginApi.client().configure(this,clientId,baseURL)
// any other configurations
...
...
}
}
Java
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// clientId example 032690b3-9bc4-4602-87c1-60c1fae782f2
final String clientId="<your client API key>";
// baseURL example https://060ce487-b934-43d0-a925-b66e80c7532f.loginid.io
final String baseURL="<your base url>";
LoginApi.client().configure(this,clientId,baseURL);
// any other configurations
...
...
}
}

Checking Device Compatibility

LoginID FIDO SDK is supported on Android devices 7+ (Nougat and up). You can use checkFidoCapability to ensure that the user device has the necessary hardware to support FIDO authentication. If such support is not available or if the user has not enrolled for biometric verification, you can prompt the user to a fallback authentication flow or display an error message.

API to check whether FIDO is supported:

/**
This API return the FidoCapabilty enum
possible return value:
FIDO_SUPPORTED
FIDO_SUPPORTED_MISSING_ENROLMENT
FIDO_NOT_SUPPORTED
FIDO_NOT_AVAILABLE
*/
FidoCapability LoginApi.client().checkFidoCapability(Context context)

API to check which biometric types are supported:

/**
This API return the list of biometrics types supported for FIDO authentication.
possible return values are:
Fingerprint
Iris
Face
*/
List<String> LoginApi.client().getFidoSupportedBiometricsTypes(Context context)

The example below demonstrates the usage of the functions above to check for device compatibility prior to sending the user to the FIDO authentication flow:

Kotlin
Java
Kotlin
val capability = LoginApi.client().checkFidoCapability(this)
when (capability) {
FidoCapability.FIDO_SUPPORTED -> {
// proceed to fido register or login operation
// ..
// ..
}
FidoCapability.FIDO_SUPPORTED_MISSING_ENROLMENT -> {
// user is missing biometric enrolment
// get the list of supported FIDO biometrics
val featureList = LoginApi.client().getFidoSupportedBiometricsTypes(this)
// pop message inform user to enroll to the list of supported hardware Fingerprint, Iris, or FaceID
// ..
// ..
}
FidoCapability.FIDO_NOT_SUPPORTED -> {
// fido is not supported prompt user to fallback authentication flow
// ..
// ..
}
FidoCapability.FIDO_NOT_AVAILABLE -> {
// fido is not available prompt user to retry later
// ..
// ..
}
}
Java
FidoCapability capability = LoginApi.client().checkFidoCapability(this);
switch (capability){
case FIDO_SUPPORTED:
// proceed to fido register or login operation
// ..
// ..
break;
case FIDO_SUPPORTED_MISSING_ENROLMENT:
// user is missing biometric enrolment
// get the list of supported FIDO biometrics
List<String> featureList =LoginApi.client().getFidoSupportedBiometricsTypes(this);
// pop message inform user to enroll to the list of supported hardware Fingerprint, Iris, or FaceID
// ..
// ..
break;
case FIDO_NOT_SUPPORTED:
// fido is not supported prompt user to fallback authentication flow
// ..
// ..
break;
case FIDO_NOT_AVAILABLE:
// fido is not available prompt user to retry later
// ..
// ..
break;
}

Getting User Account Information

For an overview of LoginID registration flow of our API, please see:

Here is a set of functions for retrieving user information and login status.

Check if the user has an existing registered account:

Kotlin
Java
Kotlin
// return true or false
val result = LoginApi.client().hasAccount()
Java
// return true or false
boolean result = LoginApi.client().hasAccount();

Get the current username:

Kotlin
Java
Kotlin
// return username in string value
val username = LoginApi.client().getCurrentUsername()
Java
// return username in string value
String username = LoginApi.client().getCurrentUsername();

Check if the user has an active login session:

Kotlin
Java
Kotlin
// return true or false
val result = LoginApi.client().isLoggedIn()
Java
// return true or false
boolean result = LoginApi.client().isLoggedIn();

Get the current access token which is the latest JWT token returned by the server after a successful registered or verified API is called:

The returned JWT indicates successful login or registration and can be used to give access to your users for certain activities of your choice, for example, access to a cloud file.

Kotlin
Java
Kotlin
// return JWT in string value
val token = LoginApi.client().getCurrentToken()
Java
// return JWT in string value
String token = LoginApi.client().getCurrentToken();

Here is an example of how to use the above functionality:

Kotlin
Java
Kotlin
if(LoginApi.client().hasAccount()){
// get current username example
val username = LoginApi.client().getCurrentUsername()
// check if user has active login session
if(LoginApi.client().isLoggedIn()){
// get current token example
val token = LoginApi.client().getCurrentToken()
...
} else {
//present login option here
...
}
...
} else {
// user has no account so can setup register user logic here
...
}
Java
if(LoginApi.client().hasAccount()){
// get current username example
String username = LoginApi.client().getCurrentUsername();
// check if user has active login session
if(LoginApi.client().isLoggedIn()){
// get current token example
String token = LoginApi.client().getCurrentToken();
...
} else {
//present login option here
...
}
...
} else {
// user has no account so can setup register user logic here
...
}

Register an Account with Username Specified

LoginApi.client().registerWithUsername(
Activity activity,
String username,
RegisterCallback callback);

Using Android biometric API requires the use of FragmentActivity instead of Activity class. This can be done by making sure you are calling activity extends the common activity API such as androidx.appcompat.app.AppCompatActivity or androidx.app.fragment.FragmentActivity

This API allows the user to create new credentials with usernames via a FIDO2 registration. Having a username registered will allow the user to login by username from multiple platforms.

Kotlin
Java
Kotlin
val registerCallback= object: RegisterCallback {
override fun onComplete(response: RegisterResponse) {
if (response.success) {
// example handle success case here
Toast.makeText(
this@MainActivity,
"Register Success!!! " + response.jwt,
Toast.LENGTH_LONG
).show()
} else {
// example handle failed case here
Toast.makeText(this@MainActivity, "Register Failed!!! " + response.errorMessage, Toast.LENGTH_LONG)
.show()
}
}
}
LoginApi.client().registerWithUsername(this@MainActivity,username,registerCallback)
Java
final RegisterCallback registerCallback=new RegisterCallback() {
@Override
public void onComplete(RegisterResponse response) {
if(response.success){
// handle success case here
} else {
// handle error case here
Log.e(TAG,response.errorMessage);
}
}
};
LoginApi.client().registerWithUsername(this, username, registerCallback);

Login or re-authenticate a registered account

Once the user has successfully registered, LoginID will assign a JWT token to the response field. The token has a timestamp associate with it. You can ask the user to re-authenticate at any time afterward based on your business logic or if the token has expired.

Login to a Previously Registered Account:

LoginApi.client().login(
Activity activity,
LoginCallback callback);

Using Android biometric API requires the use of FragmentActivity instead of Activity class. This can be done by making sure you are calling activity extends the common activity API such as androidx.appcompat.app.AppCompatActivity or androidx.app.fragment.FragmentActivity

This API allows the users to authenticate or re-authenticate via a FIDO2 login operation. Should be called when the previous access token is expired or invalid.

Kotlin
Java
Kotlin
val loginCallback= object : LoginCallback {
override fun onComplete(response: LoginResponse) {
if(response.success){
// sample handling success case
Toast.makeText(this@MainActivity,"Verify Success!!!" + response.jwt, Toast.LENGTH_LONG).show()
...
} else{
//handle error case here
Toast.makeText(this@MainActivity,"Verify Failed!!! - " + response.errorMessage, Toast.LENGTH_LONG).show()
...
...
}
}
}
LoginApi.client().login(this@MainActivity,loginCallback)
Java
final LoginCallback loginCallback=new LoginCallback() {
@Override
public void onComplete(LoginResponse response) {
if(response.success){
// handle success case here
...
...
} else {
// handle error case here
Log.e(TAG,response.errorMessage);
...
...
}
}
};
LoginApi.client().login(MainActivity.this,loginCallback);

Login with Username Specified:

LoginApi.client().login(
Activity activity,
String username,
LoginCallback callback);

This API allows you to signed into a specific account. Use this in a scenario where you want to support multiple registered accounts on the same device.

Kotlin
Java
Kotlin
val loginCallback= object : LoginCallback {
override fun onComplete(response: LoginResponse) {
if(response.success){
// sample handling success case
Toast.makeText(this@MainActivity,"Verify Success!!!" + response.jwt, Toast.LENGTH_LONG).show()
...
...
} else{
//handle error case here
Toast.makeText(this@MainActivity,"Verify Failed!!! - " + response.errorMessage, Toast.LENGTH_LONG).show()
...
...
}
}
}
// username passed from textfield input
LoginApi.client().login(this@MainActivity,username,loginCallback)
Java
final LoginCallback loginCallback=new LoginCallback() {
@Override
public void onComplete(LoginResponse response) {
if(response.success){
// handle success case here
...
...
} else {
// handle error case here
Log.e(TAG,response.errorMessage);
...
...
}
}
};
// username passed from textfield input
LoginApi.client().login(MainActivity.this,username,loginCallback);

Transaction Confirmation

High-level Flow

Please refer to the transaction confirmation flow for more details:

Integration Phases

There are 3 phases in integrating the transaction confirmation with LoginID (please refer to above flow for more detail):

  1. Transaction creation: Your platform creates the actual transaction and sends the transaction detail to LoginID.

  2. Transaction signing: This phase refers to all backend transactions related to getting end users to sign transactions through FIDO. The majority of this phase is done through LoginID SDK itself.

  3. Client verification: This phase refers to the validation activities done by the client to match the signed transactions against the original transaction performed by the end user. Such validation will need to be performed on the client side.

Transaction Signing

Below is a sample code on how to make a transaction confirmation API call as related the phase 2, Transaction signing:

Kotlin
Java
Kotlin
val txCallback = TransactionConfirmationCallback { response ->
if (response.success) {
// handle success case here
// send response.jwt token value to server for validation
Log.e(TAG,response.jwt)
//...
//...
} else {
// handle failure case here
Log.e(TAG,response.errorMessage)
//...
//...
}
}
val payload = TransactionPayload.buildText("nonce value here", "transaction message here")
LoginApi.client().transactionConfirmation(this@MainActivity, payload, txCallback)
Java
final TransactionConfirmationCallback txCallback = new TransactionConfirmationCallback() {
@Override
public void onComplete(@NonNull TransactionConfirmationResponse response) {
if (response.success) {
// handle success case here
// send response.jwt token value to server for validation
Log.e(TAG,response.jwt);
//...
//...
} else {
// handle failure case here
Log.e(TAG,response.errorMessage);
//...
//...
}
}
};
TransactionPayload payload = TransactionPayload.buildText("nonce value here", "transaction message here");
LoginApi.client().transactionConfirmation(MainActivity.this, payload, txCallback);
  • Nonce: unique ID generated by the client to represent the transaction in string format

  • Transaction Message: Message related to the transaction that will be confirmed by the user's FIDO operation in string format

  • txCallback: Handler to handle the result of the transaction

Here is the code sample on how to make a transaction confirmation API call when the user is not logged in:

Kotlin
Java
Kotlin
val txCallback = TransactionConfirmationCallback { response ->
if (response.success) {
// handle success case here
// send response.jwt token value to server for validation
Log.e(TAG,response.jwt)
//...
//...
} else {
// handle failure case here
Log.e(TAG,response.errorMessage)
//...
//...
}
}
val payload = TransactionPayload.buildText("nonce value here", "transaction message here")
LoginApi.client().transactionConfirmation(this@MainActivity, username, payload, txCallback)
Java
final TransactionConfirmationCallback txCallback = new TransactionConfirmationCallback() {
@Override
public void onComplete(@NonNull TransactionConfirmationResponse response) {
if (response.success) {
// handle success case here
// send response.jwt token value to server for validation
Log.e(TAG,response.jwt);
//...
//...
} else {
// handle failure case here
Log.e(TAG,response.errorMessage);
//...
//...
}
}
};
TransactionPayload payload = TransactionPayload.buildText("nonce value here", "transaction message here");
LoginApi.client().transactionConfirmation(MainActivity.this, username, payload, txCallback);

Client Verification

To verify the transaction, both LoginID and the Client have responsibilities. Once LoginID provides the JWT to the Client, the following steps must be performed by the Client to ensure the JWT, which summarizes the details of the verified transaction, is signed by LoginID. This is a standard JWT verification process, by which the JWT is verified with LoginID's verification public key.

Please follow the steps outlined on this page to complete the client verification:

Logout

Call logout operation to invalidate the current access token.

Kotlin
Java
Kotlin
LoginApi.client().logout()
Java
LoginApi.client().logout();