What does LinOTP’s API-first development mean for you?

LinOTP – the open source MFA solution – is developed with an API-first strategy in mind. For us at KeyIdentity this does not mean to dogmatically follow each and every REST guideline but to think about the easiest yet most flexible way of introducing new features to our API in terms of simplicity of integration before the feature is actually implemented, while remaining backwards compatibility. Therefore, our API for all of our customers is feature complete.
For an integration product such as LinOTP, an easy integration into the user’s environment is probably the most important key feature. While historically LinOTP’s most used integration practice is based on the RADIUS protocol together with the FreeRADIUS server shipped with the KeyIdentity LinOTP Smart Virtual Appliance (SVA), the HTTP based API recently gains more and more importance. Especially for web applications LinOTP’s HTTP based API allows for easier and deeper integrations.
LinOTP features a stateless HTTP based API for validation, returning responses in the simple-to-parse JSON format. Request parameters may be sent as URL encoded data in a POST request’s body. This article will show what the API-first strategy means for you and how to integrate LinOTP into your own web applications.
To demonstrate LinOTP’s API by example, we show you how to integrate the QR Token into your environment.

How to integrate the KeyIdentity QR Token into your web application

The KeyIdentity QR Token introduced with LinOTP 2.9 is a smartphone based token used for securing authentications and transactions. To use the QR Token on your smartphone you need to install the KeyIdentity authenticator app for Android or iOS.
Unlike the OATH (Initiative for Open Authentication) tokens it features asymmetric cryptography. This allows your private key to stay solely on your smartphone while LinOTP only needs your public key for verifying your TANs or signatures. The private key is used to sign a payload (challenge) sent to the device via a QR Code.
Since you can include transaction data in the challenge the QR Token can be used for securing transactions. Thinking of online banking a TAN or signature generated for a transfer of 20$ to account A is only valid for this specific transfer and cannot be used by a man-in-the-middle attacker for legitimating other transactions.
The QR Token features an offline mode for smartphones without an internet connection. Instead of automatically sending the signature to LinOTP, a TAN is displayed in the authenticor app and can be entered to the web application manually.
Further, the QR Token may be used to enforce device separation.

Note:
In case you don’t need the offline mode or device separation you should have a look at the KeyIdentity Push Token recently introduced in LinOTP 2.9.1 for further improved usability. Integrating the Push Token is very similar to the steps shown below.

Integration

Integrating the KeyIdentity QR Token is as simple as implementing three API calls (only two in case you don’t want to support the offline mode).

Step 1

The first step is used to trigger a challenge containing the transaction data. Simply send an HTTP POST request to LinOTP’s “/validate/check” function containing the user to create the challenge for (“user”), the transaction data (“data”) and the user’s token PIN (“pass”). Depending on the configured otppin policy the token PIN is interpreted as a separate PIN per token, the user’s LDAP password or it is empty and ignored (“only_otp”).

$ curl --data "user=testuser&pass=&data=Transaction data%3A%0A%0AAmount%3A 10EUR%0ATo account%3A 12345678" https://[LINOTP]/validate/check

{
   "detail": {
      "linotp_tokenserial": "LSQR00165BA8",
      "transactionid": "562599548041",
      "message": "lseqr://chal/ASoAAADfWk97VrI6-qwSjbPzsw3L2ozi3m5Pd68yrGAWoereKjBxRqUa2-ujKvQZE6USlQe7k-y4RGgADs8zSjw_6U8mjYaageW-IxB_tYmjAsOKT0djGEyVdJmU3rG1zEZ1_aau7SmvVyaj_hNYGlmGvY4_IF2K1OGCt5z1AwgSANxp0SRPqqUs4XIgDdxNd6hOwHMyK0ZtUey0O_wd837uwhVDPi_w",
      "linotp_tokentype": "qr"
   },
   "version": "LinOTP 2.9.1",
   "jsonrpc": "2.0802",
   "result": {
      "status": true,
      "value": false
   },
   "id": 0
}

The JSON response contains an object called “detail” which includes the “transactionid” of the triggered challenge. This ID is a handle to the specific transaction and should be kept in memory for the steps to follow. The “message” field contains the challenge blob and must be presented to the user as a QR code. Libraries creating QR codes from strings are available for almost every programming language used to build web applications.

Step 2

Once the user scans the QR code the authenticator app sends the challenge response to the URL defined in the authentication policy scope, which is encoded in the QR code. For easiest integration this URL can be configured to point at the LinOTP server itself (see the note below for another integration technique). This allows the authenticator app to communicate directly with LinOTP and therefore does not need any additional API endpoints in your web application.
To get the current status of the transaction the web application can poll the “/validate/check_status” function. The needed parameters are “user” and “pass” (see step 1) and the “transactionid” received in the previous JSON response. Once LinOTP receives a successful response to the transaction challenge, the “valid_tan” field in the “detail.transactions.” object is set to “true”. Otherwise, this field’s value will be “false”.

$ curl --data "user=testuser&pass=&transactionid=562599548041" https://[LINOTP]/validate/check_status

{
    "detail": {
        "transactions": {
            "752931684012": {
                "status": "open",
                "token": {
                    "serial": "LSQR00165BA8",
                    "type": "qr"
                },
                "received_tan": false,
                "message": "lseqr://chal/ASoAAADfWk97VrI6-qwSjbPzsw3L2ozi3m5Pd68yrGAWoereKjBxRqUa2-ujKvQZE6USlQe7k-y4RGgADs8zSjw_6U8mjYaageW-xB_tYmjAsOKT0djGEyVdJmU3rG1zEZ1_aau7SmvVyaj_hNYGlmGvY4_IF2K1OGCt5z1AwgSANxp0SRPqqUs4XIgDdxNd6hOwHMyK0ZtUey0O_wd837uwhVDPi_w",
                "received_count": 0,
                "valid_tan": false
            }
        }
    },
    "version": "LinOTP 2.9.1",
    "jsonrpc": "2.0802",
    "result": {
        "status": true,
        "value": true
    },
    "id": 0
}

Note:
Polling “/validate/check_status” is the easiest way of integrating the QR Token into your application. However, polling techniques may not be suitable for specific usecases, i.e. polling may cause significant workload for applications with many transactions.
For deeper integration and avoiding polling, LinOTP’s qrtoken_challenge_callback_url policy can be configured to point at an API endpoint of your web application. This endpoint should act as a reverse proxy to LinOTP’s “/validate/check_t” function. The validity of the received challenge response can be obtained directly from the “check_t” JSON response.

Step 3 – Offline Support

In case the user’s smartphone has no access to the internet during authentication, an 8-digit TAN is displayed to the user. For supporting this offline fallback method the web application may offer an input field. The TAN’s validity is checked against “/validate/check” using the parameters “user”, “transactionid” and “pass” with “pass” being the entered TAN. A boolean “true” in “result.value” is returned on a valid TAN, a boolean “false” otherwise.

$ curl --data "user=testuser&pass=35050186&transactionid=562599548041" https://[LINOTP]/validate/check

{
    "version": "LinOTP 2.9.1",
    "jsonrpc": "2.0802",
    "result": {
        "status": true,
        "value": true
    },
    "id": 0
}

And that’s it. These three simple steps are enough to integrate the KeyIdentity QR Token into your web applications and to take the first step to secure your users’ data as well as their transactions.