Interactions
Smart-ID app can support different interaction types and a Relying Party (RP) can demand a particular interaction with or without a fallback possibility. Different interactions can support different amount of data to display information to user.
Each interaction is defined by an object that has 2 parameters: type
and either displayText60
or displayText200
.
The following table shows interaction types available for each flow type. Linked notification based flow refers to the BASE/v3/signature/notification/linked
endpoint.
Interaction type & extra parameter | Description | Device link based flows | Notification based flows | Linked notification based flow |
---|---|---|---|---|
|
The simplest interaction with max 60 chars of text and PIN entry on a single screen. |
Yes |
Yes |
Yes |
|
First screen is for text only (max 200 chars) and has Confirm and Cancel buttons. Second screen is for PIN. |
Yes |
Yes |
Yes |
|
First screen combines text and Verification Code choice. Second screen is for PIN. |
No |
Yes |
No |
All three interactions types are currently supported by all the clients.
Requirements for interactions
object
RP uses interactions
parameter to list interactions it allows for the current session.
New interaction types may be introduced in the future. However, it takes some time until all apps have been updated and are actually capable of displaying the new types.
After introduction of a new interaction type both the new interaction type as a well as an older type should be provided in the array for clients that have not been yet updated.
The interactions
parameter is a Base64 encoded JSON array and the order of the items is significant. Each interaction in the array is a JSON object consisting of the type
, and either displayText60
or displayText200
. The first interaction that is supported by a specific app installation will be used.
The interaction that was used is always reported back to RP with interactionTypeUsed
response parameter to the session request.
If an app cannot support any interaction requested then the session is cancelled with reason code REQUIRED_INTERACTION_NOT_SUPPORTED_BY_APP
.
IMPORTANT
The following requirements apply for the
Failing to meet the first 4 requirements above will result in an error (HTTP 400 Bad Request). Failing to follow the last recommendation can result in some dynamic link sessions failing. If |
Guidance for writing display texts
displayText
is a short text string displayed to the user in the Smart-ID authentication or digital signature consent screen. It helps the user understand the context of the operation. displayText
will be displayed on the authentication or signing consent screen. The RP can use this to distinguish between the different information systems or different services within the RP, when requesting the authentication. When requesting a digital signature, the RP can use this to give information about the nature of signature, such as the name of the document to be signed or information about the transfer order to be executed.
For example, in case the RP is using Smart-ID to authenticate users calling the RP’s helpdesk via phone, these authentication requests must use a different displayText
than requests sent by the RP’s website. This way the user has greater confidence that the person on the phone (a helpdesk agent who might be out-sourced from an external company) is not logging into the website of the RP under the name of the user.
displayText
value can only be set by the RP backend and phishing attacks can’t change it. This is why, it is recommended to use the displayText
to alert users and show warnings if an attack is suspected. For more details, see Additional security measures page.
The displayText60
and displayText200
parameters are used by the Smart-ID app to display text on the screen. The preferred way of writing displayText60
and displayText200
is to explain the action user is taking which the user is expected to confirm.
The descriptions should be concise and specific allowing the user to verify the context of the operation quickly. A few examples:
-
Logging in to internet banking
-
Log in to mobile banking app
-
Applying for a credit card application, 1000€ credit limit
-
Signing document Contract.asice
-
Transfer 1000€ to Jane Doe GB33BUKB20201555555555
Usually, the Relying Party name does not need to be part of the display text as the RP name parameter is always displayed to the user along with the display text.
Base64 encoding interactions
Before sending the RP API request, interactions
array must be turned into a string and then Base64 encoded. The interactions
JSON should be minified to lower the overhead.
The Base64 encoding can be done as follows:
interactions := BASE64-ENCODE(TO-STRING(MINIFY(interactionsJson)))
-
Java
-
PHP
-
Python
-
Go
-
Rust
-
Kotlin
-
C#
-
Node.js
-
Ruby
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class InteractionsBase64Encode {
public static void main(String[] args) {
String interactions = """
[{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}]""";
String interactionsBase64 = Base64.getEncoder().encodeToString(
interactions.getBytes(StandardCharsets.UTF_8)
);
System.out.println(interactionsBase64);
}
}
<?php
$interactionsJsonStr = <<<EOD
[{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}]
EOD;
$interactionsBase64 = base64_encode($interactionsJsonStr);
echo $interactionsBase64;
?>
import base64
import json
interactions = [{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}]
interactions_string = json.dumps(interactions, separators=(',', ':'))
interactions_base64 = base64.b64encode(interactions_string.encode('utf-8'))
print(interactions_base64)
package main
import (
"encoding/base64"
"encoding/json"
"fmt"
)
type Interactions struct {
Type string `json:"type"`
DisplayText200 string `json:"displayText200,omitempty"`
DisplayText60 string `json:"displayText60,omitempty"`
}
func main() {
var interactions []Interactions = []Interactions{{Type: "confirmationMessage", DisplayText200: "Longer description of the transaction context"}, {Type: "displayTextAndPIN", DisplayText60: "Short description of the transaction context"}}
interactionsBytes, err := json.Marshal(interactions)
if err != nil {
fmt.Printf("error: %s\n", err)
return
}
var interactionsBase64 []byte = []byte(base64.StdEncoding.EncodeToString(interactionsBytes))
fmt.Printf("%q\n", interactionsBase64)
}
use base64::Engine as _;
use serde::{Deserialize, Serialize};
type Interactions<'a> = Vec<Interaction<'a>>;
#[derive(Debug, Deserialize, Serialize)]
enum DisplayText<'a> {
#[serde(rename = "displayText200")]
DisplayText200(&'a str),
#[serde(rename = "displayText60")]
DisplayText60(&'a str),
}
#[derive(Serialize, Deserialize)]
struct Interaction<'a> {
#[serde(rename = "type")]
type_field: &'a str,
#[serde(flatten)]
display_text: DisplayText<'a>,
}
fn main() {
let interactions: Interactions = vec![Interaction{type_field: "confirmationMessage", display_text: DisplayText::DisplayText200("Longer description of the transaction context")}, Interaction{type_field: "displayTextAndPIN", display_text: DisplayText::DisplayText60("Short description of the transaction context")}];
let interactions_base64: String = base64::engine::general_purpose::STANDARD.encode(serde_json::to_string(&interactions).unwrap().into_bytes());
println!("{:?}", interactions_base64);
}
import java.nio.charset.StandardCharsets
import java.util.Base64
fun main() {
val interactions: String = """
[{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}]""".trimIndent()
val interactionsBase64: String = Base64.getEncoder().encodeToString(
interactions.toByteArray(StandardCharsets.UTF_8)
)
println(interactionsBase64)
}
using System;
using System.Text;
public class InteractionsBase64Encode
{
public static void Main(string[] args)
{
String interactionsJson = """[{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}]""";
String interactionsBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(interactionsJson));
Console.WriteLine(interactionsBase64);
}
}
const interactions = [{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}];
const interactionsString = JSON.stringify(interactions);
const interactionsBase64 = Buffer.from(interactionsString).toString('base64');
console.log(interactions_base64);
require 'base64'
require 'json'
interactions = [{"type":"confirmationMessage","displayText200":"Longer description of the transaction context"},{"type":"displayTextAndPIN","displayText60":"Short description of the transaction context"}]
interactions_string = JSON.generate(interactions)
interactions_base64 = Base64.strict_encode64(interactions_string)
puts interactions_base64
interactions
parameterW3sidHlwZSI6ImNvbmZpcm1hdGlvbk1lc3NhZ2UiLCJkaXNwbGF5VGV4dDIwMCI6IkxvbmdlciBkZXNjcmlwdGlvbiBvZiB0aGUgdHJhbnNhY3Rpb24gY29udGV4dCJ9LHsidHlwZSI6ImRpc3BsYXlUZXh0QW5kUElOIiwiZGlzcGxheVRleHQ2MCI6IlNob3J0IGRlc2NyaXB0aW9uIG9mIHRoZSB0cmFuc2FjdGlvbiBjb250ZXh0In1d
interactions
elements examples
confirmationMessage
only, if not available then fail.Before encoding
Base64 encoded
|
|
displayTextAndPIN
only, if not available then fail.Before encoding
Base64 encoded
|
|
confirmationMessage
, if not available then fall back to displayTextAndPIN
.Before encoding
Base64 encoded
|
|
confirmationMessageAndVerificationCodeChoice
only, if not available then fail (only notification based flow).Before encoding
Base64 encoded
|
|