Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
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}}
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.
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.
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.
public static generateConsentToken(): stringThis will return the randomly generated value as a string value immediatley.
To call this;
# regular imported javascript via script tag
T1CSdk.T1CClient.generateConsentToken()# Import loaded via NPM
import {T1CClient} from "t1c-sdk-js";
T1CClient.generateConsentToken()If you decide not to use this function, the value needs to be prefixed with `::t1c::miksa::
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:
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
console.log("Client config: ", client.localConfig)
core = client.core();
}, err => {
if (err.code == 814501) {
console.log(err)
client = err.client
$('#consentModal').modal('show', {
keyboard: false
});
$('.consent-token').text(makeid(20));
} else if(err.code == 815500) {
// Agent not registered --> contact support
} else if (err.code == 112999) {
// Unavailable
} else {
console.error("T1C error:", err)
}
}); The code below is an example of a javascript event handler on a consent button.
$('#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)
})
});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.
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
Integration via the deprecated Javascript SDK
Both are viable integrations. When integrating via the API you have more control over the functionality and the dependencies used.
For updating your web application first of all you need to use the new Javascript SDK. After this there are some differences in using the SDK from the v2.
The configuration from the v2 has changed, we simplified this.
The v2 had the following configuration options;
export class GCLConfigOptions {
constructor(public gclUrl?: string,
public gwOrProxyUrl?: string,
public apiKey?: string,
public gwJwt?: string,
public tokenExchangeContextPath?: string,
public ocvContextPath?: string,
public dsContextPath?: string,
public dsFileContextPath?: string,
public pkcs11Config?: Pkcs11ModuleConfig,
public agentPort?: number,
public implicitDownload?: boolean,
public forceHardwarePinpad?: boolean,
public sessionTimeout?: number,
public consentDuration?: number,
public consentTimeout?: number,
public syncManaged?: boolean,
public osPinDialog?: boolean,
public containerDownloadTimeout?: number,
public localTestMode?: boolean,
public lang?: string,
public providedContainers?: T1CContainerid[]) {
}
}With the v3 this is significantly simplified to the following;
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"
) {}
}Some of the config options of the v3 are still in review and can be removed up until the final release of the v3, in the table below you will find more information
V2 config option
V3 config option
Description
gclUrl / gwOrProxyUrl
t1cApiUrl
in the V2 this was https://localhost:10443 while in the V3 this will be https://t1c.t1t.io (for T1T)
t1cApiPort
is the port where the webserver is listening on, in the v2 this is 10443 but in the v3 by default(T1T) this is 51983
t1cProxyPort
This value represents the port where the Proxy webserver is listening on. By default this is 51983 (obsolete)
t1cProxyUrl
Similar to the api url this is the URL where the proxy used in shared environment is running on. This is by default the same as the API url (obsolete)
applicationDomain
Host of the web application the Trust1Connector is being used on. This property is used to make sure no collisions can happen
apiKey
/
gwJwt
jwt
JWT token used for authentication of the web application towards the Trust1Connector. This must be retrieved from the web applications backend
tokenExchangeContextPath
/
ocvContextPath
/
dsContextPath
/
in v2 this was the context path for the DS based on the gwOrProxyUrl
dsFileContextPath
/
pkcs11Config
/
agentPort
/
implicitDownload
/
forceHardwarePinpad
/
sessionTimeout
/
consentDuration
/
syncManaged
/
osPinDialog
/
boolean which depicts the default os pin dialog value
containerDownloadTimeout
/
localTestMode
/
lang
/
providedContainers
/
After you've created your configuration object you can do the initialisation of the Trust1Connector SDK. This has largely remained the same except for the error codes.
V2 example:
config = new GCLLib.GCLConfig(configoptions);
GCLLib.GCLClient.initialize(config).then(res => {
client = res;
core = client.core();
console.log("GCLClient: ", res)
}, err => {
console.log("GCL error:", err)
})V3 example;
config = new T1CSdk.T1CConfig(configoptions);
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
console.log("Client config: ", client.localConfig)
core = client.core();
}, err => {
errorHandler(err);
});For more information regarding initialization we suggest the Initialize page
As an integrator I want to retrieve a consent value from the Javascript SDK
As a Integrator I would like to use a central registry hosted on the DS
Trust1Connector JavaScript SDK removes the consent when the validate returns a response where an extra consent is required.
Trust1Connector should be able to provide organization context when not requiring application tokens
Support Citrix multi-host session management for consent flow
Issue with pinEncryption when version is not found, stops the flow
JS SDK for T1C v3.5 attempts to reset bulk PIN by POST request instead of GET
File exchange relative path for download does not handle all cases
Download does not correctly build the relative path
As an Integrator I want to provide a timeout for the dialogs
Migrate to Rust Jcop
Safenet rustification
eHerkenning rustification
Implement new architecture for shared environment, multi session host, single installation, ...
Remote registry implementation
File exchange relative path for download does not handle all cases
As an Integrator I want to provide a timeout for the dialogs
Download does not correctly build the relative path
Javascript semver check doesn't handle beta and RC versions
Migrate to Rust Jcop
Safenet rustification
eHerkenning rustification
Implement new architecture for shared environment, multi session host, single installation, ...
Check correct versions for backwards compatibility
Pin Obfuscation not working for all modules
base64 encode the PIN before sending it to the API
Pin Obfuscation not working for all modules
base64 encode the PIN before sending it to the API
I want to enable module for Certinomis
Migrate certigna integration with the latest token
Return interface to previous state to prevent breaking applications
Pkcs11 module and os dialog return decryption error
Update certificate model to correctly handle multiple certificates
Device-key endpoint gets called in error handler instead of successhandler
File-exchange ArrayBuffer should be Blob
Initialising with invalid JWT does not throw an error
Entity and type response object inconsistency
Remoteloading split TX, RX and SW value based on APDU response
Use Device certificate to encrypt the pin value sent in clear text
I want to enable the module for eHerkenning
I want to enable module for Print Writer
Aventra, Idemia, Oberthur callback functions not being triggered
FileExchange typing inconsistency
Add LuxeID to the token generic interface in JS SDK
Fix imports for Pkijs
Disbable implicit any typing
Fix for bulk sign reset in JS SDK causes the reader ID not to be included in certificate retrieval
Provide separate implementation for Belgian eID with Crelan reader
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.
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
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.
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
Management of an in-memory list of active Agents
Management of user consents in a shared environment by means of browser cookies with an optional configurable TTL (time to live)
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.
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 consent flow.
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).
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.
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:
You can find the trust1connector JS SDK for the Trust1Connector v3 via NPM
You can also find the source code here
Include the 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
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.
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.
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 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.
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.
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
Trust1Connector installer is about 15-20Mb in size. The installed size comes to 35-45Mb.
This includes the Trust1Connector API, Registry and Sandbox.
Trust1Connector installer is about 15-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.
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.
Right now Trust1Connector support two operating systems;
MacOS 10.13 or higher
X86 architecture
M1/ARM architecture
Windows 8.1 or higher
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.
To run in user-space on Windows 8.1 or higher some components have to be set on the operating system
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
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKEY_CURRENT_USER\SOFTWARE\Trust1Team\Trust1Connector
Since 3.5.x no more cookies are used.
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
IE 11 (End of Life is June 15 2022)
All other browsers. As recent as possible
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.
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 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
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 104026 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.
For initialisation of the T1C you need to prepare your application first by and importing them in such a way that you can call for the Javascript functions when you need them. When you've succesfully and installed the Trust1Connector you can initialize and use the Trust1Connector
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.
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.
t1cApiUrl: string
Optional
The 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: string
Optional
The port defined to be used for the Trust1Connector. By default this is 51983
t1cProxyUrl: string
Optional - Deprecated
The 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: string
Optional - Deprecated
The port defined to be used for the Trust1Connector Proxy. By default this is 51983
jwt: string
Optional
The 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: string
Optional
The 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
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 .
Initialization of the Trust1Connector in many cases requires a user consent, the exception being when no registry is configured (either local or central). 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). 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
When either no consent is present or its invalid you will receive a invalid client 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: string
The string value that is saved to the user's clipboard needs to be sent to the Consent function.
durationInDays: number
Optional
Amount of days that the consent is valid.
callback: (error?: T1CLibException, data?: T1CClient)
Optional
Callback 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.
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
GET https://ds.t1t.io/v3/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
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.
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 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.
The following list are codes that you can expect.
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
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.
The Belgian eID container facilitates communication with card readers with inserted Belgian eID smart card. The T1C-JS client library provides function to communicate with the smart card and facilitates integration into a web or native application. This document describes the functionality provided by the Belgian eID container on the T1C
All model information can be found in the
Initialise a Trust1Connector client:
Get the Belgian eID container service:
Call a function for the Belgian eID container:
The constructor for the Belgian eID expect as the parameter to be a valid reader-ID. A reader-ID can be obtained from the exposed core functionality, for more information see Core services responds with available card-readers, available card in a card-reader, etc. For example: In order to get all connected card-readers, with available cards:
This function call returns:
We notice that a card object is available in the response in the context of a detected reader.
The reader in the example above is Bit4id miniLector, has no pin-pad capabilities, and there is a card detected with given ATR and description "Belgian eID Card".
An ATR (Answer To Reset) identifies the type of a smart-card.
The reader, has a unique ID, reader_id; this reader_id must be used in order to request functionalities for the Belgian eID card.
This must be done upon instantiation of the Belgian eID container:
All methods for beid will use the selected reader - identified by the reader_id.
The card holder is the person identified using the Belgian eID card. It's important to note that all data must be validated in your backend. Data validation can be done using the appropriate certificate (public key).
Contains all card holder related data, excluding the card holder address and photo. The service can be called:
An example callback:
Response:
Contains the card holder's address. The service can be called:
Response:
Contains the card holder's picture stored on the smart card. The service can be called:
Response:
The token info contains generic information about the card and it's capabilities. This information includes the serial number, file types for object directory files, algorithms implemented on the card, etc.
Response
Exposes all the certificates publicly available on the smart card.
Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'citizen CA certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not. The service can be called:
Response:
Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
Response:
Contains the citizen certificate stored on the smart card. The 'citizen certificate' is used to sign the 'authentication certificate' and the 'non-repudiation certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
Response:
Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
Response:
Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
Response:
All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:
Response:
The filter can be used to ask a list of custom data containers. For example, we want to read only the biometric data
Response:
All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:
Response:
The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate
Response:
As the Beid module incorperates Beid 1.7 and 1.8 there is a difference in the algorithms being used. In 1.7 we have the following;
md5
sha1
sha256
sha512
For beid 1.8 we have;
sha2_256
sha2_384
sha2_512
sha3_256
sha3_384
sha3_512
As we've noticed most integrators use sha256 and to make sure current integrations do not break we have made the Trust1Connector to map sha256 to sha3_256 for beid 1.8. Ofcourse if you want to use a specifc supported algorithm you can still select them.
By default the 1.7 will fall back to sha256 and 1.8 to sha3_256 if an incompatible algorithm is passed to the function.
The tables below explain which algorithm will be used when providing a certain algorithm value in the function;
Data can be signed using the Belgian eID smart card. To do so, the T1C facilitates in:
Retrieving the certificate chain (citizen-certificate, root-certificate and non-repudiation certificate)
Perform a sign operation (private key stays on the smart card)
Return the signed hash
To get the certificates necessary for signature validation in your back-end:
Response:
Depending on the connected smart card reader. A sign can be executed in 2 modes:
Using a connected card reader with 'pin-pad' capabilities (keypad and display available)
Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)
Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.
When signing with a crelan card reader, it is additionally possible to optionally specify a transaction ID and the language. If the card reader is not a Crelan reader, these values will be ignored. This applies to all signing methods described below.
Crelan card readers only support nl, fr, and de as languages
When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:
Response is a base64 encoded signed hash:
The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.
When the pin entry is done on the pin-pad, the following request is used to sign a given hash:
Response is a base64 encoded signed hash:
The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.
The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.
It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
The PIN set for bulk signing can be reset by calling this method.
Response will look like:
In order to calculate a hash from the data to sign, you need to know the algorithm you will use in order to sign.
You can use the following online tool to calculate the SHA256:
Hexadecimal result:
Notice that the length of the SHA256 is always the same. Now we need to convert the hexadecimal string to a base64-encoded string, another online tool can be used for this example:
Base64-encoded result:
Now we can sign the data:
Result:
Note: If you want to convert a binary signed hash to HEX (for development) you can use for example an online hexdump tool:
When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:
Response:
When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:
Response:
In order to inform a user upon the PIN retries left, the Belgian eID doesn't provide a request to retrieve this information. After an unsuccessful PIN verification, the error code indicates the number of retries left. For example, when executing:
Note that, when the user has at least one retry left, entering a correct PIN resets the PIN retry status.
For more information about the error codes you can check the
As the Beid module incorperates Beid 1.7 and 1.8 there is a difference in the algorithms being used. In 1.7 we have the following;
md5
sha1
sha256
sha512
For beid 1.8 we have;
sha2_256
sha2_384
sha2_512
sha3_256
sha3_384
sha3_512
As we've noticed most integrators use sha256 and to make sure current integrations do not break we have made the Trust1Connector to map sha256 to sha3_256 for beid 1.8. Ofcourse if you want to use a specifc supported algorithm you can still select them.
By default the 1.7 will fall back to sha256 and 1.8 to sha3_256 if an incompatible algorithm is passed to the function.
The tables below explain which algorithm will be used when providing a certain algorithm value in the function;
The T1C is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.
External Challenge
An external challenge is provided in the data property of the following example:
Response:
Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities. The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.
Generated Challenge
A server generated challenge can be provided to the JavaScript library. In order to do so, an additional contract must be provided with the 'OCV API' (Open Certificate Validation API).
Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate
The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)
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.
The ID-One Cosmo V7-n is part of the Oberthur family of cryptographic modules called ID-One Cosmo V7. Modules within
this family share the same functionalities and the description of the ID-One Cosmo V7 applies to all versions including the “-n” subject to this validation.
This document describes the functionality provided by the Oberthur ID-One smartcard - which is a PKI container:
ID-One Cosmo V7-n; FIPS 140-2 Security Policy
All model information can be found in the
When initialisation is finished you can continue using the aventra object to execute the functions below.
The expected response for this call should be;
The expected response for this call should be;
Exposes all the certificates publicly available on the smart card. The following certificates can be found on the card:
Root certificate
Signing certificate
Authentication certificate
Issuer certificate
Encryption certificate
When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.
The expected response for this call should be;
This will return information of the Aventra card.
The expected response for this call should be;
When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.
Contains the 'root certificate' stored on the smart card. The service can be called:
Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and singing. The service can be called:
Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. The service can be called:
The expected response for these calls should be in the following format;
The expected response for these calls should be in the following format;
Data can be signed using the smartcard. To do so, the SDK facilitates in:
Retrieving the certificate chain (root, intermediate and non-repudiation certificate)
Perform a sign operation (private key stays on the smart card)
Return the signed has
To sign data, an algorithm must be specified in the algorithm property (see ), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.
Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
The expected response for this call should be;
The PIN set for bulk signing can be reset by calling this method.
Response will look like:
The SDK is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card
An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.
The expected response for this call should be;
The expected response for this call should be;
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.
The ID-One Cosmo V8-n is part of the Idemia IAS ECC family of cryptographic modules called ID-One Cosmo V8. Modules within this family share the same functionalities and the description of the ID-One Cosmo V8 applies to all versions including the “-n” subject to this validation. This document describes the functionality provided by the Idemia IAS ECC ID-One smartcard - which is a PKI container - on the T1C-GCL (Generic Connector Library) implemented version:
ID-One Cosmo V8-n; FIPS 140-2 Security Policy
All model information can be found in the
When initialisation is finished you can continue using the aventra object to execute the functions below.
The expected response for this call should be;
The expected response for this call should be;
When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.
The expected response for this call should be;
This will return information of the Aventra card.
The expected response for this call should be;
When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not.
Contains the 'root certificate' stored on the smart card. The service can be called:
Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation, authentication and singing. The service can be called:
Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. The service can be called:
The expected response for these calls should be in the following format;
The expected response for these calls should be in the following format;
Data can be signed using the smartcard. To do so, the SDK facilitates in:
Retrieving the certificate chain (root, intermediate and non-repudiation certificate)
Perform a sign operation (private key stays on the smart card)
Return the signed hash
To sign data, an algorithm must be specified in the algorithm property (see ), and a Base64-encoded string representation of the digest bytes of the same algorithm in the data property.
Additionally, it is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
The expected response for this call should be;
The PIN set for bulk signing can be reset by calling this method.
Response will look like:
The SDK is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process
The expected response for this call should be;
The expected response for this call should be;
// 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'{
"success": true,
"data": "eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0.eyJpc3MiOiJ0MWNkcy1hcHAiLCJzdWIiOiJkZXZlbG9wbWVudCIsImV4cCI6MTU5OTA1MTExMywiaWF0IjoxNTk5MDQ5OTEzLCJuYmYiOjE1OTkwNDk5MDh9.LE_AdYv9PWxqSRm6-lkV_3TxInCqbf_hTwHFKCFfYwkuzex6AMkeW6FaVCOxu-EBU158S2g70i4VBpeT2TAr0IoOyjK-nalvVG5aB9MwidZMtiPlidcUfsDhsyhbhwqlhI2dzB5J5KsBmvZwpoG-Pg2koUSidruixg3SxRrCMotBRlRNKItnYgfs6_wvd_OOLXs2OlufYOD876MWcJymBK48wf9ESQ50clR3zwPAQsNnXFq2Augk0gOlCgWO1--WgaFeMnBF28b7genZXIkwZCfT82nRYtiOs0zLK2WtyireTHDgjIZif4nX8pggE7t_63Hbv8wCvv8_Mg2PfdhCMQ"
}const configoptions = new T1CSdk.T1CConfigOptions(
environment.t1cApiUrl,
environment.t1cApiPort,
environment.t1cProxyUrl,
environment.t1cProxyPort,
environment.jwt
);
config = new T1CSdk.T1CConfig(configoptions);
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
console.log("Client config: ", client.localConfig)
core = client.core();
}, err => {});updateJWT(jwt: string, callback?: (error: T1CLibException, data?: T1CClient) => void): Promise<T1CClient>core.updateJWT("jwt").then(client => {}, error => {});Environment
DS url
Acceptance
https://acc-ds.t1t.io
Production
https://ds.t1t.io
{
description: "some error description",
code: "some error code"
}
Error
Origin
1XXXXX
General
2XXXXX
Transaction service
3XXXXX
Certificate service
4XXXXX
Meta service
5XXXXX
File exchange
6XXXXX
Identity service
7XXXXX
Reader service
8XXXXX
Proxy
Error
Type
X01XXX
Reader
X02XXX
Card
X03XXX
Notification
X04XXX
Security
X05XXX
Configuration
X06XXX
Input
X07XXX
Session
X08XXX
PIN
X09XXX
PUK
X10XXX
Pace
X11XXX
Module
X12XXX
System
X13XXX
I/O
X14XXX
Consent
X15XXX
Agent
Code
Exception type
10000
GeneralConnectorException
XXX000
InvalidDigestException
XXX001
ModuleNotSupportedException
XXX002
ModuleNotAvailableException
XXX003
ModuleNotImplementedException
XXX004
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
XXX996
ClientErrorException (invalid input body or request was send)
XXX997
SandboxRuntimeException (failure in the sanbox, API will implicitly restart the sandbox)
Error code
Description
111003
Module not implemented
106029
Parameter error
105126
Configuration error
112031
Invalid T1C state error
104025
Forbidden exception
814501
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error code
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
Error
Description
312998
Module not implemented
611004
Parameter error
411004
Invalid T1C state error
212998
Forbidden exception
211004
Function not supported
202040
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
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
504130
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
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)
354
513121
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…)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script defer src="./T1CSdk.js"></script>
</head>
<body>
...
</body>
</html><script defer src="./T1CSdk.js"></script>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"
) {}
}// ...
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);
// ...// When remote DS is used set the following parameter
config.dsUrl = "https://acc-ds.t1t.io";// ...
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) {
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)
}
});
// ...public getImplicitConsent(codeWord: string, durationInDays?: number,
callback?: (error?: T1CLibException, data?: T1CClient) => void
): Promise<T1CClient>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)
})
}
})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;apikey
string
API-key received from Trust1Team
{
"success": true,
"data": "eyJraWQiOiJ0MWNkcyIsImFsZyI6IlJTMjU2In0...v8_Mg2PfdhCMQ"
}{
"message": "No API key found in request"
}{
"success": false,
"description": "Invalid API key",
"code": 1005,
}export interface AbstractEidBE {
allData(filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
biometric(callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
address(callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
picture(callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
intermediateCertificates(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
}, err => {
console.error(error)
});var beid = client.beid(reader_id);function callback(err,data) {
if(err){console.log("Error:",JSON.stringify(err, null, ' '));}
else {console.log(JSON.stringify(data, null, ' '));}
}
beid.biometric(callback);var core = client.core();
core.readersCardAvailable(callback);{
"data": [
{
"card": {
"atr": "3B9813400AA503010101AD1311",
"description": ["Belgian eID Card"]
},
"id": "57a3e2e71c48cee9",
"name": "Bit4id miniLector",
"pinpad": false
}
],
"success": true
}var beid = client.beid(reader_id);client.beid(reader_id).biometric(callback);function callback(err,data) {
if(err){
console.log("Error:",JSON.stringify(err, null, ' '));
}
else {
console.log(JSON.stringify(data, null, ' '));
}
}{
"birthDate": "15 JUL 1993",
"birthLocation": "Roeselare",
"cardDeliveryMunicipality": "Avelgem",
"cardNumber": "592..8233",
"cardValidityDateBegin": "27.05.2015",
"cardValidityDateEnd": "27.05.2025",
"chipNumber": "U0xHk...EstwAjEpJQQg==",
"documentType": "01",
"firstNames": "Gilles Frans",
"name": "Platteeuw",
"nationalNumber": "930...154",
"nationality": "Belg",
"nobleCondition": "",
"pictureHash": "Fqva9YCp...JKyn8=",
"rawData": "AQw1OTIxMjQwNTgy...TARFBar2vWAqTW+axEIuyskBgFySsp/",
"sex": "M",
"signature": "hKys9WMjUm4ipg...14xUCg/98Y9/gP/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
"specialStatus": "0",
"thirdName": "J",
"version": "0"
}client.beid(reader_id).address(callback);{
"municipality": "Hoeselt",
"rawData": "ARJLZXJrc...AAAAAA==",
"signature": "mhPyeRg25H...w==",
"streetAndNumber": "Kerkstraat X",
"version": "0",
"zipcode": "3730"
}client.beid(reader_id).picture(callback);{
"data": "/9j/4AAQSkZJRgABA...59aVpcklSDzyKUTEDGK//9k=",
"success": true
}{
"data": {
"eid_compliant":48,
"electrical_perso_interface_version":0,
"electrical_perso_version":3,
"graphical_perso_version":7,
"label":"BELPIC",
"prn_generation":4,
"raw_data":"MCcCAQAEEFNMSU4z...JFTFBJQwMCBDCeBAcDAAA=",
"serial_number":"534C494E..1231C",
"version":0,
"version_rfu":0
},
"success": true
}client.beid(reader_id).rootCertificate(parseCertsBoolean, callback);{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}client.beid(reader_id).authenticationCertificate(parseCertsBoolean, callback);{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}client.beid(reader_id).intermediateCertificates(parseCertsBoolean, callback);{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}client.beid(reader_id).nonRepudiationCertificate(parseCertsBoolean, callback);{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}client.beid(reader_id).encryptionCertificate(parseCertsBoolean, callback);{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}var filter = [];
client.beid(reader_id).allData({ filters: filter}, callback);{
"picture": {
"picture": "/9j/4AAQSkZJRgABAgEBLAEsAAD/...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"
},
"biometric": {
"birthDate": "15 JUL 1993",
"birthLocation": "Roeselare",
"cardDeliveryMunicipality": "Avelgem",
"cardNumber": "592124058233",
"cardValidityDateBegin": "27.05.2015",
"cardValidityDateEnd": "27.05.2025",
"chipNumber": "...==",
"documentType": "01",
"firstNames": "Gilles Frans",
"name": "Platteeuw",
"nationalNumber": "...",
"nationality": "Belg",
"nobleCondition": "",
"pictureHash": "...=",
"rawData": "...+axEIuyskBgFySsp/",
"sex": "M",
"signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
"specialStatus": "0",
"thirdName": "J",
"version": "0"
},
"address": {
"municipality": "Hoeselt",
"rawData": "...==",
"signature": "...+Evety1PnTE4pqXaHgBxIpk+P8kRL5W3zDV+../../..+YoHBC9KqTmSpl5KULxdnKiyCt+2RyJdzE2wyoymjRmysIhJy1wW9PRnx99S1TFqQLuc0tyBmkBPR4aFqmOq4a7zqd0q2Q1g+BbnwJ4d3oa10ia5+0kBXf0THoXv3HYIHlnwhBMfAtWzPnFrYBuAKTwyl7yBF5IFfXFpGWuVZUTJElgNcmNvsHMnAhVwDw==",
"streetAndNumber": "Kerkstraat X",
"version": "0",
"zipcode": "3730"
}
}var filter = ['biometric'];
client.beid().allData({ filters: filter }, callback);{
"biometric": {
"birthDate": "15 JUL 1993",
"birthLocation": "Roeselare",
"cardDeliveryMunicipality": "Avelgem",
"cardNumber": "592124058233",
"cardValidityDateBegin": "27.05.2015",
"cardValidityDateEnd": "27.05.2025",
"chipNumber": "...==",
"documentType": "01",
"firstNames": "Gilles Frans",
"name": "Platteeuw",
"nationalNumber": "...",
"nationality": "Belg",
"nobleCondition": "",
"pictureHash": "...=",
"rawData": "...+axEIuyskBgFySsp/",
"sex": "M",
"signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
"specialStatus": "0",
"thirdName": "J",
"version": "0"
}
}var filter = [];
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);{
"rootCertificate": {
...
},
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
},
"intermediateCertificates": {
...
},
"encryptionCertificate": {
...
}
}var filter = ['rootCertificate'];
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);{
"rootCertificate": {
...
}
}Provided algorithm value
Selected algorithm by T1C
md5
md5
sha1
sha1
sha256
sha256
sha512
sha512
any other value
sha256
Provided algorithm value
Selected algorithm by T1C
sha2_256
sha2_256
sha2_384
sha2_384
sha2_512
sha2_512
sha3_256
sha3_256
sha3_384
sha3_384
sha3_512
sha3_512
sha256
sha3_256
sha384
sha3_384
sha512
sha3_512
any other value
sha3_256
var filter = null;
client.beid(reader_id).allCerts(parseCerts, { filters: filter}, callback);{
"rootCertificate": {
...
},
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
},
"intermediateCertificates": {
...
},
"encryptionCertificate": {
...
}
}var data = {
"pin":"...",
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": true,
"txId": "1234",
"language": "fr"
}
client.beid(reader_id).sign(data, callback);var data = {
"pin":"...",
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": true
}
client.beid(reader_id).sign(data, callback);{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}var data = {
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": false
}
client.beid(reader_id).sign(data, callback);{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
pin: "1234"
}
const bulk = true;
beid.sign(data, bulk).then(res => {
}, err => {
console.error(err)
})beid.resetBulkPin().then(res => {
}, err => {
console.error(err)
}){
"success": true,
"data": true
}This is sample text to demonstrate siging with Belgian eID135b870026cfbe12dec348069811fcde5bed28800ac54dbf45ecdf04eb13e95bE1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=var data = {
"pin":"...",
"algorithm":"sha256",
"data":"E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
}
client.beid(reader_id).signData(data, callback);{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}var data = {
"pin":"..."
}
client.beid(reader_id).verifyPin(data, callback);{
"verified": true
}var data = {}
client.beid(reader_id).verifyPin(data, callback);{
"verified": true
} $("#buttonValidate").on('click', function () {
var _body={};
_body.pin = $("#psw").val(); //only when no pin-pad available
var beid = client.beid(reader_id);
beid.verifyPin(_body, validationCallback);
});Provided algorithm value
Selected algorithm by T1C
md5
md5
sha1
sha1
sha256
sha256
sha512
sha512
any other value
sha256
Provided algorithm value
Selected algorithm by T1C
sha2_256
sha2_256
sha2_384
sha2_384
sha2_512
sha2_512
sha3_256
sha3_256
sha3_384
sha3_384
sha3_512
sha3_512
sha256
sha3_256
sha384
sha3_384
sha512
sha3_512
any other value
sha3_256
var data = {
"pin": "...",
"algorithm": "sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
client.beid(reader_id).authenticate(data, callback);{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The calculated digest of the hash is prefixed with:
DigestInfo ::= SEQUENCE {
digestAlgorithm AlgorithmIdentifier,
digest OCTET STRING
}
Make sure this has been taken into consideration in order to validate the signature in a backend process.generic.allAlgoRefs(module, callback);{
"success": true,
"data": ["sha1", "sha256"]
}export interface AbstractOberthur73 {
allCertFilters(): string[];
allKeyRefs(): string[];
allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
issuerCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>
verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}T1cSdk.initialize(config).then(res => {
const oberthur = res.client.oberthur(readerId);
}, err => {
console.error(error)
});oberthur.allCertFilters().then(res => {
}, err => {
console.error(err)
}){
success: true,
data: ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate', 'nonRepudiationCertificate', 'issuerCertificate']
}oberthur.allKeyRefs().then(res => {
}, err => {
console.error(err)
}){
success: true,
data: ['authenticate', 'sign', 'encrypt']
}const filter = ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate'];
oberthur.allCerts(filter).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
authenticationCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},
citizenCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},
nonRepudiationCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},,
rootCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},,
encryptionCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},
}
}oberthur.tokenData().then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
version?: string,
serialNumber?: string,
label?: string,
changeCounter?: number,
}
}oberthur.rootCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})oberthur.authenticationCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})oberthur.nonRepudiationCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})oberthur.issuerCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})aventra.encryptionCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}const data = {
pin: "1234", // optional
osDialog: true // optional
}
oberthur.verifyPin(data).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
"verfied": true
}
}const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
id: "123"
}
const bulk = false;
oberthur.sign(data, bulk).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
data: string
}
}diplad.resetBulkPin().then(res => {
}, err => {
console.error(err)
}){
"success": true,
"data": true
}const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs="
id: "123"
}
oberthur.authenticate(data).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
data: string
}
}oberthur.allAlgoRefs(data).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
ref: ['sha256', 'md5']
}
}export interface AbstractIdemia {
allCertFilters(): string[];
allKeyRefs(): string[];
allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
issuerCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>
verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}T1cSdk.initialize(config).then(res => {
const idemia = res.client.idemia(readerId);
}, err => {
console.error(error)
});idemia.allCertFilters().then(res => {
}, err => {
console.error(err)
}){
success: true,
data: ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate', 'nonRepudiationCertificate', 'issuerCertificate']
}idemia.allKeyRefs().then(res => {
}, err => {
console.error(err)
}){
success: true,
data: ['authenticate', 'sign', 'encrypt']
}const filter = ['rootCertificate', 'authenticationCertificate', 'encryptionCertificate'];
idemia.allCerts(filter).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
authenticationCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},
citizenCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},
nonRepudiationCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},,
rootCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},,
encryptionCertificate?: {
certificate?: TokenCertificateObject,
certificates?: Array<TokenCertificateObject>
},
}
}idemia.tokenData().then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
version?: string,
serialNumber?: string,
label?: string,
changeCounter?: number,
}
}idemia.rootCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})idemia.authenticationCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})idemia.nonRepudiationCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})idemia.issuerCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
})aventra.encryptionCertificate(parseCertsBoolean).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}const data = {
pin: "1234", // optional
osDialog: true // optional
}
idemia.verifyPin(data).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
"verfied": true
}
}const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
id: "123"
}
const bulk = false;
idemia.sign(data, bulk).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
data: string
}
}idemia.resetBulkPin().then(res => {
}, err => {
console.error(err)
}){
"success": true,
"data": true
}const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
id: "123"
}
idemia.authenticate(data).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
data: string
}
}idemia.allAlgoRefs(data).then(res => {
}, err => {
console.error(err)
}){
success: true,
data: {
ref: ['sha256', 'md5']
}
}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
The Chambersign token is a token that requires for the middleware of Chambersign to be installed prior to using it on the Trust1Connector.
The chambersign software for windows requires administration rights to be installed. After installation the location will be:
x64 & x86 ; C:\Program Files\ChamberSign
To check if this has been installed we can use the File-exchange create type function and then check the contents of the (sub)-folders.
To check if the middleware is installed the sample code below is a good start to use the File-Exchange to check if the middleware has been installed and its safe to continue to use the ChamberSign middleware and the Trust1Connector.
const entity = "chambersign";
const type = "middleware";
const initPath = "C:\\Program Files\\ChamberSign"
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
core = client.core();
let fileex = client.fileex();
const middlewareInstalled = await isMiddlewareInstalled(fileex);
if (middlewareInstalled) {
// Middleware is installed you can use the chambersign token with the T1C
} else {
// Middleware not installed please install before using it with the T1C
}
}, err => {
errrorHandler(err);
});
async function isMiddlewareInstalled(fileexClient) {
fileexClient.existsType(entity, type).then(existsRes => {
if (existsRes.data) {
// Type exists
return checkFilesPresent(fileexClient);
} else {
// Type does not exist
fileexClient.createType(entity, type, initPath).then(createRes => {
return checkFilesPresent(fileexClient);
}, err => {
errrorHandler(err);
})
}
}, err => {
// Type exists error, try to create and then check if middleware is installed
fileexClient.createType(entity, type, initPath).then(createRes => {
return checkFilesPresent(fileexClient);
}, err => {
errrorHandler(err);
})
});
}
async function checkFilesPresent(fileexClient) {
await fileexClient.existsFile(entity, type, "HashLogic\\bin\\idoPKCS.dll").then(existsFileRes => {
return existsFileRes;
}, err => {
return false;
})
}export interface AbstractEidGeneric {
// getModuleDescription(module: string, callback?: (error: T1CLibException, data: DataObjectResponse) => void): Promise<DataObjectResponse>;
// allData(module: string, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
allCerts(module: string, parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
// biometric(module: string, callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
// tokenData(module: string, callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
// address(module: string, callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
// picture(module: string, callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
// rootCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
// intermediateCertificates(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
authenticationCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
// encryptionCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
verifyPin(module: string, body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(module: string, body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(module: string, body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(module: string, callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(module: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}All model information can be found in the Token typings model page
Initialise a Trust1Connector client with a valid configuration:
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
}, err => {
console.error(error)
});In order to get all connected card-readers, with available cards:
var core = client.core();
core.readersCardAvailable(callback);This function call returns:
{
"data": [
// List of reader with cards found
],
"success": true
}Using the generic interface can be done as follows;
const module = "chambersign";
var generic = client.generic(selected_reader.id);Because we're using the generic interface we can define the module variable upfront since we know we want to use the chambersign integration.
Exposes all the certificates publicly available on the smart card.
Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
generic.authenticationCertificate(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:
var filter = [];
generic.allCerts(module, parseCerts, { filters: filter}, callback);Response:
{
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
}
}The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate
var filter = ['authenticationCertificate'];
generic.allCerts(module, { filters: filter}, callback);Response:
{
"authenticationCertificate": {
...
}
}To get the certificates necessary for signature validation in your back-end:
var filter = null;
generic.allCerts(module, { filters: filter}, callback);Response:
{
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
}
}Depending on the connected smart card reader. A sign can be executed in 2 modes:
Using a connected card reader with 'pin-pad' capabilities (keypad and display available)
Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)
Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.
When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:
var data = {
"pin":"...",
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": true
}
generic.sign(module, data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.
When the pin entry is done on the pin-pad, the following request is used to sign a given hash:
var data = {
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": false
}
generic.sign(module, data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.
The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.
It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
pin: "1234"
}
const bulk = true;
generic.sign(module, data, bulk).then(res => {
}, err => {
console.error(err)
})The PIN set for bulk signing can be reset by calling this method.
generic.resetBulkPin(module).then(res => {
}, err => {
console.error(err)
})Response will look like:
{
"success": true,
"data": true
}When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:
var data = {
"pin":"..."
}
generic.verifyPin(module, data, callback);Response:
{
"verified": true
}When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:
var data = {}
generic.verifyPin(module, data, callback);Response:
{
"verified": true
}The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.
External Challenge
An external challenge is provided in the data property of the following example:
var data = {
"pin": "...",
"algorithm": "sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
generic.authenticate(module, data, callback);Response:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.
Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate
generic.allAlgoRefs(module, callback);The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)
{
"success": true,
"data": ["sha1", "sha256"]
}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
The following page describes how you can integrate the Certigna module exposed on the Trust1Connector onto your web application.
export interface AbstractCertigna {
allCertFilters(): string[];
allKeyRefs(): string[];
allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}All model information can be found in the Token typings model page
Initialise a Trust1Connector client with a valid configuration:
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
}, err => {
console.error(error)
});In order to get all connected card-readers, with available cards:
var core = client.core();
core.readersCardAvailable(callback);This function call returns:
{
"data": [
// List of reader with cards found
],
"success": true
}Using the generic interface can be done as follows;
var client = client.certigna(selected_reader.id);Because we're using the generic interface we can define the module variable upfront since we know we want to use the certigna integration.
Exposes all the certificates publicly available on the smart card.
Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
client.authenticationCertificate(parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
client.nonRepudiationCertificate(parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:
var filter = [];
client.allCerts(parseCerts, { filters: filter}, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate
var filter = ['authenticationCertificate'];
client.allCerts({ filters: filter}, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}To get the certificates necessary for signature validation in your back-end:
var filter = null;
client.allCerts({ filters: filter}, callback);Response:
{
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
}
}Depending on the connected smart card reader. A sign can be executed in 2 modes:
Using a connected card reader with 'pin-pad' capabilities (keypad and display available)
Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)
Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.
When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:
var data = {
"pin":"...",
"algorithm":"sha256",
"data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
"osDialog": true
}
client.sign(data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.
When the pin entry is done on the pin-pad, the following request is used to sign a given hash:
var data = {
"algorithm": "sha256",
"data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
"osDialog": false
}
client.sign(data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.
The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.
It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
pin: "1234"
}
const bulk = true;
client.sign(data, bulk).then(res => {
}, err => {
console.error(err)
})The PIN set for bulk signing can be reset by calling this method.
client.resetBulkPin(module).then(res => {
}, err => {
console.error(err)
})Response will look like:
{
"success": true,
"data": true
}When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:
var data = {
"pin":"..."
}
client.verifyPin(data, callback);Response:
{
"verified": true
}When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:
var data = {}
client.verifyPin(data, callback);Response:
{
"verified": true
}The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.
External Challenge
An external challenge is provided in the data property of the following example:
var data = {
"pin": "...",
"algorithm": "sha256",
"data":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="
}
client.authenticate(data, callback);Response:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.
Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate
client.allAlgoRefs(callback);The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)
{
"success": true,
"data": ["sha256"]
}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
The following page describes how you can integrate the Certigna module exposed on the Trust1Connector onto your web application.
export interface AbstractCertinomis {
allCertFilters(): string[];
allKeyRefs(): string[];
allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}All model information can be found in the Token typings model page
Initialise a Trust1Connector client with a valid configuration:
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
}, err => {
console.error(error)
});In order to get all connected card-readers, with available cards:
var core = client.core();
core.readersCardAvailable(callback);This function call returns:
{
"data": [
// List of reader with cards found
],
"success": true
}Using the generic interface can be done as follows;
var client = client.certinomis(selected_reader.id);Because we're using the generic interface we can define the module variable upfront since we know we want to use the certigna integration.
Exposes all the certificates publicly available on the smart card.
Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
client.authenticationCertificate(parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
client.nonRepudiationCertificate(parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:
var filter = [];
client.allCerts(parseCerts, { filters: filter}, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate
var filter = ['authenticationCertificate'];
client.allCerts({ filters: filter}, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}To get the certificates necessary for signature validation in your back-end:
var filter = null;
client.allCerts({ filters: filter}, callback);Response:
{
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
}
}The Certinomis token hashes the data on the token itself. Data to sign needs to be a base64 encoding of the data that needs to be signed.
When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:
var data = {
"pin":"...",
"algorithm":"sha256",
"data":"dGVzdA=="
"osDialog": true
}
client.sign(data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.
The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.
The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.
It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
const data = {
algorithm: "sha256",
data: "dGVzdA==",
pin: "1234"
}
const bulk = true;
client.sign(data, bulk).then(res => {
}, err => {
console.error(err)
})The PIN set for bulk signing can be reset by calling this method.
client.resetBulkPin(module).then(res => {
}, err => {
console.error(err)
})Response will look like:
{
"success": true,
"data": true
}When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:
var data = {
"pin":"..."
}
client.verifyPin(data, callback);Response:
{
"verified": true
}When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:
var data = {}
client.verifyPin(data, callback);Response:
{
"verified": true
}The T1C is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.
External Challenge
An external challenge is provided in the data property of the following example:
var data = {
"pin": "...",
"algorithm": "sha256",
"data":"dGVzdA=="
}
client.authenticate(data, callback);Response:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.
Via the Trust1Connector generic modules you are able to retrieve available algorithms to use for Signing or Authenticate
client.allAlgoRefs(callback);The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)
{
"success": true,
"data": ["sha256"]
}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.
The following page describes how you can integrate the Eherkenning module exposed on the Trust1Connector onto your web application.
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.
The Generic token interface is an interface used to integrate all supported tokens. This interface relies on the fact that you will need to provide a valid module. The module suggested from the reader response can be used here.
export interface AbstractEidGeneric {
getModuleDescription(module: string, callback?: (error: T1CLibException, data: DataObjectResponse) => void): Promise<DataObjectResponse>;
allData(module: string, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
allCerts(module: string, parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
biometric(module: string, callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
tokenData(module: string, callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
address(module: string, callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
picture(module: string, callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
rootCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
intermediateCertificates(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
authenticationCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
encryptionCertificate(module: string, parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
verifyPin(module: string, body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(module: string, body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(module: string, body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(module: string, callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(module: string, callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}All model information can be found in the Token typings model page
Initialise a Trust1Connector client with a valid configuration:
T1CSdk.T1CClient.initialize(config).then(res => {
client = res;
}, err => {
console.error(error)
});In order to get all connected card-readers, with available cards:
var core = client.core();
core.readersCardAvailable(callback);This function call returns:
{
"data": [
{
"card": {
"atr": "3B9813400AA503010101AD1311",
"description": ["Belgian eID Card"]
},
"id": "57a3e2e71c48cee9",
"name": "Bit4id miniLector",
"pinpad": false,
"suggestedModule": "beid"
}
],
"success": true
}As you can see in the response we get a property suggestedModule which is returned based on the card, reader and AID information. This suggested module can be used in the generic interface.
Using the generic interface can be done as follows;
var generic = client.generic(selected_reader.id, pin, pinType);The pin and pinType are optional and are used for unlocking the pace layer (if the card is protected with a pace layer).
At this point for each use-case you will need to provide the module. This can be manually defined or be retrieved from the suggestedModule property in the reader-response. In the examples below we provide the module as a variable module
The card holder is the person identified using the Belgian eID card. It's important to note that all data must be validated in your backend. Data validation can be done using the appropriate certificate (public key).
Contains all card holder related data, excluding the card holder address and photo. The service can be called:
generic.biometric(module, options, callback);An example callback:
function callback(err,data) {
if(err){
console.log("Error:",JSON.stringify(err, null, ' '));
}
else {
console.log(JSON.stringify(data, null, ' '));
}
}Response:
{
"birthDate": "15 JUL 1993",
"birthLocation": "Roeselare",
"cardDeliveryMunicipality": "Avelgem",
"cardNumber": "592..8233",
"cardValidityDateBegin": "27.05.2015",
"cardValidityDateEnd": "27.05.2025",
"chipNumber": "U0xHk...EstwAjEpJQQg==",
"documentType": "01",
"firstNames": "Gilles Frans",
"name": "Platteeuw",
"nationalNumber": "930...154",
"nationality": "Belg",
"nobleCondition": "",
"pictureHash": "Fqva9YCp...JKyn8=",
"rawData": "AQw1OTIxMjQwNTgy...TARFBar2vWAqTW+axEIuyskBgFySsp/",
"sex": "M",
"signature": "hKys9WMjUm4ipg...14xUCg/98Y9/gP/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
"specialStatus": "0",
"thirdName": "J",
"version": "0"
}Contains the card holder's address. The service can be called:
generic.address(module, callback);Response:
{
"municipality": "Hoeselt",
"rawData": "ARJLZXJrc...AAAAAA==",
"signature": "mhPyeRg25H...w==",
"streetAndNumber": "Kerkstraat X",
"version": "0",
"zipcode": "3730"
}Contains the card holder's picture stored on the smart card. The service can be called:
generic.picture(module, callback);Response:
{
"data": "/9j/4AAQSkZJRgABA...59aVpcklSDzyKUTEDGK//9k=",
"success": true
}The token info contains generic information about the card and it's capabilities. This information includes the serial number, file types for object directory files, algorithms implemented on the card, etc.
Response
{
"data": {
"eid_compliant":48,
"electrical_perso_interface_version":0,
"electrical_perso_version":3,
"graphical_perso_version":7,
"label":"BELPIC",
"prn_generation":4,
"raw_data":"MCcCAQAEEFNMSU4z...JFTFBJQwMCBDCeBAcDAAA=",
"serial_number":"534C494E..1231C",
"version":0,
"version_rfu":0
},
"success": true
}Exposes all the certificates publicly available on the smart card.
Contains the 'root certificate' stored on the smart card. The root certificate is used to sign the 'citizen CA certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not. The service can be called:
generic.rootCertificate(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the 'authentication certificate' stored on the smart card. The 'authentication certificate' contains the public key corresponding to the private RSA authentication key. The 'authentication certificate' is needed for pin validation and authentication. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
generic.authenticationCertificate(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the citizen certificate stored on the smart card. The 'citizen certificate' is used to sign the 'authentication certificate' and the 'non-repudiation certificate'. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
generic.intermediateCertificates(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the 'non-repudiation certificate' stored on the smart card. The 'non-repudiation certificate' contains the public key corresponding the private RSA non-repudiation key. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
generic.nonRepudiationCertificate(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}Contains the 'encryption certificate' stored on the smart card. The 'encryption certificate' corresponds to the private key used to sign the 'biometric' and 'Address' data. When additional parsing of the certificate is needed you can add a boolean to indicate if you want to parse the certificate or not The service can be called:
generic.encryptionCertificate(module, parseCertsBoolean, callback);Response:
{
success: true,
data: {
certificate?: string,
certificates?: Array<string>,
certificateType?: string,
id?: string,
parsedCertificate?: Certificate,
parsedCertificates?: Array<Certificate>
}
}All data on the smart card can be dumped at once, or using a filter. In order to read all data at once:
var filter = [];
generic.allData(module, { filters: filter}, callback);Response:
{
"picture": {
"picture": "/9j/4AAQSkZJRgABAgEBLAEsAAD/...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"
},
"biometric": {
"birthDate": "15 JUL 1993",
"birthLocation": "Roeselare",
"cardDeliveryMunicipality": "Avelgem",
"cardNumber": "592124058233",
"cardValidityDateBegin": "27.05.2015",
"cardValidityDateEnd": "27.05.2025",
"chipNumber": "...==",
"documentType": "01",
"firstNames": "Gilles Frans",
"name": "Platteeuw",
"nationalNumber": "...",
"nationality": "Belg",
"nobleCondition": "",
"pictureHash": "...=",
"rawData": "...+axEIuyskBgFySsp/",
"sex": "M",
"signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
"specialStatus": "0",
"thirdName": "J",
"version": "0"
},
"address": {
"municipality": "Hoeselt",
"rawData": "...==",
"signature": "...+Evety1PnTE4pqXaHgBxIpk+P8kRL5W3zDV+../../..+YoHBC9KqTmSpl5KULxdnKiyCt+2RyJdzE2wyoymjRmysIhJy1wW9PRnx99S1TFqQLuc0tyBmkBPR4aFqmOq4a7zqd0q2Q1g+BbnwJ4d3oa10ia5+0kBXf0THoXv3HYIHlnwhBMfAtWzPnFrYBuAKTwyl7yBF5IFfXFpGWuVZUTJElgNcmNvsHMnAhVwDw==",
"streetAndNumber": "Kerkstraat X",
"version": "0",
"zipcode": "3730"
}
}The filter can be used to ask a list of custom data containers. For example, we want to read only the biometric data
var filter = ['biometric'];
generic.allData(module, { filters: filter }, callback);Response:
{
"biometric": {
"birthDate": "15 JUL 1993",
"birthLocation": "Roeselare",
"cardDeliveryMunicipality": "Avelgem",
"cardNumber": "592124058233",
"cardValidityDateBegin": "27.05.2015",
"cardValidityDateEnd": "27.05.2025",
"chipNumber": "...==",
"documentType": "01",
"firstNames": "Gilles Frans",
"name": "Platteeuw",
"nationalNumber": "...",
"nationality": "Belg",
"nobleCondition": "",
"pictureHash": "...=",
"rawData": "...+axEIuyskBgFySsp/",
"sex": "M",
"signature": ".../OlA44h4YCM/h+J14xUCg/98Y9/.../C/RB2dtVbHwFvDuafmr4ZEshTlZTLidHKlISFvFWOtsLAEPCbl5LjfQwcOKe0pDADtHb4IStBnr+aaE8oHsTaKq66Y+zt+AbwdmWOrMA5URKKf7dZkY7jt3h8KZDw36VjcytUgjxVIdqwHsDkmIjK6mJtakIwybS5wn3RiQj33/vgG7JTRZJoKgDXLLTvLZO4qlfA==",
"specialStatus": "0",
"thirdName": "J",
"version": "0"
}
}All certificates on the smart card can be dumped at once, or using a filter. In order to read all certificates at once:
var filter = [];
generic.allCerts(module, parseCerts, { filters: filter}, callback);Response:
{
"rootCertificate": {
...
},
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
},
"intermediateCertificates": {
...
},
"encryptionCertificate": {
...
}
}The filter can be used to ask a list of custom data containers. For example, we want to read only the rootCertificate
var filter = ['rootCertificate'];
generic.allCerts(module, { filters: filter}, callback);Response:
{
"rootCertificate": {
...
}
}Data can be signed using the Belgian eID smart card. To do so, the T1C-GCL facilitates in:
Retrieving the certificate chain (citizen-certificate, root-certificate and non-repudiation certificate)
Perform a sign operation (private key stays on the smart card)
Return the signed hash
To get the certificates necessary for signature validation in your back-end:
var filter = null;
generic.allCerts(module, { filters: filter}, callback);Response:
{
"rootCertificate": {
...
},
"authenticationCertificate": {
...
},
"nonRepudiationCertificate": {
...
},
"intermediateCertificates": {
...
},
"encryptionCertificate": {
...
}
}Depending on the connected smart card reader. A sign can be executed in 2 modes:
Using a connected card reader with 'pin-pad' capabilities (keypad and display available)
Using a connected card reader without 'pin-pad' capabilities (no keypad nor display available)
Security consideration: In order to sign a hash, security considerations prefer using a 'pin-pad'.
When the web or native application is responsible for showing the password input, the following request is used to sign a given hash:
var data = {
"pin":"...",
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": true
}
generic.sign(module, data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'authenticationreference' property can contain the following values: sha1, sha256, sha512, md5.
When the pin entry is done on the pin-pad, the following request is used to sign a given hash:
var data = {
"algorithm":"sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E=",
"osDialog": false
}
generic.sign(module, data, callback);Response is a base64 encoded signed hash:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}The 'algorithm_reference' property can contain the following values: sha1, sha256, sha512, md5.
The core services lists connected readers, and if they have pin-pad capability. You can find more information in the Core Service documentation on how to verify card reader capabilities.
It is possible to bulk sign data without having to re-enter the PIN by adding an optional bulk parameter set to true to the request. Subsequent sign requests will not require the PIN to be re-entered until a request with bulk being set to false is sent, or the Bulk Sign Reset method is called.
When using bulk signing, great care must be taken to validate that the first signature request was successful prior to sending subsequent requests. Failing to do this will likely result in the card being blocked.
const data = {
algorithm: "sha256",
data: "E1uHACbPvhLew0gGmBH83lvtKIAKxU2/RezfBOsT6Vs=",
pin: "1234"
}
const bulk = true;
generic.sign(module, data, bulk).then(res => {
}, err => {
console.error(err)
})The PIN set for bulk signing can be reset by calling this method.
generic.resetBulkPin(module).then(res => {
}, err => {
console.error(err)
})Response will look like:
{
"success": true,
"data": true
}When the web or native application is responsible for showing the password input, the following request is used to verify a card holder PIN:
var data = {
"pin":"..."
}
generic.verifyPin(module, data, callback);Response:
{
"verified": true
}When the pin entry is done on the pin-pad, the following request is used to verify a given PIN:
var data = {}
generic.verifyPin(module, data, callback);Response:
{
"verified": true
}The T1C-GCL is able to authenticate a card holder based on a challenge. The challenge can be:
provided by an external service
provided by the smart card An authentication can be interpreted as a signature use case, the challenge is signed data, that can be validated in a back-end process.
External Challenge
An external challenge is provided in the data property of the following example:
var data = {
"pin": "...",
"algorithm": "sha1",
"data":"I2e+u/sgy7fYgh+DWA0p2jzXQ7E="
}
generic.authenticate(module, data, callback);Response:
{
"success": true,
"data": {
"data" : "W7wqvWA8m9S...="
}
}Take notice that the PIN property can be omitted when using a smart card reader with pin-pad capabilities.
Via the Trust1Connector modules you are able to retrieve available algorithms to use for Signing or Authenticate
generic.allAlgoRefs(module, callback);The response you can expect is a list of algorithms, an example can be found below (the values below are purely examplatory)
{
"success": true,
"data": ["sha1", "sha256"]
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.
Each lawyer in Belgium registered at the balie is obliged since 1/1/2018 to have an electronic lawyer card. This is declared in atr. 193bis of the Codex Deontologie voor Advocaten:
“De advocaat moet voor zijn identificatie en voor de authenticatie beschikken over de elektronische CCBE-advocatenkaart.”
More info at https://www.diplad.be/en-GB/t/23/elektronische-advocatenkaart.aspx.
export interface AbstractEidDiplad {
allData(filters: string[] | Options, callback?: (error: T1CLibException, data: TokenAllDataResponse) => void): Promise<TokenAllDataResponse>;
allCerts(parseCerts?: boolean, filters?: string[] | Options, callback?: (error: T1CLibException, data: TokenAllCertsResponse) => void): Promise<TokenAllCertsResponse>;
biometric(callback?: (error: T1CLibException, data: TokenBiometricDataResponse) => void): Promise<TokenBiometricDataResponse>;
tokenData(callback?: (error: T1CLibException, data: TokenDataResponse) => void): Promise<TokenDataResponse>;
address(callback?: (error: T1CLibException, data: TokenAddressResponse) => void): Promise<TokenAddressResponse>;
picture(callback?: (error: T1CLibException, data: TokenPictureResponse) => void): Promise<TokenPictureResponse>;
rootCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
intermediateCertificates(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
authenticationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
nonRepudiationCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
encryptionCertificate(parseCerts?: boolean, callback?: (error: T1CLibException, data: TokenCertificateResponse) => void): Promise<TokenCertificateResponse>;
verifyPin(body: TokenVerifyPinData, callback?: (error: T1CLibException, data: TokenVerifyPinResponse) => void): Promise<TokenVerifyPinResponse>;
authenticate(body: TokenAuthenticateOrSignData, callback?: (error: T1CLibException, data: TokenAuthenticateResponse) => void): Promise<TokenAuthenticateResponse>;
sign(body: TokenAuthenticateOrSignData, bulk?: boolean, callback?: (error: T1CLibException, data: TokenSignResponse) => void): Promise<TokenSignResponse>;
allAlgoRefs(callback?: (error: T1CLibException, data: TokenAlgorithmReferencesResponse) => void): Promise<TokenAlgorithmReferencesResponse>
resetBulkPin(callback?: (error: T1CLibException, data: BoolDataResponse) => void): Promise<BoolDataResponse>;
}All model information can be found in the Token typings model page
T1cSdk.initialize(config).then(res => {
const diplad = res.client.createEidDiplad(readerId);
}, err => {
console.error(error)
});diplad.allData().then(res => {
}, err => {
console.log(err);
}Response will look like:
{
"data": {
"biometric": {
"cardNumber": "cardNumber",
"cardValidityDateEnd": "2021-01-08",
"chipNumber": "c57c0a3f-d034-46c9-831e-a208b2e44fb6",
"firstNames": "Tom",
"name": "Van Cammen",
"nationality": "BE",
"rawData": "BASE64_ENCODED_CARD_DATA",
"version": "1",
"issuer": ""
},
"picture": {
"picture": "BASE64_ENCODED_BYTE_ARRAY"
}
},
"success": true
}diplad.biometric().then(res => {
}, err => {
console.log(err);
}