Device link flows

The device link flows are the primary flows to be used for initiating Smart-ID transactions. It consists of the following steps:

  1. User interacts with an RP frontend (a webpage or an app).

  2. RP backend makes a request to RP API to create a device link based session (authentication, signature, or certificate-choice) to obtain security parameters that are necessary for generating device links. For authentication and certificate-choice sessions, the request may either be anonymous (no personal identifier is provided) or non-anonymous (signature session can’t be anonymous).

  3. RP starts creating device links. In case of QR codes, but not Web2App nor App2App links, the links must be updated each second. The device links must be generated in the RP backend and then forwarded to the RP frontend each time.

  4. RP frontend displays QR codes / Web2App links / App2App links. The user interacts with one of them by either:

    1. Opening Smart-ID app and scanning the dynamic QR code (preferred option for QR codes);

    2. Using a native camera app to scan the dynamic QR code (not supported by all camera apps) which opens the Smart-ID app where user has to scan the QR code again.

    3. Clicking on the Web2App link in an RP webpage, thus opening the Smart-ID app;

    4. Clicking on the App2App link in an RP app, thus opening the Smart-ID app.

  5. Smart-ID app extracts the necessary parameters and makes a request to the Smart-ID backend to check the integrity, validity and freshness of the device link. If the request was non-anonymous, it is verified that the provided personal identifier agrees with the actual user’s identity.

  6. The user is asked to verify the transaction details and enter their PIN.

  7. After the signature has been given, the RP receives the result via the session status endpoint. In case of anonymous flow, RP learns the identity of the user only at this point (via the user’s certificate).

  8. User is redirected back to the RP with the given callback URL in same-device flows and RP performs the callback URL verification steps described in Callback URLs page.

IMPORTANT
  1. For device link flows, a single request must be sent. For a single session that displays both a dynamic QR code and a Web2App or App2App link, multiple requests must not be sent. Some examples:

    • If an RP would like to display a Web2App or App2App link without a dynamic QR code, a device link flow with a callback URL must be started.

    • If an RP would like to display a dynamic QR code without the option for Web2App or App2App links, a device link flow can be started without a callback URL.

    • If an RP would like to display both, a dynamic QR code and a Web2App or App2App link, a device link flow with a callback URL must be started (but the callback URL will only be relevant if the user interacts with the Web2App/App2App link, not the QR code).

  2. In same-device flow, it may be easier for RP to send a request to session status endpoint only after the callback has been received. This is only relevant when the QR code flow is not provided.

The following diagram describes the device link based flow for the authentication session.

flow

The following diagram describes the device link based flow for the signature session.

flow

The following diagram describes the device link based flow for the certificateChoice session.

flow

When RP backend makes a request to RP API to create a new device link based session, RP API server generates and returns the following parameters as a response:

  • sessionID - session ID (RP UUID);

  • sessionToken - unique value that is used to connect this authentication/signing attempt between the relevant parties (RP, RP API, Smart-ID app);

  • sessionSecret - Base64 encoded key value that must be kept secret and must not be shared with any other party (including RP frontend);

  • deviceLinkBase - the base URL to be used to generate the QR/Web2App/App2App device links.

RP then calculates the Web2App or App2App device link and dynamic QR code and shows it to the end user. The dynamic QR code must be updated regularly with the interval of 1 second.

It is recommended that RP offers multiple options, QR image and Web2App link, to the user at the same time if either:

  1. RP is unable to detect from the user agent whether the user is using a mobile device or a PC,

  2. The user is accessing RP website from a mobile device, for example a tablet device, and might want to authenticate using a separate mobile device.

NOTE

The device link structure is similar for both same-device and cross-device flows. The differences between them are:

  1. The value of deviceLinkType is different (Web2App, App2App vs QR),

  2. same-device links do not have elapsedSeconds and should not be dynamically regenerated,

  3. the final representation of the link to the user is different (a clickable HTTPS link vs a dynamic QR code).

IMPORTANT
  1. All values in the deviceLink are case-sensitive. The resulting deviceLink must match bit by bit with the expected deviceLink in the Smart-ID backend.

  2. There must not be URL encoding in the deviceLink.

  3. There must not be URL fragment (#) in the deviceLink.

  4. The order of the path parameters in the device link must be the same as specified in the examples below. All values are required and must be non-empty; the only exceptions to this are:

    • in certificate-choice session requests parameters digest, interactions and signatureProtocol must be included as empty fields;

    • in QR flows, initialCallbackUrl must be included as an empty field;

    • in same-device flows, elapsedSeconds parameter must be missing from unprotectedDeviceLink.

Same-device flows

The device link for App2App and Web2App is a URL:

deviceLink := STR-CONCAT(
        deviceLinkBase, "?",
        "deviceLinkType=", deviceLinkType,
        "&sessionToken=", sessionToken,
        "&sessionType=", sessionType,
        "&version=", version,
        "&lang=", lang,
        "&authCode=", authCode)
  • Java

  • PHP

  • Python

  • Go

  • Rust

  • Kotlin

  • C#

  • Node.js

  • Ruby

public class DeviceLinkGenerator {

  public static void main(String[] args) {
    String deviceLinkBase = "https://smart-id.com";
    String deviceLinkType = "Web2App";
    String sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
    String sessionType = "auth";
    String version = "1.0";
    String lang = "eng";
    String authCode = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0";

    String deviceLink = deviceLinkBase + "?" +
      "deviceLinkType=" + deviceLinkType +
      "&sessionToken=" + sessionToken +
      "&sessionType=" + sessionType +
      "&version=" + version +
      "&lang=" + lang +
      "&authCode=" + authCode;

    System.out.println(deviceLink);
  }
}
<?php

$deviceLinkBase = "https://smart-id.com";
$deviceLinkType = "Web2App";
$sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
$sessionType = "auth";
$version = "1.0";
$lang = "eng";
$authCode = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0";

$deviceLink = $deviceLinkBase . "?"
  . "deviceLinkType=" . $deviceLinkType
  . "&sessionToken=" . $sessionToken
  . "&sessionType=" . $sessionType
  . "&version=" . $version
  . "&lang=" . $lang
  . "&authCode=" . $authCode;

echo $deviceLink;

?>
device_link_base = "https://smart-id.com"
device_link_type = "Web2App" # One of "Web2App", "App2App"
session_token = "wGIrqveE6AuGDATZKmR1mtAZ"
session_type = "auth"
version = "1.0"
lang = "eng"
auth_code = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0"
device_link = device_link_base + "?" + "deviceLinkType=" + device_link_type + "&sessionToken=" + session_token + "&sessionType=" + session_type + "&version=" + version + "&lang=" + lang + "&authCode=" + auth_code
print(device_link)
package main

import (
	"fmt"
	"strconv"
)

func main() {
	var deviceLinkBase string = "https://smart-id.com"
	var deviceLinkType string = "Web2App" // One of "Web2App", "App2App"
	var sessionToken string = "wGIrqveE6AuGDATZKmR1mtAZ"
	var sessionType string = "auth"
	var version string = "1.0"
	var lang string = "eng"
	var authCode string = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0"

	var deviceLink string = deviceLinkBase + "?" + "deviceLinkType=" + deviceLinkType +
		"&sessionToken=" + sessionToken +
		"&sessionType=" + sessionType +
		"&version=" + version +
		"&lang=" + lang +
		"&authCode=" + authCode

	fmt.Printf("%s\n", deviceLink)
}
fn main() {
    let device_link_base: &str = "https://smart-id.com";
    let device_link_type: &str = "Web2App"; // One of "Web2App", "App2App"
    let session_token: &str = "wGIrqveE6AuGDATZKmR1mtAZ";
    let session_type: &str = "auth";
    let version: &str = "1.0";
    let lang: &str = "eng";
    let auth_code: &str = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0";

    let device_link: String = format!("{}?deviceLinkType={}&sessionToken={}&sessionType={}&version={}&lang={}&authCode={}", device_link_base, device_link_type, session_token, session_type, version, lang, auth_code);

    println!("{}", device_link);
}
fun main() {
    val deviceLinkBase: String = "https://smart-id.com"
    val deviceLinkType: String = "Web2App"
    val sessionToken: String = "wGIrqveE6AuGDATZKmR1mtAZ"
    val sessionType: String = "auth"
    val version: String = "1.0"
    val lang: String = "eng"
    val authCode: String = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0"

    val deviceLink: String = "$deviceLinkBase" + "?" +
        "deviceLinkType=$deviceLinkType&" +
        "sessionToken=$sessionToken&" +
        "sessionType=$sessionType&" +
        "version=$version&" +
        "lang=$lang&" +
        "authCode=$authCode"

    println(deviceLink)
}
using System;

public class DeviceLinkGenerator
{
    public static void Main(string[] args)
    {
        string deviceLinkBase = "https://smart-id.com";
        string deviceLinkType = "Web2App";
        string sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
        string sessionType = "auth";
        string version = "1.0";
        string lang = "eng";
        string authCode = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0";

        string deviceLink = deviceLinkBase + "?" +
            "deviceLinkType=" + deviceLinkType +
            "&sessionToken=" + sessionToken +
            "&sessionType=" + sessionType +
            "&version=" + version +
            "&lang=" + lang +
            "&authCode=" + authCode;

        Console.WriteLine(deviceLink);
    }
}
const deviceLinkBase = "https://smart-id.com";
const deviceLinkType = "Web2App";
const sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
const sessionType = "auth";
const version = "1.0";
const lang = "eng";
const authCode = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0";

const deviceLink = deviceLinkBase + "?" +
  "deviceLinkType=" + deviceLinkType +
  "&sessionToken=" + sessionToken +
  "&sessionType=" + sessionType +
  "&version=" + version +
  "&lang=" + lang +
  "&authCode=" + authCode;

console.log(deviceLink);
device_link_base = "https://smart-id.com"
device_link_type = "Web2App" # One of "Web2App", "App2App"
session_token = "wGIrqveE6AuGDATZKmR1mtAZ"
session_type = "auth"
version = "1.0"
lang = "eng"
auth_code = "aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0"
device_link = device_link_base + "?" +
  "deviceLinkType=" + device_link_type +
  "&sessionToken=" + session_token +
  "&sessionType=" + session_type +
  "&version=" + version +
  "&lang=" + lang +
  "&authCode=" + auth_code
puts device_link
Example 1. Web2App link (authentication session)
https://smart-id.com/device-link?deviceLinkType=Web2App&sessionToken=wGIrqveE6AuGDATZKmR1mtAZ&sessionType=auth&version=1.0&lang=eng&authCode=aegUh6gCKkXBJhhvtJqSTWB5_2W8TDQt5eZ7db6krv0
Example 2. App2App link (signature session)
https://smart-id.com/device-link?deviceLinkType=App2App&sessionToken=wGIrqveE6AuGDATZKmR1mtAZ&sessionType=sign&version=1.0&lang=eng&authCode=8QZ16rkBW_ffkq6osT7UH1DbUlF9gEOZevgj-A0VNbM
Example 3. Web2App link (certificate-choice session)
https://smart-id.com/device-link?deviceLinkType=Web2App&sessionToken=wGIrqveE6AuGDATZKmR1mtAZ&sessionType=cert&version=1.0&lang=eng&authCode=PI1qYa9_l6zR-v6Pkre6ycSm7S3BGiOQSe5OQlw4UJg

Cross-device (dynamic QR code) flows

QR message itself is defined as a URL, just like App2App and Web2App links.

deviceLink := STR-CONCAT(
        deviceLinkBase, "?",
        "deviceLinkType=", deviceLinkType,
        "&elapsedSeconds=", TO-STRING(elapsedSeconds),
        "&sessionToken=", sessionToken,
        "&sessionType=", sessionType,
        "&version=", version,
        "&lang=", lang,
        "&authCode=", authCode)
  • Java

  • PHP

  • Python

  • Go

  • Rust

  • Kotlin

  • C#

  • Node.js

  • Ruby

public class DeviceLinkGenerator {

  public static void main(String[] args) {
    String deviceLinkBase = "https://smart-id.com";
    String deviceLinkType = "QR";
    int elapsedSeconds = 22;
    String sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
    String sessionType = "auth";
    String version = "1.0";
    String lang = "eng";
    String authCode = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0";

    String deviceLink = deviceLinkBase + "?" +
      "deviceLinkType=" + deviceLinkType +
      "&elapsedSeconds=" + elapsedSeconds +
      "&sessionToken=" + sessionToken +
      "&sessionType=" + sessionType +
      "&version=" + version +
      "&lang=" + lang +
      "&authCode=" + authCode;

    System.out.println(deviceLink);
  }
}
<?php

$deviceLinkBase = "https://smart-id.com";
$deviceLinkType = "QR";
$elapsedSeconds = 22;
$sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
$sessionType = "auth";
$version = "1.0";
$lang = "eng";
$authCode = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0";

$deviceLink = $deviceLinkBase . "?"
  . "deviceLinkType=" . $deviceLinkType
  . "&elapsedSeconds=" . $elapsedSeconds
  . "&sessionToken=" . $sessionToken
  . "&sessionType=" . $sessionType
  . "&version=" . $version
  . "&lang=" . $lang
  . "&authCode=" . $authCode;

echo $deviceLink;

?>
device_link_base = "https://smart-id.com"
device_link_type = "QR" # "QR"
elapsed_seconds = 22
session_token = "wGIrqveE6AuGDATZKmR1mtAZ"
session_type = "auth"
version = "1.0"
lang = "eng"
auth_code = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0"
device_link = device_link_base + "?" + "deviceLinkType=" + device_link_type + "&elapsedSeconds=" + str(elapsed_seconds) + "&sessionToken=" + session_token + "&sessionType=" + session_type + "&version=" + version + "&lang=" + lang + "&authCode=" + auth_code
print(device_link)
package main

import (
	"fmt"
	"strconv"
)

func main() {
	var deviceLinkBase string = "https://smart-id.com"
	var deviceLinkType string = "QR" // "QR"
	var elapsedSeconds int = 22
	var sessionToken string = "wGIrqveE6AuGDATZKmR1mtAZ"
	var sessionType string = "auth"
	var version string = "1.0"
	var lang string = "eng"
	var authCode string = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0"

	var deviceLink string = deviceLinkBase + "?" + "deviceLinkType=" + deviceLinkType +
		"&elapsedSeconds=" + strconv.Itoa(elapsedSeconds) +
		"&sessionToken=" + sessionToken +
		"&sessionType=" + sessionType +
		"&version=" + version +
		"&lang=" + lang +
		"&authCode=" + authCode

	fmt.Printf("%s\n", deviceLink)
}
fn main() {
    let device_link_base: &str = "https://smart-id.com";
    let device_link_type: &str = "QR"; // "QR"
    let elapsed_seconds: i32 = 22;
    let session_token: &str = "wGIrqveE6AuGDATZKmR1mtAZ";
    let session_type: &str = "auth";
    let version: &str = "1.0";
    let lang: &str = "eng";
    let auth_code: &str = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0";

    let device_link: String = format!("{}?deviceLinkType={}&elapsedSeconds={}&sessionToken={}&sessionType={}&version={}&lang={}&authCode={}", device_link_base, device_link_type, elapsed_seconds, session_token, session_type, version, lang, auth_code);

    println!("{}", device_link);
}
fun main() {
    val deviceLinkBase: String = "https://smart-id.com"
    val deviceLinkType: String = "QR"
    val elapsedSeconds: Int = 22
    val sessionToken: String = "wGIrqveE6AuGDATZKmR1mtAZ"
    val sessionType: String = "auth"
    val version: String = "1.0"
    val lang: String = "eng"
    val authCode: String = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0"

    val deviceLink: String = "$deviceLinkBase" + "?" +
        "deviceLinkType=$deviceLinkType&" +
        "elapsedSeconds=$elapsedSeconds&" +
        "sessionToken=$sessionToken&" +
        "sessionType=$sessionType&" +
        "version=$version&" +
        "lang=$lang&" +
        "authCode=$authCode"

    println(deviceLink)
}
using System;

public class DeviceLinkGenerator
{
    public static void Main(string[] args)
    {
        string deviceLinkBase = "https://smart-id.com";
        string deviceLinkType = "QR";
        int elapsedSeconds = 22;
        string sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
        string sessionType = "auth";
        string version = "1.0";
        string lang = "eng";
        string authCode = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0";

        string deviceLink = deviceLinkBase + "?" +
            "deviceLinkType=" + deviceLinkType +
            "&elapsedSeconds=" + elapsedSeconds.ToString() +
            "&sessionToken=" + sessionToken +
            "&sessionType=" + sessionType +
            "&version=" + version +
            "&lang=" + lang +
            "&authCode=" + authCode;

        Console.WriteLine(deviceLink);
    }
}
const deviceLinkBase = "https://smart-id.com";
const deviceLinkType = "QR";
const elapsedSeconds = 22;
const sessionToken = "wGIrqveE6AuGDATZKmR1mtAZ";
const sessionType = "auth";
const version = "1.0";
const lang = "eng";
const authCode = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0";

const deviceLink = deviceLinkBase + "?" +
  "deviceLinkType=" + deviceLinkType +
  "&elapsedSeconds=" + elapsedSeconds +
  "&sessionToken=" + sessionToken +
  "&sessionType=" + sessionType +
  "&version=" + version +
  "&lang=" + lang +
  "&authCode=" + authCode;

console.log(deviceLink);
device_link_base = "https://smart-id.com"
device_link_type = "QR" # "QR"
elapsed_seconds = 22
session_token = "wGIrqveE6AuGDATZKmR1mtAZ"
session_type = "auth"
version = "1.0"
lang = "eng"
auth_code = "OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0"
device_link = device_link_base + "?" +
  "deviceLinkType=" + device_link_type +
  "&elapsedSeconds=" + elapsed_seconds.to_s +
  "&sessionToken=" + session_token +
  "&sessionType=" + session_type +
  "&version=" + version +
  "&lang=" + lang +
  "&authCode=" + auth_code
puts device_link
Example 4. QR link (authentication session)
https://smart-id.com/device-link?deviceLinkType=QR&elapsedSeconds=22&sessionToken=wGIrqveE6AuGDATZKmR1mtAZ&sessionType=auth&version=1.0&lang=eng&authCode=OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0
Example 5. QR code (authentication session)
alt=https://smart-id.com/device-link?deviceLinkType=QR&elapsedSeconds=22&sessionToken=wGIrqveE6AuGDATZKmR1mtAZ&sessionType=auth&version=1.0&lang=eng&authCode=OY1eHaD4UYedrBwtqUbSkpa0w7ttm4FllPkCD_3wlE0

For more details on how the dynamic QR code or other device links should be presented in the RP frontend, see Device link and QR presentation section.

The table below explains the parameters that are included in the device link calculation.

IMPORTANT
  • The calculation of device links must be performed in the RP backend. All values (including elapsedSeconds) must all be generated in the RP backend and the RP frontend must not be able to change or affect these parameters.

  • For dynamic QR code flows, the dynamic generation (every 1s) of the authCode parameter must be done in the RP backend, NOT in the RP frontend or RP app so as not to leak the sessionSecret parameter. Also, it is forbidden to generate values of authCode parameter ahead of time and forward them to the RP frontend/app.

version parameter

version parameter is a pre-defined value. Currently, only 1.0 is supported. It must be used in string form in device links.

Example 6. version parameter
"1.0"

sessionToken parameter

RP API returns sessionToken. It is a URL safe value and it must be used as is (in string form) in device links.

Example 7. sessionToken parameter
"wGIrqveE6AuGDATZKmR1mtAZ"

deviceLinkType parameter

The parameter deviceLinkType describes the device link type:

  • QR - for dynamic QR codes,

  • Web2App - for non-dynamic Web2App device links,

  • App2App - for non-dynamic App2App device links.

The string value must be used as is (in string form) in device links.

Example 8. deviceLinkType parameter
"QR"

sessionType parameter

The parameter sessionType describes the session type:

  • auth - for authentication session,

  • sign - for signature session,

  • cert - for certificate-choice session.

The string value must be used as is (in string form) in device links.

Example 9. sessionType parameter
"auth"

elapsedSeconds parameter

The elapsedSeconds parameters is seconds since receiving the response from the initial session creation request to RP API. Notice that dynamic QR code link must be re-calculated each second because the elapsedSeconds value changes.

elapsedSeconds value must be converted to string value to be used in QR code links:

elapsedSeconds := TO-STRING(elapsedSeconds)
  • Java

  • PHP

  • Python

  • Go

  • Rust

  • Kotlin

  • C#

  • Node.js

  • Ruby

public class Int2Str {

    public static void main(String[] args) {
        int elapsedSeconds = 22;
        String elapsedSecondsStr = Integer.toString(elapsedSeconds);
        System.out.println(elapsedSecondsStr);
    }
}
<?php

$elapsedSeconds = 22;
$elapsedSecondsStr = strval($elapsedSeconds);
echo $elapsedSecondsStr;

?>
elapsed_seconds = 22
elapsed_seconds_str = str(elapsed_seconds)
print(elapsed_seconds_str)
package main

import (
	"fmt"
	"strconv"
)

func main() {
	var elapsedSeconds int = 22
	var elapsedSecondsStr string = strconv.Itoa(elapsedSeconds)
	fmt.Printf("%s\n", elapsedSecondsStr)
}
fn main() {
    let elapsed_seconds: i32 = 22;
    let elapsed_seconds_str: String = elapsed_seconds.to_string();
    println!("{}", elapsed_seconds_str)
}
fun main() {
    val elapsedSeconds: Int = 22
    val elapsedSecondsStr: String = elapsedSeconds.toString()
    println(elapsedSecondsStr)
}
using System;

public class Int2Str
{
    public static void Main()
    {
        int elapsedSeconds = 22;
        string elapsedSecondsStr = elapsedSeconds.ToString();
        Console.WriteLine(elapsedSecondsStr);
    }
}
let elapsedSeconds = 22;
let elapsedSecondsStr = elapsedSeconds.toString();
console.log(elapsedSecondsStr);
elapsed_seconds = 22
elapsed_seconds_str = elapsed_seconds.to_s
puts elapsed_seconds_str
Example 10. elapsedSeconds parameter
"22"

lang parameter

The lang parameter defines the interface language for the HTTPS fallback page that is shown to the user when there are technical problems regarding opening device links (for example, if user’s browser does not support Web2App links and needs to be configured to allow them or if Smart-ID app is not installed on the phone). Its format must be ISO 639-2 three-letter language code. It is recommended that for consistent user experience, RP provides here the same language that the user was already using in the RP UI. This parameter only affects the language of the fallback page, not the Smart-ID app itself.

Example 11. lang parameter
"eng"

authCode parameter

authCode parameter generation is explained in detail in authCode calculation page.

Parameter visibility

The following table aims to clarify which of the parameters involved in device link construction should be accessible by which parties (see legend below). The table also includes parameters which are used for authCode calculation (e.g. unprotectedDeviceLink) — for their descriptions, see authCode calculation page.

RP API server RP backend RP frontend/app

version

check emoji 2714

check emoji 2714

check emoji 2714

sessionID

star emoji 2B50

check emoji 2714

no entry emoji 26D4

sessionToken

star emoji 2B50

check emoji 2714

check emoji 2714

sessionSecret

star emoji 2B50

check emoji 2714

no entry emoji 26D4

deviceLinkType

check emoji 2714

star emoji 2B50

check emoji 2714

sessionType

check emoji 2714

star emoji 2B50

check emoji 2714

signatureProtocol

check emoji 2714

star emoji 2B50

cross emoji 274C

rpChallenge

check emoji 2714

star emoji 2B50

no entry emoji 26D4

digest

check emoji 2714

star emoji 2B50

no entry emoji 26D4

relyingPartyName

check emoji 2714

star emoji 2B50

cross emoji 274C

brokeredRpName

check emoji 2714

star emoji 2B50

cross emoji 274C

interactions

check emoji 2714

star emoji 2B50

cross emoji 274C

initialCallbackUrl

check emoji 2714

star emoji 2B50

no entry emoji 26D4

unprotectedDeviceLink

check emoji 2714

star emoji 2B50

check emoji 2714

elapsedSeconds

check emoji 2714

star emoji 2B50

check emoji 2714

authCode

check emoji 2714

star emoji 2B50

check emoji 2714

lang

check emoji 2714

star emoji 2B50

check emoji 2714

Legend:

  • star emoji 2B50 - source of parameter (the party that generates/calculates it)

  • check emoji 2714 - knows parameter

  • cross emoji 274C - does not know parameter

  • no entry emoji 26D4 - MUST NOT know parameter

Fallback page

For cases when the app is not installed or some other problem occurs with opening a device link, a fallback HTTPS webpage is opened with instructions on how to resolve the issue. The lang parameter in the link is by default used to show the same language as on the RP UI. The instructions cover the following scenarios:

  • User is not on a mobile device where Smart-ID app is installed and has been allowed by the RP to use a wrong type of device link (e.g. a same-device link on a PC).

  • Smart-ID App is not installed on the current device.

  • Mobile browser does not support universal links / Android App links.

  • Mobile OS/browser settings disallow the link and user intervention is required.

For generation of QR codes, error correction level LOW or MEDIUM should be used. HIGH cannot be used due to the typical device link length. The QR code should have sufficient margins to enable quick scanning by the Smart-ID app. The optimal block size for QR code is 6-10 pixels per block when displayed on a PC, since:

  • Block sizes 5 pixels and less are too small for easy scanning (devices might have focus issues, although many will not).

  • Block sizes 20 pixels and above are too big for convenient scanning and take up too much space.

When QR code is displayed on a mobile device, it is recommended to show the QR code as big as possible, up to 10 pixels per block.

QR code can be generated on the client or server. It is recommended to use the SVG format as it remains sharp when users zoom the page. Note that many QR code libraries that support SVG output do not accept block size as an input parameter. So, block size should be estimated based on overall image dimensions, device link length and error correction level. See QR generator section for an example which also calculates the resulting block size in pixels.

IMPORTANT

The actual generation of the QR image can be done both in the backend or the frontend, however the link itself must only be generated by the RP backend. This is because sensitive parameters such as sessionSecret must never be sent to the RP frontend.

QR generator

This form allows you to test different QR code sizes with the recommended parameters and estimate the block size in pixels.

QR Code Generator

SVG QR Code Generator

QR code will appear here.