The Trust1Connector Javascript SDK is a library that purely functions as a proxy towards the Trust1Connector API. This Library does not contain any business logic.
Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks which are also available on the Trust1Connector Javascript SDK.
Trust1Connector JS SDK
You can find the trust1connector JS SDK for the Trust1Connector v3 via NPM
Include the Trust1Connector JavaScript SDK on your web application. This will provide you with access to the SDK's functions which are used to execute the Trust1Connector's functionality.
From now on we will refer to the Trust1Connector JS SDK to the following variances;
T1C-js/t1cjs
T1C SDK
Using Trust1Connector in as a library
The Trust1Connector is a Javascript Library with TypeScript typings. This can be easily used in any web-application by loading the javacript files on the web-page.
Loading the T1C SDK onto a web-page can be done as shown in the code example below of a html page
In the example you can see that we load the Javascript SDK on line 8
The defer attribute means that the script will be downloaded in parallel with the rest of the web-page but will be executed when the page has finished loading in.
This is mostly used to make sure that when the Javascript wants to target a specific element on the page, for example a div, that this element has already been loaded and is accessable.
Using Trust1Connector as a module
We also provide an npm package that makes it easier to load and use the Trust1Connector Javascript SDK as a module.
The Trust1Connector API v3 exposes a secure REST API on the client device. Trust1Team has created a t1c.t1t.io DNS entry (or customer-specific DNS entry) that points to 127.0.0.1 in order to facilitate SSL communication. This means that if the customer infrastructure uses a proxy for all network traffic, an exemption must be made for t1c.t1t.io to always point to the origin device's loopback address. The same holds true for the localhost domain name, this should redirect to 127.0.0.1 on the user's local system, not the localhost of the proxy server.
If no exemption is made and https://t1c.t1t.io is handled by a proxy, it will redirect to 127.0.0.1 IP of the proxy server instead of the local machine, and the Trust1Connector API will be unreachable.
The reserved domain from Trust1Team (t1c.t1t.io) has been registered with DNSSEC on the aforementioned URI. When a PARTNER uses its own DNS, we strongly recommend applying DNSSEC on the domain used in production.
DNS rebind protection
Some (corporate) networks have a policy that disables the ability to bind a domain to a local network IP. The Trust1Connector relies on this for t1c.t1t.io which resolves in to 127.0.0.1 which is a local ip for localhost
If DNS rebind protection is enabled it is unable to use t1c.t1t.io for connection towards the Trust1Connector because the network does not allow this Domain to be a local ip-address.
To resolve the issue either DNS rebind protection can be disabled or you can whitelist the domain t1c.t1t.io to allow this domain.
Applications using the Trust1Connector
Applications that want to make use of the Trust1Connector will be run from a specific domain. This means that the Trust1Connector needs to know that certain domains/applications want to make use of the Trust1Connector's functionality.
For these applications to gain access to the Trust1Connectors API we need to whitelist the domain in whats called the cors list. This list contains all the accepted domains that can make use of the Trust1Connector.
If you want to use the Trust1Connector on a specific domain, please contact our support team to add this domain to the cors list.
Distribution Service
In order to correctly function, the Trust1Connector API must be able to connect to its configured Distribution Service. You must allow REST traffic to the following URLs (if applicable):
Acceptance: https://acc-ds.t1t.io
Production: https://ds.t1t.io
A partner can opt for its own Distribution server, whereas the URIs mentioned above, will be defined by the hosting party.
The option of working without Distribution Service is also possible. You can find all the possibilities to run the Trust1Connector here
In some cases (environments) the Domain acc-ds.t1t.io or ds.t1t.io are not accessable. If this is because the domain cannot be resolved we do recommend to either ask the network/system administrator to make sure that those domains can be resolved on the network. Or changing the DNS server to the google DNS (8.8.8.8 & 8.8.4.4), this has solved the issue for some of our customers.
Disk Space
Keep in mind sizes can vary a bit depending on the Operating system and the environment (develop, acceptance, production)
Windows
Trust1Connector installer is about 20Mb in size. The installed size comes to 40-50Mb.
This includes the Trust1Connector API, Registry and Sandbox.
MacOS
Trust1Connector installer is about 20Mb in size. The installed size comes to 40-50Mb.
This includes the Trust1Connector API, Registry and Sandbox.
The increased size over windows mainly comes to the way MacOS handles dialogs. These are distributed with the Trust1Connector as seperate binaries.
API Key
All endpoints of the Trust1Connector API are secured and require a JWT to access. To obtain a token, an .
This API key must be requested from TRUST1TEAM, or created by the customer if they are hosting their own Distribution Service. The API key must never be used in a front-end application (where the API key can be compromised). The API key is needed to exchange the token, using a Distribution Server, resulting in a short-lived Json Web Token.
A PARTNER can decide to distribute a version without the use of a JWT. In those cases, the liability of the security flow resides completely in the context of the web application, thus Trust1Team can not guarantee the security context where the Trust1Connector is integrated upon.
Operating System
Trust1Connector support two operating systems for all tokens, Linux (Debian/Ubuntu) for PKCS11 tokens; On request, a Google Chromebook can be supported depending on the deployment or target installer.
MacOS 11.x or higher
X86 architecture
M1/M2/ARM architecture
Trust1Team support Windows/Mac OSX OS families where lifecycle support is guaranteed from the Vendor of the Operating System. The moment the OS version has been marked as ‘end of life’, Trust1Team can not guarantee the functionality anymore.
When PARTNERS are in need to support an older version or keeping the support running on the level of Trust1Team, no guarantees can be made. Trust1Team can setup a custom project, on demand of the PARTNER. Those requirements, changes or other adaptations needed, are not covered in the Trust1Connector license fee.
Supported OS or platform
Supported
Remarks
2023-10
macOS 14 (Sonoma) has issues at the moment with usblib and CCID. A future patch will fix the card reader issues; Updates will be come avaible when a patch is released
Windows 8.1 or higher
To run in user-space on Windows 8.1 or higher some components have to be set on the operating system
Registry keys
Below you can find a list of all registry keys that will be created for the working of the Trust1Connector, All these keys are added to HKCU
The Trust1Connector is browser agnostic so it does not matter what browser is being used as long as it support HTTP communication (HTTP 1.1) (which should all of them).
Version wise we do recommend to use the latest versions of your browser for security reasons but the versions below is was we accept as a minimum
Chrome >80
Firefox >75
Edge 88 or higher
Windows 810 or higher
Yes
macOS 10.15 (Cataline)
No
EOL
macOS 11 (Big Sur)
Yes
macOS 12 (Monterey)
Yes
macOS 13 (Ventura)
Yes
macOS 14 (Sonoma)
Yes*
IE 11 (End of Life is June 15 2022)
All other browsers. As recent as possible
Windows 7
No
EOL but some partners are running a custom compiled target of the Trust1Connector in production until migration.
Windows 8.1
No
EOL but some partners are running a custom compiled target of the Trust1Connector in production until migration. Reference
Shared environment - issue with 904300-Signature data does not equal the expected data: reg should not send out the signature in the responses (or verify if the client pub is correctly loaded for REMOTE environments) -> local is not an issue
Task
Apple al-tool deprecation for signing/notarization
Story
Direct download of SSL when digest is not equal to the published version on DS
Add the integration with Local Signing Application
Sidecar for Certificate check upon start and init
Add swagger-ui initial set of exposed apis
Provide an initial openApi spec for LSA module
Improvement
As an integrator I can ask T1C to digest data before sign for each module
v3.7.10
Release 03/10/2023
Release Notes
Bug
t1c-sdk-js make excessive failing "pre-flight" requests
Ds Logs push using CURL has issues -> not sending over the PUT json body
File exchange list content type on macos sometimes gives read access errors on a just created folder via the API
SSL certifiicate synchronisation does not happen after first startup
Update T1C SSL certificates when running binaries from user session, while binaries are located in admin location
Task
Update notarization in packager, altool being deprecated
RMCR - Upgrade sentry to latest version
Document Dashboard setup
Story
As a User/Support desk I would like to change the log-level (info|debug|warn)
As a System I need to keep my transactions between installations
Improvement
Update Cryptoki on Mac/Win for updated PKCS11 drivers
v3.7.9
Released 26/07/2023
Release notes
Bug
T1C-2735 Validate and consent Lock error on mutex should not return invalid consent but should give a propper try again later error
T1C-2780 As a system administator I want to see the transactions of devices - somehow the transactions don't reach the DS
Prevent the refresh needed when polling during connector update/upgrade
Task
Add version to the installer
Upgrade Rust Edition 2021
Update Clap
Story
As a connector running on a local device I want to support key rotation from the application consumer
Update clap to v4 as CLI parser
Enable insecure for debugging when running in dev mode
Update the token information returned to the web application to contain a valid type
Finalise PKCS11 session for each running instance when ending a remote transaction
Update the PNA specification as an extension on previous release (announced Google Chrome v117)
Add documentation for ReadMyCards Web Application used for demonstration and showcase
Upgrade utility libs
Initial version for an independant debugger
Improvement
Add tracing events to the connector api and registry
v3.7.7
Released 30/05/2023
Release notes
Bug
T1C-2102 JWT token validation consistently fails due to incorrect device time
Story
As a DS I need to provide a JWT token based on the time information of the requester.
Pass through the optional lable from the JWT SUB to the transactions file and DS
As a system I should be able to send the log files to the DS so that support can easily look for issues with a device
Improvement
As a client of the T1C API I want the api to validate the JWT token sent before proceeding with the use case
As a T1C API I want to renew the certificate needed for validation of the JWT when rotation happens on the DS
v3.7.5
Released 18/01/2023
Release notes
Bug
After registering the device a synchronisation needs to happen
v3.7.4
Released 22/12/2022
Release notes
Task
Upgrade compiler version to latest stable
Story
As a system I when installed in a separate folder I want to validate the SSL certificate validity and domain based on the root file
v3.7.2
Released 20/10/2022
Release notes
Story
As a system I should be able to send the log files to the DS so that support can easily look for issues with a device
v3.7.1
Released 20/10/2022
Release notes
Bug
Remove header that was added in 3.7.0 from testing APN (w3c draft) implementation which caused older versions to fail
v3.7.0
Released 19/10/2022
Release notes
Bug
Registry does not retrieve the base cors list on startup
Mutex lock causes Registry and api to go into a deadlock
When the user has a custom date/time set on his System it causes the API to crash on DS communication
Shared environment/multi user setup makes the Registry and API get in a deadlock state
Vulnerabilities based on Penetration test of Connective
Improvement
Use separate endpoint for reg to validate if api is registered on the correct user
As an integrator I can ask for all readers and ask to exclude readers by name
Story
As a system I want to use the private and public device key to encrypt and decrypt the response data so that an integrator/SDK can validate that no man in the middle attack has happened
🔺Mutex
The API and Registry use a feature called Mutexes to have data that can be shared over multiple OS threads. Using this is necessary for some functionality. In previous versions when you have a Shared environment (citrix for example) you could make the API and Registry get into what's called a DeadlockThis caused the Mutex to never be unlocked for use by another OS thread. Causing the connector to be blocked completely.This has now been solved and has been tested on instances of 1000 concurrent devices.
🔺System time out of sync
We had a user which Operating system had a custom date set (not synced) which caused issues with DS communication. The DS communication also checks wether the time of request is not in the future or in the past (with some slack ofcourse). So if you use the Connector with a custom date you will not be able to contact the DS because it requires a request within a correct time-zone.If this is not the case it could be that a malicious user is trying to exploit the DS at which point the DS refuses the request. The issue was that this caused the Connector to crash.This has been solved so that the Connector does not crash.System time must be correct, otherwise DS communication can not be done (secrity issue)
✅ Private Network Access
Private Network Access is a new CORS draft. Which prevents remote servers to contact local instances without any extra checks. Chrome has already implemented this draft in a non-blocking manner, the implemenation of chrome is to send 2 pre-flight requests. One which is the normal pre-flight and another one where the PNA implementation has been done.At this point the pre-flight for the PNA implementation is non-blocking meaning that if the pre-flight fails it will not block the request.When the PNA Cors draft is final this will become blocking.In this release we've already started adding some required components to support this in an upcoming release.
☑️ Sync log files with DS
In this release we've implemented a feature where the Connector will send it's log files towards the DS. This is so that support desks can easily get the log files of the device which is requesting support.
☑️ HTTP verify response signature
We've added a feature where you can run the Connector in regualr HTTP mode. To still be secure we've added a signature field to the responses which can be verified to not be tampered with at the client's side. This verification is implemented in the JS SDK.
v3.6.3
Released 19/08/2022
Release notes
Bug
t1c-sdk-js tries to validate any present consent token when consent is disabled (optional consent)
Improvement
Remove the implicit CORS request from API info endpoint to DS, and provide/expose a public function in JS for application to force a CORS sync
Story
As a dashboard user I want to see how many installation have the DNS rebind issue
v3.6.1
Javascript SDK 3.6.0 has been unpublished and contains a bug in the consent flow where the error code is not returned correctly
Released 01/04/2022
The Mac Silicon (M1) is not yet supported for this version
Release notes
Bug
Update consent error codes for 3.6.x so that they do not interfere with other error codes
Improvement
As an SDK integrator I want to be able to fetch all the certificates on a token, including their information
As a user I want to validate the signed hash from a PKCS11 token, using the validation function of the PKCS11 interface
Story
As a user I want ot use Camerfirma token
As a user I want to use Chambersign token
As a SDK integrator I want to be able to call the TokenInfo enpdoint on PKCS11 tokens
🔺 Consent error code update
The consent error code has been updated in the Trust1Connector API library, and t1c-sdk-js clients have no impact on that change
🔺 Multi-client support and race condition fix
When using different instances of the Trust1Connector (optionally from another partner) on a Windows system, a port collision could be possible due to a race condition in port assignment upon initialization. Ports are now protected with anti-collision and are salted to make a port less guessable.
🔺 Implicit creation of LaunchAgents folder on Mac/OSX
When no LaunchAgents folder was present on the system, the installation procedure creates this folder implicitly.
☑️ Exposed Camerfirma interface
Camerfima is a new PKCS11 token added to the modules of the Trust1Connector. The Camerfirma token pre-requisites the installation of the Carmerfirma middleware.
☑️ Exposed Chambersign interface
Chambersign is a new PKCS11 token added to the modules of the Trust1Connector. The Chambersign token pre-requisites the installation of the Chambersign middleware.
☑️ Token Info endpoint will now returned detailed information when using a PKCS11 token
The token info endpoint has been implemented before only for identity tokens. We have added support for Token Info of the PKCS11 modules. As the response has a different data structure, an additional type has been added for clients to parse the response correctly.
The PKCS11 token info exposes information on the algorithms which can be used for different use cases (digital signature, validation, authentication, ...). In a future release additional functionality will be provided such as: encryption, decryption, key exchange,...
✅ Fetch all the certificates on a token including all their information
For the different notification types, many tokens share multiple certificates for a single type. The original interface supported only a single certificate response. To be backwards compatible, those certification function have been adapted to be behave the same as in v3.5.x.
New functions are available to support multiple certificate reponses, they are called: [certificateType]Extended. For PKCS11 tokens the certificate response also returns, besides the base64 encoded certificate and the certificate id, the following properties:
issuer
subject
serial number
hash sub pub key
hash iss pub key
exponent (payment modules)
remainder (payment modules)
parsed certificate (ASN1 format of the base64 encoded certificate)
✅ Signed hash validation function exposed for PKCS11 tokens
A new function has been added for all PKCS11 modules called the 'validate' endpoint. This endpoint, when available, can be used to validate a signed hash received after calling the 'sign' function. In an next version a variant of the validation function using OpenSSL will be added for all tokens.
✅ PKCS11 migration towards RUST
For the Trust1Connector to support more PKCS11 functionality, the intermediate PKCS11 layer has been removed in preference of a direct PKCS11 LIB integration. FFI is used in RUST to support any library which need to be loaded.
✅ Token Algortihm input validation for signing and authentication
Additional guard has been implemented to prevent empty algorithms for the digital signature and validation endpoints. PKCS11 tokens will verify as well if the provided algortihm is exposed as an allowed mechanism for the targetted use case.
✅ JCOP3 ATR added
The Trust1Connector can now detec Java Card Object Platform 3 typed cards
✅ Select default PKCS11 non-repudation or authentication certificate
When requesting for a signature or an authentication, the correct certificate must be provided. For PKCS11 tokens the certificate id (or reference) can be ommitted. The PKCS11 token will be default pick the first certificate (for the type needed) and use this with the specified mechanism to sign/authenticate.
✅
Improvement upon the Trust1Connector
🔺
Bugfix
Concept
Running the Trust1Connector in a shared environment, such as Citrix, XenApp and Remote Desktop, requires additional installation steps. In this section we explain the concept and approach used.
Architecture Overview
The following schematic seems rather complicated as it explains the inner workings of the Trust1Connector components, the concept is elaborate further on this page. If you are only interested in what the integration impact is for your Web Application in a Shared Environment, you can skip directly to the section: Integration in Web Applications
Component Diagram
Components
Web Environment
The Web Application can use the T1C-SDK-JS or a custom REST API client for integration purpose. As the Web Application operates in a browser context, resolving an agent, by means of a consent, will result in a browser cookie being provided.
The T1C-SDK-JS implements the detection of a Shared Environment during the initialisation of the library. When initialisation succeeds without a controlled exception, the setup is a standalone; when the initialisation throws an 401 Error, the T1C-SDK-JS can be used to request the user for a Consent.
When using the REST API directly form your web application, reading the browser cookie and performing the initialisation must be done by the integrating Web Application itself.
Shared Environment Host
Compared to Trust1Connector v2, the v3 release has a separate component to be be installed on a shared host. This component is called the T1C-Proxy and only exposes the following use cases:
Verify random available ports [in a predefined range] which can be used by an Agent (Session of T1C-API running in user space)
Port reservation upon installation of a new T1C-API in an active user session
Port registration upon initialisation of a T1C-API in an active user session
The T1C-Proxy operates by Default on the API port defined in the T1C-DS (Distribution Server). From a Web Application perspective, this is the only information known. When a Web Application requests the information of the device, the PROXY device type will inform the Web Application that the targeted underlying API is a PROXY, which means that the Web Application must ask for the Agent specific API port to configure an URI which can be used to execute the use cases.
When using the T1C-SDK-JS this is done implicitly during initialisation.
Shared Environment Client
A T1C-API installed for a specific users runs in [User Space]. To avoid possible attack vectors, the Trust1Connector v3 will always run in [User Space].
Upon installation of the T1C-API, during the post install phase, the T1C-API will try to verify automatically if it is running in a shared environment. If this is the case, the T1C-API will ask the T1C-Proxy for available ports and will reserve those post, prior to initialisation and startup.
The ports which are reserved by the T1C-Proxy are the following:
T1C-API Port: This is the port exposing the OpenAPI interface towards Web Applications and used by the T1C-SDK-JS
When receiving ports during post-install, an user agent device is temporary RESERVED in the Agent Registry of the T1C-Proxy. Upon T1C-API initialisation, the port configurations will be confirmed and the Agent Registry will set the device state on REGISTERED. From this moment on, a T1C-API instance, running in an active user session, will be available for the Web Application via the .
The T1C-gRPC instance is inherently a component from the T1C-API, and thus is managed by the T1C-API. As each user must have it's own hardened runtime for communication purpose, the port assigned for T1C-gRPC will be registered and configured by the T1C-API (and restarted when needed).
Central Back-Office
Starting from this release (v3) of the Trust1Connector, each device must have a link with an active and running T1C-DS (Trust1Connector Distribution Server). This is to guarantee security, updates, and avoid potential risk in production.
The T1C-DS is proceeded by an API Gateway who is managing the security offloading in the application layer. For a Web Application to communicate with a T1C-Proxy or T1C-API, a JWT (Json Web Token) is needed and obliged. The T1C-DS is responsible for the key management, the certificate management and other use cases which are described in a separate wiki.
In order to retrieve a valid JWT, the T1C-DS can be requested from your application back-end with a valid api-key. The JWT is valid for a given amount of time, and sets the context used when requesting the T1C-API on a device.
Security
Pin Handling
The PIN handling logic is implemented in the Trust1Connector API. More information on the basic and/or advanced rules can be found on the following link:
Share Environment Flows
Communication Stack
Downloading latest Trust1Connector
Downloading Trust1Connector
The T1C JS SDK no longer has a method to download the T1C installer.
Instead, the T1C installer can be downloaded by navigating the client browser to the /v3_5/downloads/installer endpoint of the Distribution Service (e.g. https://acc-ds.t1t.io/v3_5/downloads/installer). The Distribution Service will analyse the User-Agent
header and automatically initiate the download of an OS-appropriate installer of the latest configured version. The user agent string parsing is considered "best-effort"; as they can vary wildly depending OS and browser software.
Alternatively, you can also initiate the download of a T1C installer with the following endpoints:
/v3_5/downloads/installers/{{OS}}: This endpoint allows you to specify the OS for which you wish to obtain an installer. The possible values are win32, win64, unix, macosmacosarm.
/v3_5/downloads/installers/{{OS}}/versions/{{version}}: This endpoint allows you to download a specific version of a T1C installer for a specific OS.
If using the generic endpoint 3_5/downloads/installer
The automatic user-agent detection also does not differentiate between ARM/M1 and Intel Mac devices
Differentiate between MacOS architectures
For MacOS there are currently 2 supported architectures:
ARM64 (M1, ...)
Intel x86_64
Currently, browsers etc do not display which architecture you're running. So in order to provide download links to the users you need to provide them with the option to download any of the 2 architectures. The user needs to decide which platform he is running.
From the DS you can get both links with the following URL's (Production DS is used in the example);
After this, you can provide the user with the choice of which one they want to download. Below you can see an example of how Google does this with their Browser, Google Chrome.
Here you can clearly see they provide two versions, with a recommendation on Intel because the majority of the users still run Intel Apple devices
Distribution services
Below you can find a list of Distribuction services available from Trust1Team. If you are integrating with a 3rd party that uses the Trust1Connector you can contact them for information regarding the Distribution services.
Environment
DS url
Acceptance
https://acc-ds.t1t.io
Production
https://ds.t1t.io
Example upgrade flow
Information below is an example. If the integrator pleases he can alter the flow to their business use-case
Via the Distribution service you can fetch the latest available version. This can be done via the call
This will return all information needed from the latest version, for example our latest version at this point returns:
You can check the boolean values mandatoryrecommended and allowed to determine a pop-up for example, so that the user can download and use this Trust1Connector.
You can also retrieve the same information for a specific version. This endpoint returns the same response type as the latest version call:
In the call above, you can substitute 3.6.0 for the desired version ID
Example screenshot below of our demo-application (rmc.t1t.io)
Below you can find an example of how an version check can be implemented in your front-end application.
Consent
Introduction
The Trust1Connector requires a user consent to function. This consent will be stored in the browsers localstorage for that user.
The consent token is stored with a domain specific key;t1c-consent-{{applicationDomain}}::{{apiUrl}}
curl --location --request GET 'https://acc-ds.t1t.io/v3_5/versions/3.6.0' \
--header 'Authorization: Bearer eyJh...BCr8Q'
When executing the consent flow, the user will be provided with a consent token which can be pasted into his clipboard. This token has to be passed with the Consent function which will perform a verfication (the token pasted in the clipboard - form the application context - should match with the token available on the clipboard for the T1C).
The consent can be configured to have an expiration date, when this expiration date has been exceeded, a new consent will be asked towards the user.
Consent dialog for implicit consent
Upon installation of the Trust1Connector, a user will not be able to retrieve any data from the connector without first giving its consent, agreeing to give access to his/her card reader of filestorage. Without this consent, all requests will return a 401/404 Unauthorized response with error No valid consent found or at initialisation of the Trust1Connector SDK an error No valid consent found. The application should detect these errors and use it to trigger the consent dialog.
The application shows this code word on screen and provide a button for 'copy-to-clipboard'. When the user has copied the code word to the clipboard (on user click button event), an implicit consent request can be executed towards the T1C. The T1C will grab the pasted code word from the user system clipboard and if both match, an implicit user consent has been granted for the calling application. The relation between the application and the local T1C instance is 'approved'. At this point the Trust1Connector returns a verified consent object that is stored in the browser's localstorage. This object is used to validate the consent and retrieve the necessary information for the Trust1Connector to function. This object will be re-used the next time the user wants to use the Trust1Connector until the consent expires.
Generating a random clipboard value
The clipboard value is a random value that is used to determine which agent you are running. This clipboard value needs to be pseudorandom so that we dont accidently find different agent.
The Javascript has an exposed function that creates this value for you.
The function is statically available on the T1CClient class and has the following interface.
This will return the randomly generated value as a string value immediatley.
To call this;
If you decide not to use this function, the value needs to be prefixed with `::t1c::miksa::
User clipboard remark
Initially the concept was based on copying programmatically the code word, from the application context, to the user system clipboard. Although, through CAB forum, this not allowed; A user interaction is mandatory. The application should provide a 'copy-to-clipboard' button or alike in order to 'trigger' a user action. Once this action has been done, the T1C can be triggered to execute the consent.
Currently, the need for a user interaction is a known limitation (aka. clipboard.js). As this is the case, the W3C has a project ' Clipboard APIs' to propose a solution for a new clipboard API in browsers. The use case for 'Remote clipboard synchronisation' as a use case included in this draft proposal. As this is a draft, and not yet supported by the browsers, we can not perform an automatic 'paste' ('copy' in terms of the browser) to the clipboard.
Sending an implicit consent request can be done as follows:
The code below is an example of a javascript event handler on a consent button.
This call has 1 required and 2 optional parameters:
Code Word(required): a code word in string format that will be shown in the consent dialog.
Consent duration in days (optional): Allows the application the specify how long this consent is to be valid if granted. If not provided, the default value is 365 days.
Callback function(optional): function to be called with the result of the consent request.
The response of the consent will be an updated T1C Client which you after this point can use to continue your use-case(s).
The response can also be a 400 Bad Request with status code 814501 "Invalid consent" or 814500 "No agents registered" which means that the request has been sent with the unique code but the Registry cannot not find the user associated with it by checking the clipboards of all connected users.
This could mean that there is no T1C API client present or it is not running correctly.
public static generateConsentToken(): string
# regular imported javascript via script tag
T1CSdk.T1CClient.generateConsentToken()
# Import loaded via NPM
import {T1CClient} from "t1c-sdk-js";
T1CClient.generateConsentToken()
$('#consentModal .btn-primary').on('click', (ev) => {
const tokenNode = document.querySelector('.consent-token');
var range = document.createRange();
range.selectNode(tokenNode);
window.getSelection().addRange(range);
try {
document.execCommand('copy');
} catch (err) {
console.log('Oops, unable to copy');
}
window.getSelection().removeRange(range);
const clipboardData = tokenNode.textContent;
const validityInDays = 365
client.core().getImplicitConsent(clipboardData, validityInDays).then(consentRes => {
client = consentRes // replace the client and other set variables of the T1C
core = client.core();
core.version().then(versionResult => console.log("T1C running on core " + versionResult));
$('#consentModal').modal('hide');
}, err => {
console.error(err)
})
});
Authenticated client
Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.
Introduction
The Trust1Connector API requires a valid JWT token to be provided in the Authorization header. This JWT token can be retrieved by asking the Distribution Service to generate a token for a specific API-key.
It is important that this API-key is not exposed in the front-end application as this is a security violation.
When you've received a valid JWT token from the DS you can provide this into the configuration object when initialising the Trust1Connector JS client.
When using the Trust1Connector Javascript SDK the Authorization header is automatically populated with the JWT provided while initialising.
When the Token has expired there is a function which you can call to provide a new token and which will in turn return an updated client to be used.
Retrieving a JWT token
Retrieving a valid JWT token happens via the DS. When passing a valid API-key to header of the endpoint {{ds-url}}/v3/tokens/application (GET) you wil in turn receive a valid JWT token.
Example response
Refresh JWT token
Refreshing the JWT token can only be done after a first successfull initialisation of the Trust1Connector. This means the Trust1Connector has to be initialised with a valid configuration the first time. When the token expires after first successfull initialisation you can use the refreshJWT function described below
A JWT token is only valid for a certain period. After this period the API will return an error. At this point you need to request a new JWT token to be able to communicate with the API.
In the T1C JS SDK there is a function which you can use to re-initalise the client with a new valid JWT token. This should be done when you receive a 104025 error-code which means you do not have a valid JWT
The updateJWT function can be found in the Core service. After initialising you can retrieve the core as follows:
The function's interface is as follows;
This function returns an updated client which you can continue to use for your desired use-cases.
Distribution services
Environment
DS url
Acceptance
https://acc-ds.t1t.io
Production
https://ds.t1t.io
// Config object definition
export class T1CConfigOptions {
constructor(
public t1cApiUrl?: string,
public t1cApiPort?: string,
public t1cProxyUrl?: string,
public t1cProxyPort?: string,
public jwt?: string
) {}
}
// example
const configoptions = new T1CSdk.T1CConfigOptions(
environment.t1cApiUrl,
environment.t1cApiPort,
environment.t1cProxyUrl,
environment.t1cProxyPort,
environment.jwt
);
config = new T1CSdk.T1CConfig(configoptions);
curl --location --request GET 'https://acc-ds.t1t.io/v3_5/tokens/application' \
--header 'apikey: your-api-key'
Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.
Introduction
This page describes all generic token models used.
Models
export class ModuleDescriptionResponse extends DataObjectResponse {
constructor(public data: TokenModuleDescription, public success: boolean) {
super(data, success);
}
}
export class TokenCertificateResponse extends T1CResponse {
constructor(public data: TokenCertificate, public success: boolean) {
super(success, data);
}
}
export class TokenCertificate {
constructor(
public certificate?: string,
public certificates?: Array<string>,
public certificateType?: string,
public id?: string,
public parsedCertificate?: Certificate,
public parsedCertificates?: Array<Certificate>
) {}
}
export class TokenAddressResponse extends DataObjectResponse {
constructor(public data: TokenAddressData, public success: boolean) {
super(data, success);
}
}
export class TokenPictureResponse extends DataObjectResponse {
constructor(public data: TokenPictureData, public success: boolean) {
super(data, success);
}
}
export class TokenVerifyPinResponse extends DataObjectResponse {
constructor(public data: TokenVerifyPinResponseData, public success: boolean) {
super(data, success);
}
}
export class TokenVerifyPinResponseData {
constructor(
public verified: boolean
) {}
}
export class TokenSignResponse extends DataObjectResponse {
constructor(public data: TokenSignResponseData, public success: boolean) {
super(data, success);
}
}
export class TokenSignResponseData {
constructor(
public data?: string
) {}
}
export class TokenAuthenticateResponse extends DataObjectResponse {
constructor(public data: TokenAuthenticateResponseData, public success: boolean) {
super(data, success);
}
}
export class TokenAuthenticateResponseData {
constructor(
public data?: string
) {}
}
export class TokenModuleDescription {
constructor(
public desc: string
) {}
}
export class TokenAddressData {
constructor(
public municipality?: string,
public rawData?: string,
public signature?: string,
public streetAndNumber?: string,
public version?: number,
public zipcode?: string
) {}
}
export class TokenAllDataResponse extends DataObjectResponse {
constructor(public data: TokenAllData, public success: boolean) {
super(data, success);
}
}
export class TokenAllData {
constructor(
public picture?: TokenPictureData,
public biometric?: TokenBiometricData,
public address?: TokenAddressData,
) {}
}
export class TokenPictureData {
constructor(
public picture?: string,
public signature?: string,
public width?: number,
public height?: number,
) {}
}
export class TokenData {
constructor(
public rawData?: string,
public version?: string,
public serialNumber?: string,
public label?: string,
public prnGeneration?: string,
public eidCompliant?: string,
public graphicalPersoVersion?: string,
public versionRfu?: string,
public electricalPersoVersion?: string,
public electricalPersoInterfaceVersion?: string,
public changeCounter?: number,
public activated?: string,
) {}
}
export class TokenDataResponse extends DataObjectResponse {
constructor(public data: TokenData, public success: boolean) {
super(data, success);
}
}
export class TokenBiometricData {
constructor(
public birthDate?: string,
public birthLocation?: string,
public cardDeliveryMunicipality?: string,
public cardNumber?: string,
public cardValidityDateBegin?: string,
public cardValidityDateEnd?: string,
public chipNumber?: string,
public documentType?: string,
public firstNames?: string,
public name?: string,
public nationalNumber?: string,
public nationality?: string,
public nobleCondition?: string,
public pictureHash?: string,
public rawData?: string,
public sex?: string,
public signature?: string,
public specialStatus?: string,
public thirdName?: string,
public version?: number,
public issuer?: string
) {}
}
export class TokenBiometricDataResponse extends DataObjectResponse {
constructor(public data: TokenBiometricData, public success: boolean) {
super(data, success);
}
}
export class TokenAlgorithmReferencesResponse {
constructor(public data: TokenAlgorithmReferences, public success: boolean) {
}
}
export class TokenAlgorithmReferences {
constructor(public ref: Array<string>) {
}
}
export class TokenResetPinResponse {
constructor(public data: TokenResetPin, public success: boolean) {
}
}
export class TokenResetPin {
constructor(public verified: boolean) {
}
}
export class PinType {
static PIN = 'Pin';
static CAN = 'Can';
}
// Requests
export class TokenAuthenticateOrSignData {
constructor(public algorithm: string, public data: string, public pin?: string, public pace?: string, public id?: string, public osDialog?: boolean, public txId?: string, public language?: string, public base64Encoded?: boolean, public timeout?: number) {
}
}
export class TokenVerifyPinData {
constructor(public pin?: string, public pace?: string, public osDialog?: boolean, public base64Encoded?: boolean, public timeout?: number) {
}
}
export enum TokenResetPinReferenceType {
issign = "issign",
isauthenticate = "isauthenticate",
isencrypt = "isencrypt"
}
export class TokenResetPinData {
constructor(
public puk: string,
public pin?: string,
public resetOnly?: boolean,
public osDialog?: boolean,
public reference?: TokenResetPinReferenceType,
public base64Encoded?: boolean) {
}
}
export class PaymentVerifyPinData {
constructor(public pin?: string, public osDialog? :boolean, public base64Encoded?: boolean, public timeout?: number) {
}
}
export class PaymentSignData {
constructor(public txId: string, public language: string, public data: string, public timeout?: number) {
}
}
export class TokenCertificateExtendedResponse extends T1CResponse {
constructor(public data: TokenCertificateExtended, public success: boolean) {
super(success, data);
}
}
export class TokenCertificateExtended {
constructor(
public certificates?: Array<T1CCertificate>
) {
}
}
export class T1CCertificate {
constructor(
public certificate?: string,
public certificateType?: string,
public id?: string,
public subject?: string,
public issuer?: string,
public serialNumber?: string,
public url?: string,
public hashSubPubKey?: string,
public hashIssPubKey?: string,
public exponent?: string,
public remainder?: string,
public parsedCertificate?: Certificate
) {
}
}
Initialize Trust1Connector
Introduction
For initialisation of the T1C you need to prepare your application first by adding the SDK JS files to your project and importing them in such a way that you can call for the Javascript functions when you need them. When you've succesfully downloaded and installed the Trust1Connector you can initialize and use the Trust1Connector
Mode of operations
The Trust1Connector's architecture is created so that we can support a wide range of system setups. This means we can both support single users using the Trust1Connector but also systems where multiple users make use of the same hardware, we call this shared environments.
Additionally to shared environments, we support remote desktops as an extension on shared environments.
Since Trust1Connector version 3.6.1 we can provide integrators the support to initialise the Trust1Connector in different ways.
Single Instance Without Consent
Please contact support if you need support for this modus. As this is not the default mode and requires the Trust1Connector to be run in a specific context
Using this operation mode, the integrator can decide to use the Trust1Connector and inforce that no consent is needed. making it very straightforward for the end-user to utilise any functionality the Trust1Connector offers.
In this mode we cannot support multiple instances of the Trust1Connector. Meaning shared environments and multiple users logged in on the same system can create unexpected behaviour.
Single Instance With Consent
This is the default mode of operation and goes hand-in-hand with instances. A consent is required to both request the user's permission to use the Trust1Connector on his system and also to correctly determine which instance of the Trust1Connector needs to be used.
The Consent provides support to use the Trust1Connector with multiple users on the same system ().
Using Single Instance with consent as an operational mode, enforeces users to consent unregarded the environment - be it single device or multi user environment. Validity of the consent can be determined by the application.
Multi-user Instance With Consent
Just like the this mode requires a consent to both ask permission to the user and determine the correct instance of the Trust1Connector Agent/API.
This mode support shared environments such as Citrix, terminal server and remote desktop.
Creating the configuration object
We will prepare the SDK's configuration Object, this object is used to pass information about which default port the Trust1Connector is running on, JWT key, API url, ... which is needed to properly contact and use the Trust1Connector.
When the Trust1Connector is configured with a Distribution Service in mind you can provide a valid JWT token in the configuration object. .
Retrieving JWT tokens should be handled in your own backend to maximize security
Now we can create a complete Configuration Options object to be passed to the Trust1Connector.
T1CConfigOptions
The T1C config options is a class that can be used to create a valid configuration object to initialize the Trust1Connector. Below you can find a class definition.
t1cProxyUrl and t1cProxyPort are deprecated since 3.5.x and only used in 3.4.x versions.
Parameters
t1cApiUrl: stringOptionalThe URL that connects to the local Trust1Connector instances. This can be either localhost or a domain that directs towards localhost. By default this will be https://t1c.t1t.io
t1cApiPort: stringOptionalThe port defined to be used for the Trust1Connector. By default this is 51983
t1cProxyUrl: stringOptional - DeprecatedThe URL that connects to the local Trust1Connector Proxy instances. This can be either localhost or a domain that directs towards localhost. By default this will be https://t1c.t1t.io
t1cProxyPort: stringOptional - DeprecatedThe port defined to be used for the Trust1Connector Proxy. By default this is 51983
jwt: stringOptionalThe JWT token that is used to authenticate towards the Trust1Connector. This should be retrieved from the DS and is only needed when the Trust1Connector is configured to work with a DS and requires JWT validation
applicationDomain: stringOptionalThe domain of the application that is using the Trust1Connector. This is used to make sure the consent is only available for a specific web-application. This prevents various clients to interfere with eachother.
This domain also tags the Distribution service transactions being sent to the Distribution service. This makes it easy to distinguish between applications/tags for the transactions
When a remote DS is used you can set the following field with the correct DS url, this will in turn use the DS's capabilities of acting as a Trust1Connector proxy for enchanced security.
Now we can continue to use the config variable to and retrieve a T1CClient
Authenticated client
If you need to set up the Trust1Connector with a valid JWT token you can follow the documentation on the to from the DS.
When you have a valid token you can provide this in the Configuration. This will make sure the Trust1Connector is usable until the token becomes unvalid. At which point you can your token to continue to use the Trust1Connector. More information on how to retrieve,use and refresh a token can be found on the .
Initializing the Trust1Connector SDK
Initialization of the Trust1Connector in many cases requires a user consent, the exception being when no registry is configured (either local or central) and if the Trust1Connector is run in a enabled. More information can be found . The registry allowed us to create a Trust1Connector that works in any environment, without the need for Administrative rights from the users, wether it be Standalone, Multi session, RDP, Citrix, ...
To Initialize the Trust1Connector a is required(when a central or local registry is present) or when the . When no consent can be found the error codes 814500 or 814501 will be thrown. This means that either the previous consent is not valid anymore or no consent was given yet.
More information regarding the consent can be found on the which explains it in more detail.
If you have the enabled the consent error will not appear but will either give a valid Client to use or a 112999 error, depicting it could not find any active instance of the Trust1Connector.
When either no consent is present or its invalid you will receive a invalidclient object (line 8 in example above) that can be used to trigger the getImplicitConsent function in the Core serivce.
The Consent requires a user action to . This data is used by the T1C registry to make sure you're targetting the correct instance of the Trust1Connector. More information about this can be found here.
The signature of the getImplicitConsent function is as follows;
This function expects:
codeword: stringThe string value that is saved to the user's clipboard needs to be sent to the Consent function.
durationInDays: numberOptionalAmount of days that the consent is valid.
callback: (error?: T1CLibException, data?: T1CClient)OptionalCallback when you're not using ES
Below is a small javascript example of how you can trigger the getImplicitConsent function
After this you will have a client that can be used to execute the rest of the functionality that the Trust1Connector has to offer.
Full example
Enforcing consent flow in a optional consent enabled Trust1Connector
When your instance of the Trust1Connector has the optional consent mode enabled but still want to enforce the consent flow you can use the following explicit consent initialisation.
This will ignore the enabled feature of having the consent being optional and will require a valid consent to operate the Trust1Connector.
Clipboard
To provide a consent, we suggest you use the clipboard functionality available in browsers. The most supported way is via document.exeCommand and below you can find an example of this.
There is also a but this is not fully supported yet
The code below is an example of how you can integrate a copy command in the webbrowser
Retrieve JWT token
GEThttps://ds.t1t.io/v3_5/tokens/application
This endpoint will return a valid JWT token to use for a certain period based on the API-key you provide in the `apikey` header
Headers
Name
Type
Description
Trust1Connector environments
The Trust1Connector has a Develop, Acceptance and production version. The difference between them is mainly the Distirbution service connection and the port number they use.
These port numbers are linked to the Trust1Connector distributed by Trust1Team. If you have a custom installation these will be different. Please contact your distributor for more information.
The port numbers of the Trust1Connector are;
Environment
Port number
Distribution service
Module/container setup
Introduction
This document will describe how you can set up your desired module or generic module for using the functionalities that each module have. This ofcourse requires you to succesfully initialized the Trust1Connector via or and have a
When the user has selected his desired reader to use we can continue to initialize the module to use. This requires at least the readerID to properly initialize.
Some modules like the LuxID module require you to also add a additional pin and pinType for example, this will also need to be provided in the module initialization.
To initialize a module we first need the client as described in the introduction, here's a quick happy flow of how to retrieve a T1CClient
When we have the T1CClient we can use this to choose our module. We can also use the generic interface if we want.
the reader_id is the identifier which can be retrieved from the readers functionality
Base module initialization
Below is an example of how to iniailize the Belgian EID module. This is a specific module that has all the functionalities for the Belgian EID card. You can see we use the client to fetch an instance of the beid module which we can further use to execute any functionality exposed on the beid module.
now we can use this to for example fetch all the available token data;
Generic
Generic Token
Ofcourse we can also use the generic interface which has all the functions exposed that you can use for all the modules.
This will require you to always provide the module when you call any of its functions. Because it still needs to know which commands it needs to send to the card/token.
When we now want to execute a getAllData for beid we would call it like this;
Generic is split up in 2 different generic modules. This is because the payment modules differ to much from the regular tokens.
Generic Payment
To initialise a generic payment module its very similar to the token version but the available functions will differ.
When we now want to execute a readData for emv we would call it like this;
Interfaces
Below you can find an overview of the generic interfaces. This shows what functions are available on both. If you want more information about a specific token/module you need to go to their respecitve pages which will explain more in detail what you can do with them.
Generic Token interface
Generic Payment interface
Available modules
Below is a list of the available modules;
generic
paymentGeneric
fileex
rawprint
beid
remoteloading
emv
crelan
aventra
oberthur
idemia
luxeid
wacom
diplad
certigna
certinomis
dnie
safenet
eherkenning
jcop
airbus
luxtrust
camerfirma
chambersign
Functions
these are the exposed functions available on the T1CClient to initialize a module
class T1CConfigOptions {
constructor(
public t1cApiUrl?: string,
public t1cApiPort?: string,
public t1cProxyUrl?: string, // deprecated
public t1cProxyPort?: string, // deprecated
public jwt?: string,
public applicationDomain?: string, // "rmc.t1t.be"
) {}
}
client.core().getImplicitConsent(document.querySelector(".clipboard-data").innerHTML).then(res => {
console.log("Consent Executed")
client = res;
// Use the client for your use-cases
}, err => {
// Failed, use the error client to retry the consent
this.client = err.client;
console.error(err.description ? err.description : err)
})
// Global client to be used over the entire application
const client = null
// Prepare the configuration
let environment = {
t1cApiUrl: 'https://t1c.t1t.io',
t1cApiPort: '51983',
t1cProxyUrl: 'https://t1c.t1t.io',
t1cProxyPort: '51983',
jwt: 'eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0..._Mg2PfdhCMQ',
applicationDomain: 'test-app'
};
const configoptions = new T1CSdk.T1CConfigOptions(
environment.t1cApiUrl,
environment.t1cApiPort,
environment.t1cProxyUrl,
environment.t1cProxyPort,
environment.jwt,
environment.applicationDomain
);
config = new T1CSdk.T1CConfig(configoptions);
// Initialize the Trust1Connector with the previously created configuration object
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
console.log("Client config: ", client.localConfig);
core = client.core();
core.version().then(versionResult => console.log("T1C running on core "+ versionResult));
}, err => {
if (err.code == 814500 || err.code == 814501) {
// (new) Consent is required
}
else if(err.code == 112999) {
// Could not connect with the Trust1Connector
} else {
// an uncatched error occured
console.error("T1C error:", err)
}
});
// when the user has clicked on the clipboard/consent button we execute the getImplicitConsent function
document.querySelector(".clipboard").addEventListener("click", (ev) => {
if (client != null) {
client.core().getImplicitConsent(document.querySelector(".clipboard-data").innerHTML).then(res => {
console.log("Consent Executed")
client = res;
// Use the client for your use-cases
}, err => {
this.client = err.client;
console.error(err.description ? err.description : err)
})
}
})
// ...
T1CSdk.T1CClient.initializeExplicitConsent(config).then(res => {
client = res;
console.log("Client config: ", client.localConfig);
core = client.core();
core.version().then(versionResult => console.log("T1C running on core "+ versionResult));
}, err => {
if (err.code == 814500 || err.code == 814501) {
client = err.client;
// (new) Consent is required
}
else if(err.code == 112999) {
// Could not connect with the Trust1Connector
} else {
// an uncatched error occured
console.error("T1C error:", err)
}
});
// ...
const tokenNode = document.querySelector('.consent-token');
var range = document.createRange();
range.selectNode(tokenNode);
window.getSelection().addRange(range);
try {
// Now that we've selected the anchor text, execute the copy command
document.execCommand('copy');
} catch(err) {
console.log('Oops, unable to copy');
}
// Remove the selections - NOTE: Should use
// removeRange(range) when it is supported
window.getSelection().removeRange(range);
const clipboardData = tokenNode.textContent;
public generic = (reader_id: string, pin?: string, pinType?: PinType): AbstractEidGeneric => {
return this.moduleFactory.createEidGeneric(reader_id, pin, pinType)
};
public paymentGeneric = (reader_id: string): AbstractPaymentGeneric => {
return this.moduleFactory.createPaymentGeneric(reader_id)
};
public fileex = (): AbstractFileExchange => {
return this.moduleFactory.createFileExchange()
};
public rawprint = (): AbstractRawPrint => {
return this.moduleFactory.createRawPrint()
};
public beid = (reader_id: string): AbstractEidBE => {
return this.moduleFactory.createEidBE(reader_id)
};
public remoteloading = (reader_id: string): AbstractRemoteLoading => {
return this.moduleFactory.createRemoteLoading(reader_id)
};
public emv = (reader_id: string): AbstractEmv => {
return this.moduleFactory.createEmv(reader_id)
};
public crelan = (reader_id: string): AbstractCrelan => {
return this.moduleFactory.createCrelan(reader_id)
};
// get instance for Aventra
public aventra = (reader_id: string): AbstractAventra => {
return this.moduleFactory.createAventra(reader_id);
}
// get instance for Oberthur
public oberthur = (reader_id: string): AbstractOberthur73 => {
return this.moduleFactory.createOberthur(reader_id);
}
// get instance for Oberthur
public idemia = (reader_id: string): AbstractIdemia => {
return this.moduleFactory.createIdemia(reader_id);
}
public luxeid = (reader_id: string, pin: string, pin_type: PinType): AbstractEidLux => {
return this.moduleFactory.createEidLUX(reader_id, pin, pin_type);
}
public wacom = (): AbstractWacom => {
return this.moduleFactory.createWacom();
}
public diplad = (reader_id: string): AbstractEidDiplad => {
return this.moduleFactory.createEidDiplad(reader_id);
}
public certigna = (reader_id: string): AbstractCertigna => {
return this.moduleFactory.createCertigna(reader_id);
}
public certinomis = (reader_id: string): AbstractCertinomis => {
return this.moduleFactory.createCertinomis(reader_id);
}
public dnie = (reader_id: string): AbstractDNIe => {
return this.moduleFactory.createDNIe(reader_id);
}
public safenet = (reader_id: string): AbstractSafenet => {
return this.moduleFactory.createSafenet(reader_id);
}
public eherkenning = (reader_id: string): AbstractEherkenning => {
return this.moduleFactory.createEherkenning(reader_id);
}
public jcop = (reader_id: string): AbstractJcop => {
return this.moduleFactory.createJcop(reader_id);
}
public airbus = (reader_id: string): AbstractAirbus => {
return this.moduleFactory.createAirbus(reader_id);
}
public luxtrust = (reader_id: string): AbstractLuxTrust => {
return this.moduleFactory.createLuxTrust(reader_id);
}
public camerfirma = (reader_id: string): AbstractCamerfirma => {
return this.moduleFactory.createCamerfirma(reader_id);
}
public chambersign = (reader_id: string): AbstractChambersign => {
return this.moduleFactory.createChambersign(reader_id);
}
Status codes / error handeling
Introduction
In the Trust1Connector V3 we've completely reworked the error system. The goal of this system is to have error codes which are easy to read, understand and integrate. Our first implementation was a very generic approach with as few error codes as possible.
After some iterations of the Trust1Connector we've discovered that the old error system did not suffice the needs of integrators.
So we've upgraded the system to be more consistent and extensive. This provides integrators the flexibility to have a very detailed error handeling system while keeping it easy to understand and read.
The new system provides information about the origin, type and detailed information of the error. We maintained the same type (integers) as our previous error codes, this makes it easier to differentiate them.
Status Codes
T1C uses response codes when handling a request.
In case of an error the response will contain a body with more detailed information about the error:
Error format
Error codes will be in the following number format XXXXXX for example 201010 is an error code that depicts an error occurred with the reader in the Transaction service.
The first digit depicts the Origin of that error, values can be the following;
The following 2 digits describe the type of error;
Finally we have 3 digits that give a more detailed error. These will give you more information about the specific error-case.
Currently we have the following exceptions that can be thrown.
Codes to expect
The following list are codes that you can expect.
General / Controller
Aventry My Id 4
Oberthur 7.3
Idemia cosmo 8.2
BeID
Diplad
Luxtrust
Luxeid
EMV
Crelan
File exchange
Error codes coming from v2
Simple error handeling
The most simple way you can check the error codes is by only taking into account the latest 3 digits. The first 3 digits provide information about the Context and environment
Identity service
7XXXXX
Reader service
8XXXXX
Proxy
9XXXXX
System
Input
X07XXX
Session
X08XXX
PIN
X09XXX
PUK
X10XXX
Pace
X11XXX
Module
X12XXX
System
X13XXX
I/O
X14XXX
Consent
X15XXX
Agent
FunctionNotSupportedException
XXX005
FunctionNotAvailableException
XXX006
FunctionNotImplementedException
XXX007
ServiceNotSupportedException
XXX008
ServiceNotAvailableException
XXX009
ServiceNotImplementedException
XXX010
ReaderException
XXX011
ReaderTimeoutException
XXX012
ReaderProviderException
XXX013
ReaderNotAvailableException
XXX014
ReaderCancelledException
XXX020
InitialisationException
XXX021
DistributionServiceException
XXX022
GenericRestException
XXX023
JsonParseException
XXX024
JWTParseException
XXX025
ForbiddenException
XXX026
UnauthorisedException
XXX028
DeviceKeyStoreMissingException
XXX029
ParamRestException
XXX030
ProxyServiceException
XXX031
InvalidStateException
XXX032
DeviceKeyException
XXX040
TransactionException
XXX041
TransactionNotFoundException
XXX042
TransactionNotSupportedException
XXX043
TransactionProviderException
XXX044
ApplicationLockedException
XXX045
PaceLayerException
XXX046
TransactionPinBlockedException
XXX047
TransactionInvalidPinException
XXX048
TransactionPukBlockedException
XXX049
TransactionInvalidPukException
XXX050
TransactionPinTimeoutException
XXX051
TransactionPinCancelledException
XXX052
TransactionSignAuthenticateErrorException
XXX053
CardProtocolException
XXX054
ApduException
XXX060 - XXX069
TransactionPukException
XXX070 - XXX079
TransactionPinException
XXX090
EncryptionException
XXX100
CertificateException
XXX101
CertificatePinException
XXX102
CertificateNotFoundException
XXX103
CertificateProviderException
XXX104
MetaException
XXX105
MetaPinException
XXX106
MetaNotFoundException
XXX107
MetaProviderException
XXX110
PKCS11Exception
XXX111
PKCS11ProviderException
XXX120
FileExchangeException
XXX121
IoException
XXX123
AccessException
XXX124
TypeException
XXX125
EntityException
XXX126
ConfigurationException
XXX127
ContentException
XXX128
AccessReadException
XXX129
AccessWriteException
XXX130
AccessExecuteException
XXX131
FileNotFoundException
XXX132
FileAlreadyExistsException
XXX133
TypeAlreadyExistsException
XXX135
MatrixPrinterException
XXX140
NotificationException
XXX998
InternalErrorException
XXX999
ConnectorNotAvailableException
XXX501
ConsentException
XXX500
AgentNotFoundException
XXX200
InvalidSessionException
XXX201
InvalidAtrException
XXX300
SecurityException
XXX996
ClientErrorException (invalid input body or request was send)
XXX997
SandboxRuntimeException (failure in the sanbox, API will implicitly restart the sandbox)
Consent error
815500
Agent not found
104000
Invalid digest error
104021
Error contacting or retrieving info from Distribution service
104020
Error initialising T1C
104030
Error contacting or getting info from the proxy
104028
Device keystore missing
104027
DS JWE error
104026
Unauthorised
104027
Forbidden
104024
JWT parsing error
104023
JSON parsing error
100890
Decryption exception, pin or puk or pace value could not be decrypted
106997
Invalid input body or request has been send to the API
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
209048
Puk blocked
209049
invalid puk
209062
Invalid puk 2 retries remain
209061
invalid puk 1 retry remain
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208074
invalid Pin 4 retries remain
208073
invalid Pin 3 retries remain
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208074
invalid Pin 4 retries remain
208073
invalid Pin 3 retries remain
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
209048
Puk blocked
209049
invalid puk
209064
Invalid puk 4 retries remain
209063
Invalid puk 3 retries remain
209062
Invalid puk 2 retries remain
209061
invalid puk 1 retry remain
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Card error
302040
Card error
402040
Card error
602040
Card error
206029
Parameter exception
208072
invalid Pin 2 retries remain
208071
invalid Pin 1 retry remain
206046
Pin blocked
206047
invalid pin
201051
Pin cancelled
2015050
Pin timeout
202010
Card not present
302010
Card not present
602010
Card not present
Execute rights missing
513124
Type error
513125
Entity error
513127
Content error / file not found
503140
Notification error, when a OS dialog returns an error
513131
File not found
513132
File already exists
Source '/Users/gilles/Desktop/fileextest/test.plist' does not exist
355
503140
No valid dir path returned, no valid file path returned, Timeout, No PIN entered
356
513124
No Type with name test was found in entity with name testEnt,
357
513124
type with name testType already exists
358
513131 or 513132
FIle not found or File already exists
359
not applicable
360
513125
Entity with name testEnt already exists
361
513125
No Entity with name testEnt was found
/
505126
No configuration found (file-exchange config file is missing/deleted…)
Error
Origin
1XXXXX
General
2XXXXX
Transaction service
3XXXXX
Certificate service
4XXXXX
Meta service
5XXXXX
File exchange
Error
Type
X01XXX
Reader
X02XXX
Card
X03XXX
Notification
X04XXX
Security
X05XXX
Configuration
Code
Exception type
10000
GeneralConnectorException
XXX000
InvalidDigestException
XXX001
ModuleNotSupportedException
XXX002
ModuleNotAvailableException
XXX003
ModuleNotImplementedException
Error code
Description
111003
Module not implemented
106029
Parameter error
105126
Configuration error
112031
Invalid T1C state error
104025
Forbidden exception
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
Error
Description
505126
Configuration error / none is found
504123
Access exception/ not enough access rights - General error
513121
I/O error
504128
Read rights missing
504129
Write rights missing
Old code
New code
example description
351
504128
/Library/Updates/ProductMetadata2.plist (Operation not permitted)
352
504129
/Library/Updates/ProductMetadata2.plist (Operation not permitted)
353
504130
/Library/Updates/ProductMetadata2.plist (Operation not permitted)
The Trust1Connector core services address communication functionality with local devices. The Trust1Connector core exposes 2 main interfaces:
Quick-Migration Guide (v2 -> v3)
Introduction
When you already have a V2 integrated this page will provide you with some easy steps to quickly migrate to the V3 of the Trust1Connector. Migration from the v2 to the v3 of the Trust1Connector can be done in 2 ways;
Integration of the API
Generic token
Sample code uses ES6 language features such as arrow functions and promises. For compatibility with IE11, code written with these features must be either transpiled using tools like Babel or refactored accordingly using callbacks.
Introduction
interface for web/native applications using JavaScrip/Typescript
REST API as a new approach and to incorporate the Trust1Connector as a microservice in the application architecture
In this guide, we target only the use of Trust1Connector's core interface for web/native applications.
The T1C-SDK-JS exposes protected resources for administration and consumer usage.
The JavaScript library must be initialized correctly in order to access the all resource.
Consumer resources
Consumer resources are typically used from an application perspective:
Get pub-key certificate
Get version
Get Information (operating system, runtime, user context, variable configuration)
List card-readers (with active card)
Get card-reader
List card-readers (with active cards)
List card-readers (with or without active card)
Trigger a push of the log files towards the DS
Executing these functionality is explained further.
Core Functionalities
The Trust1Connector functionalities are about secured communication with device hardware.
The document highlights communication with smart card readers - contact and contact-less. Other hardware devices can be enabled or integrated as well in the solution. Some of the already are, for example printer drivers, signature tablet drivers, ...
After you've initialized the Trust1Connector you can execute the rest of the Trust1Connector's functionality, for example listing the readers and fetching information from a specific smart card.
List card readers
Returns a list of available card readers. Multiple readers can be connected. Each reader is identified by a unique reader_id.
The response will contains a list of card readers:
When multiple readers are attached to a device, the response will show all connected card readers:
Important to notice:
The response adds a card-element when a card is inserted into the card reader.
The response contains card-reader pin-pad capabilities
Card Inserted
As mentioned in the List card-readers, when a smart-card is inserted/detected, the reader will contain the cart-type based on the ATR. The ATR (Anwser To Reset), is the response from any smart-card when powered, and defines the card type.
The Trust1Connector recognized more than 3k smart-card types.
Pin-Pad Capabilities
As mentioned in the List card-readers, when a card-reader has pin-pad capabilities, this will be mentioned in the response (notice the pinpadproperty):
List Card-Readers - Explained Example
The following example is the response for List card-readers on a device with 4 different card-readers attached:
In the above example you notice that 4 card-readers are connected. Each card-reader receives his temporary id which can be used for other functions where a card-reader id is needed.
This method can be requested in order to list all available card-readers, and optional cards-inserted.
Each card-reader has a vendor provided name, which is retrieved from the card-reader itself.
An additional property pinpad, a boolean value, denotes if the card-reader has pin-pad capabilities. A pin-pad is a card-reader, most of the times with its own display and key-pad.
From a security perspective, it's considered best practice to use as much as possible pin-pad capabilities of a pin-pad card-reader.
When a reader has a smart-card inserted (contact interface) or detected (contactless interface), the card type will be resolved by the GCL in order to respond with a meaningful type.
In the above examples you see that; one card-reader has a Belgian eID card; another card-reader has a MisterCash or VISA Card available for interaction.
The readers returned, are the card-readers with a card available. The card-readers where no card is presented, are ignored.
Get card reader with card inserted
Returns a list of available card readers with a smart card inserted. Multiple readers can be connected with multiple smart cards inserted. Each reader is identified by a unique reader_id and contains information about a connected smart card. A smart card is of a certain type. The Trust1Connector detects the type of the smart card and returns this information in the JSON response.
Response:
Get the Javascript SDK version
To retrieve the version of the Javascript SDK you can use the version function available in the CoreService
You can follow the example below to retrieve the version number
The ouput in the log of the code above should look like the following
Get device public key
via the getDevicePublicKey endpoint you're able to fetch the public key information of the device. This requires an authenticated client to be able to access this endpoint.
This endpoint is used in the library to encrypt pin, puk and pace information so that it is not exposed in the network logs of the browser.
Encryption of pin, puk and pace is only possible when the Trust1Connector is registered via a DS and has a valid device key-pair. The SDK will automatically switch to send the pin, puk or pace info in clear text if its not able to encrypt. The Trust1Connector API will also detect if it has no valid device key-pair it will not try to decrypt the incoming pin, puk or pace information.
Push log files
Via the pushLogs function you can trigger the Trust1Connector to send out the log files towards the Distribution service.