Skip to main content
Version: v6

Protecting app logins

In this how-to, you will learn how to integrate the Incognia Transaction API to improve the recognition of trusted users at login without adding friction to the user experience. You will be able to automatically approve trusted login attempts, trigger step-up authentication, and block suspicious logins.

Requirements#

Step-by-step#

Setting the Account ID on the app#

In order to verify a login attempt, Incognia needs to have an association between a device and a unique account identifier. The Account ID is used for this purpose.

To make this association, call the Incognia.setAccountId method whenever a user is authenticated and a user identifier is available on your application and a Incognia.clearAccountId when the user logs out.

// Set the Account IDIncognia.setAccountId(accountId)

warning
While data such as e-mail and phone numbers are examples of identifiers, their use in the SDK is forbidden. Consider using non-personal information, such as UUIDs, and Hashing to securely generate and set the Account ID.

Forwarding the device's Installation ID to your server#

To verify a login attempt, Incognia needs to receive an Installation ID to identify the device from which the login originates. Since your server will request the Incognia API to assess the risk of this login, it needs to receive this information from your mobile application.

The installation ID can be forwarded to your server in two ways.

Option 1: Sending the Installation ID as a header#

Before sending a login request from your mobile application to your server, call Incognia.getInstallationId and set its value as a header of the request. We encourage you to choose a clear name for this header, like Incognia-Installation-ID, so you can easily identify it on the server-side.

This option has a clear benefit if your application will use more than one Incognia solution because you won't need to change each request's properties, like signup, login, payment, password change, etc.

// This method may return null if the SDK has not yet been initialized or if an error occurs on initialization.val installationId = Incognia.getInstallationId()
// HttpURLConnectionhttpUrlConnection.setRequestProperty("Incognia-Installation-ID", installationId)
// Send the request with the installationId to your backend server

Option 2: Sending the Installation ID in the body of the request#

Before sending the login request from your mobile application to your server, call Incognia.getInstallationId and send it as additional information about this login. We suggest that you choose a clear name for this property like Incognia-Installation-ID, so you can easily identify it on the server-side.

Handling the user's login request#

When your server receives a login request, you can use Incognia intelligence to assess the risk of this login attempt inside this request/response cycle.

To evaluate this login attempt risk, your server will request the Transaction API informing that a login attempt was made alongside its Installation ID and the Account ID of the account that the device is attempting to access.

A sample implementation of a controller/handler#

Let's consider a toy example as back-end with the controller below:

// LoginController.java@Controller("/login")public class LoginController {  private final PasswordAuthenticator passwordAuthenticator;  private final TokenGenerator tokenGenerator;
  @Post  public HttpResponse<?> postLogin(@Valid @Body LoginRequest request) {    boolean isPasswordValid = passwordAuthenticator.isValid(request.getEmail(), request.getPassword());    if (isPasswordValid) {      Token token = tokenGenerator.getTokenForUser(request.getEmail());      return HttpResponse.ok(token);    }    return HttpResponse.unauthorized();  }}
important
You are required to authenticate when using the Incognia API. For authentication details, see Authenticating in Incognia APIs

Considering that the authentication logic is implemented, you can add risk assessment requests to your login handler:

// LoginController.java@Controller("/login")public class LoginController {  private final PasswordAuthenticator passwordAuthenticator;  private final TokenGenerator tokenGenerator;  // read how to use Incognia's Java Wrapper: https://github.com/inloco/incognia-api-java  private final IncogniaAPI incogniaAPI;
  @Post  public HttpResponse<?> postLogin(@Valid @Body LoginRequest request) {    boolean isPasswordValid = passwordAuthenticator.isValid(request.getEmail(), request.getPassword());    if (isPasswordValid) {      var riskAssessment = api.registerLogin(request.getIncogniaInstallationId(), request.getAccountId()).getRiskAssessment();      if (riskAssessment.equals(Assessment.HIGH_RISK)) {        // Automatically denies if Incognia gives high risk!        return HttpResponse.unauthorized();      }      Token token = tokenGenerator.getTokenForUser(request.getEmail());      return HttpResponse.ok(token);    }    return HttpResponse.unauthorized();  }}

Using the Incognia risk assessment#

When your server makes a request to the Transaction API endpoint, it will receive a response like the following:

{  "id": "936af478-3602-4775-9cd3-5981ce51cfc8",  "risk_assessment": "low_risk",  "evidence": {    "device_model": "moto g(10)",    "known_account": true,    "location_services": {      "location_permission_enabled": true,      "location_sensors_enabled": true    },    "device_integrity": {      "probable_root": false,      "emulator": false,      "gps_spoofing": false,      "from_official_store": true    },    "device_fraud_reputation": "unknown",    "device_behavior_reputation": "unknown",    "account_integrity": {      "recent_high_risk_assessment": false    },    "first_device_login_at": "2021-12-15T17:18:39.310051Z",    "first_device_login": false  }}

The response contains the id of the created entity (in this case, a login), the risk_assessment provided by Incognia based on device behavior, and evidence that supports this assessment. You can learn more about all the returned data in this article: Understanding risk assessments.

The returned assessment can be used with other risk-related data, such as in a risk engine, to decide if this login should be accepted. Incognia's risk assessments include:

  • high_risk: the login performed by the device may be fraudulent and we advise you to take preventive actions in these scenarios, such as requiring additional step-up authentication or simply blocking this login attempt;
  • low_risk: the login performed by the device seems to be safe to accept;
  • unknown_risk: we are unable to provide a precise assessment at the time of the request. You should require additional authentication (e.g. 2FA).
tip
You can identify login attempts coming from new devices and handle them differently based on Incognia risk assessments, see Secure and frictionless device change

Wrapping Up#

After these steps, your application is ready to recognize trusted users at login without friction and preventing account takeovers.