- 1. Introduction
- 2. General description
- 3. REST API flows
- 4. Helper libraries and demo applications
- 5. OCSP
Mobile-ID (MID) REST interface offers the entry point to main use cases for Mobile-ID:
- digital signing
- authentication
- pulling an End Users's signing certificate
- Application Provider - provider of the MID service (SK ID Solutions AS)
- Relying Party (RP) - e-service provider - client for the MID REST API. Authenticates users via MID REST service and/or uses MID REST for users to sign documents inside the e-service.
- Session - A process initiated by Relying Party, which contains authentication or signing operation.
- End User - Person that has a mobile phone with Mobile-ID SIM and who initiates authentication or signing in e-service.
- Mobile Signing - A process where (besides other operations) the hash value of document to be signed is encrypted using secret signing key (stored on SIM-card, protected by 5-digit PIN)
- Mobile Authentication - A process where generated hash is encrypted using secret authentication key (stored on SIM-card, protected by 4-digit PIN)
- Verification Code - A 4-digit number displayed both in e-service and in cellphone screen during authentication and signing. See paragraph 2.4 for more info.
- OCSP - The Online Certificate Status Protocol
Mobile-ID API is exposed over REST interface as described below. All messages are encoded using UTF-8.
Possible string values of RelyingPartyName are agreed between Relying Party and Application Provider during registration. The value from request is checked during authorization and is displayed to the End User on cell phone screen during authentication and signing. This field is case insensitive.
E-Service provider can have more than one relyingPartyName for different e-services.
relyingPartyUuid is a shared secret that is handed to Relying Party by Application Provider during registration.
This value contains hexadecimal digits in canonical 8-4-4-4-12 format, for example:
de305d54-75b4-431b-adb2-eb6b9e546014
E-Service provider can have more than one relyingPartyUUID for different e-services.
NB! The value relyingPartyUuid is case-sensitive, so only small caps are allowed.
Relying Party creates the hash using one of the supported hashing algorithms. For signing the document to be signed is the input for the chosen hash algorithm.
For authentication the hash can be random HEX string with correct length. The length has to be one of:
- 32 bytes = 64 HEX characters (if hashType is SHA-256)
- 48 bytes = 96 HEX characters (if hashType is SHA-384)
- 64 bytes = 128 HEX characters (if hashType is SHA-512)
MID REST supports signature operations based on SHA-2 family of hash algorithms, namely SHA-256, SHA-384 and SHA-512. Their corresponding identifiers in API are "SHA256", "SHA384" and "SHA512".
Verification code is a 4-digit number used in mobile authentication and mobile signing. Verification code is cryptographically linked with hash value to be signed. Verification code is displayed both in mobile phone and in e-service provider application in order to provide authenticity of the signing request and enable end user to verify what is exactly being signed.
During Mobile-ID authentication and signing it is required that e-service provider calculates verification code from the hash what will be signed and displays it to the user.
6 bits from the beginning of hash and 7 bits from the end of hash are taken. The resulting 13 bits are transformed into decimal number and printed out. The Verification code is a decimal 4-digits number in range 0000...8192, always 4 digits are displayed (e.g. 0041).
Example:
- Hash value: 2f665f6a6999e0ef0752e00ec9f453adf59d8cb6
- Binary representation of hash: 0010 1111 0110 0110 1111 .... 1000 1100 1011 0110
- Verification code – binary value: 0010110110110
- Verification code – decimal value (displayed for the user): 1462
All positive responses are given using HTTP status code "200 OK". Cases where end user is not a Mobile ID customer or the certificate of End User is not active are also considered as positive responses and HTTP status code 200 is used.
In some cases, 4xx series error codes are used, those cases are described per request. All 5xx series error codes indicate some kind of fatal server error.
Main flows of MID REST API - authentication and signing - include involvement from End User who has to enter PIN on the cellphone. As this can take time - these processes are split in two parts:
- First request initiates the process and immediately returns session id to the Relying Party.
- Relying Party has to then periodically make status check requests until the process has finished.
MID-REST API-s remain backwards compatible with following exceptions:
- new request fields may be added over time
- new fields may be added to JSON responses. Developers need to take this into account when
de-serializing JSON fields into objects. For example when using Jackson to de-serialize JSON
objects into Java objects the Java classes should be annotated with
@JsonIgnoreProperties(ignoreUnknown = true)
or the configuration parameter FAIL_ON_UNKNOWN_PROPERTIES should be set to false. Otherwise Jackson starts throwingcom.fasterxml.jackson.databind.exc.UnrecognizedPropertyException
when a new field is added to a MID-REST API response.
See chapter 3.4. for fetching current API version.
It is essential that RP performs all the required checks when connecting to the HTTPS API endpoint, to make sure that the connection endpoint is authentic and that the connection is secure. This is required to prevent MITM (Man-in-the-middle) attacks for the authentication and signature protocols.
The RP must do the following checks :
- Verify if the HTTPS connection and the TLS handshake is performed with the secure TLS ciphersuite.
- The RP must implement HTTPS pinning (https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning) and verify that the X.509 certificate of the HTTPS endpoint belongs to MID API and is trusted. The HTTPS certificate of MID API can be downloaded here: https://www.skidsolutions.eu/en/Repository/certs/other-important-certificates - section "mid.sk.ee"
- Verify that the X.509 certificate of the HTTPS endpoint is valid (not expired, signed by trusted CA and not revoked)
These checks are incorporated into:
In case the RP fails to verify the connection security and the attacks is able to launch MITM attack (you can find more info here)
BASE: mid-api
Method |
URL |
POST | BASE/certificate |
This method retrieves the signing certificate. Use cases for fetching of the signing certificate:
- to verify the signature obtained by the signature endpoint (as the signing certificate is not included in the signing response)
- for embedding the certificate into *AdES-styled digital signatures which require knowledge of the certificate before creating the signature. (See Java code example that first pulls the certificate and then starts the signing process.)
- to test if end user is a Mobile ID customer.
If end user has two pairs of certificates (RSA and Elliptic Curve Cryptography (ECC)) then system returns preferred certificate (ECC).
- User identified in the request (by relyingPartyName, relyingPartyUUID and IP-address)
- Request result has been returned to caller.
Parameter |
Type |
Mandatory |
Description |
---|---|---|---|
relyingPartyName | string | + | Name of the relying party – previously agreed with Application Provider. |
relyingPartyUUID | string | + | UUID of the relying party - is case-sensitive. |
phoneNumber | string | + | Phone number of the signer with the country code in the format of +xxxxxxxxx |
nationalIdentityNumber | string | + | Identification number of the signer (personal national ID number). For example 38412319871 |
{
"relyingPartyUUID": "de305d54-75b4-431b-adb2-eb6b9e546014" ,
"relyingPartyName": "BANK123",
"phoneNumber": "+3726234566" ,
"nationalIdentityNumber": "38412319871"
}
{
"result": "OK",
"cert": "MIIHhjCCBW6gAwIBAgIQDNYLtVwrKURYStrYApYViTANBgkqhkiG9w0B...",
"time": "2019-07-23T11:32:01",
"traceId": "5ffc28098bb14341"
}
Parameter |
Type |
Mandatory |
Description |
---|---|---|---|
result | string | + | End result of the transaction. |
cert | string | for OK result | Certificate value, DER + Base64 encoded. |
time | datetime | Since 5.2.1 | Used by Application Provider for tracking application logs of any error report. |
traceId | HEX number | Since 5.2.1 | Used by Application Provider for tracking application logs of any error report. |
For all the result values HTTP status code 200 is used.
Result | Reason |
---|---|
OK | An active certificate was found |
NOT_FOUND | No certificate for the user was found |
HTTP status code | Error message | Reason |
---|---|---|
400 | {parameterName} cannot be null. | Required parameter in request is missing on has incorrect format/value |
401 | Failed to authorize user | User authorization by relyingPartyName, relyingPartyUUID and IP-address fails |
405 | Method Not Allowed | Only POST and OPTIONS methods are allowed. |
500 | Internal error | MID-REST internal error. Retry the operation. |
Different URL-s need to be used to initiate signing or authentication:
Process |
Method |
URL |
Signing | POST | BASE/signature |
Authenticate | POST | BASE/authentication |
- End User in the request is identified.
- A new session with ID is returned in response.
Parameter |
Type |
Mandatory |
Description |
---|---|---|---|
relyingPartyName | string | + | Name of the Relying Party, previously agreed with Application Provider. Displayed together with displayText and Verification Code on cellphone screen before End User can insert PIN. |
relyingPartyUUID | string | + | UUID of the Relying Party - previously agreed with Application Provider and is case-sensitive. |
phoneNumber | string | + | Phone number of the signer with the country code in the format of +xxxxxxxxx |
nationalIdentityNumber | string | + | Identification number of the signer (personal national ID number) |
hash | string | + | Base64 encoded hash function output to be signed. |
hashType | string | + | Hash algorithm used to create the hash. |
language | string | + | Language for user dialog in mobile phone. 3-letters capitalized acronyms are used. Possible values: EST, ENG, RUS, LIT. NB! If you use language="LIT" to send to Estonian number (+372...) or you use language="EST" to send to Lithuanian number (+370...) then internally language is replaced with "ENG". |
displayText | string | Text displayed in addition to relyingPartyName and Verification Code before asking authentication PIN. Maximum length is 100 bytes that is either 50 or 100 characters depending on the encoding - see displayTextFormat. If you set displayTextFormat="GSM-7" then all characters not beloning to this alphabet are replaced with spaces. | |
displayTextFormat | string | Specifies which characters and how many can be used in "displayText". Possible values are "GSM-7" and "UCS-2”, if nothing is specified then defaults to "GSM-7". GSM-7 allows displayText to contain up to 100 characters from standard GSM 7-bit alpabet including up to 5 characters from extension table ( €[]^|{}\ ). UCS-2 allows up to 50 characters from UCS-2 alpabet (this has all Cyrillic characters, ÕŠŽ šžõ and ĄČĘĖĮŠŲŪŽ ąčęėįšųūž). [More info about encoding](https://en.wikipedia.org/wiki/GSM_03.38). |
{
"relyingPartyUUID": "00000000-0000-0000-0000-000000000000",
"relyingPartyName": "DEMO",
"phoneNumber": "+3726234566",
"nationalIdentityNumber": "38412319871",
"hash": "0nbgC2fVdLVQFZJdBbmG7oPoElpCYsQMtrY0c0wKYRg=",
"hashType": "SHA256",
"language": "ENG",
"displayText": "This is display text.",
"displayTextFormat": "GSM-7"
}
Following dialogues are displayed on end user cellphone screen for authentication and signing. Actual design varies on different phone models.
Note that when the process is signing the prompt to End User has "Sign?" in the end and authentication has "Enter?".
{
"sessionID": "de305d54-75b4-431b-adb2-eb6b9e546015"
}
Any response where HTTP status code is not 200 is considered an error condition. HTTP status code 4xx refers to errors made by the Relying Party and HTTP status code 5xx refers to an error on the Application Provider's side.
If authentication or signing is not successful because of End User not entering PIN or due to communication failure this is not considered an error condition but rather a something that can be predicted and expected i.e. it is part of the normal flow.
HTTP status code | Error message | Reason |
---|---|---|
400 | Required {parameterName} is missing. | Mandatory parameter in request is missing on has incorrect format/value |
400 | The length of the hash must match the type of hash | Hash length does not match the type of hash. For example base64 decoded value of SHA256 hash has to be (256bits divided with 8bits) = 32 bytes. |
400 | Hash must be Base64 encoded | Hash is not base64 encoded. |
401 | Failed to authorize user | User authorization by relyingPartyName, relyingPartyUUID and IP-address fails |
405 | Method Not Allowed | Only HTTP methods POST and OPTIONS are allowed |
500 | Internal error | MID-REST internal error. Try start the process again from the beginning. |
See next chapter for body of the error.
Example error response contents:
{
"error": "relyingPartyUUID must not be null",
"time": "2019-07-23T11:27:49",
"traceId": "4a295f2786d6dc89"
}
Any error response (when HTTP status code is not 200) contains an error message. This response is meant for the developer to fix the call. There is no need to parse any error responses (where HTTP status code is not 200) and these error messages should not be shown to the End User. Also error responses hold time and traceId parameters which are for Application Provider to find the application logs for any reports about possible errors of MID-REST API.
Polling of the authentication and signing status differs from endpoint name to be used.
Process |
Method |
URL |
Signing | GET | BASE/signature/session/:sessionId?timeoutMs=:timeoutMs |
Authentication | GET | BASE/authentication/session/:sessionId?timeoutMs=:timeoutMs |
- Session is present in the system and the request is either running or has been completed recently.
- Current session state has been returned to user.
Parameter |
Type |
Mandatory |
Description |
---|---|---|---|
sessionId | string | + | Session ID |
timeoutMs | integer | Maximum time in milliseconds the server is allowed to wait before returning a response. See next chapter for more info. |
In order to avoid making many requests towards Application Provider the E-Service provider is recommended to use long polling by setting parameter timeoutMs.
If the session is in RUNNING state (meaning waiting for user to enter the PIN to the cellphone and the response to arrive) the server waits this amount of time before responding.
If this parameter is not provided, a default is used (can change, value 10000ms). For very large values the service silently reverts to configuration specific maximum value (can change, value around 60000-12000ms). For very low values the service silently reverts to configuration specific minimum value (can change, value around 1000ms)
If the state of session changes during the wait time then the response is sent out immediately. If the wait time is over but the response has not yet arrived from phone then the service responds back that the session is RUNNING and the caller is encouraged to immediately create a new long polling request.
The E-Service provider should not make new requests for given session before the previous request gets a response back. However, if Application Provider detects a new request with the same session ID then the previous request is discarded and response with state=RUNNING is replied back to the previous request.
NB! E-Service provider should set its own internal request timeout to a slightly higher value (add additional ~1500ms). For example if E-Service provider makes a request with ?timeoutMs=60000 then it should set a request timeout of 61500ms (and not use the same value of 60000ms) as it takes additional time to transfer the request and response over the network.
Parameter |
Type |
Present |
Description |
---|---|---|---|
state | string | + | State of request. One of "RUNNING", "COMPLETE". |
result | string | Only if state is COMPLETE | Result of the transaction. See paragraph 3.3.7 for possible values. |
signature | string | Only if state is COMPLETE | Structure describing the signature result, if any. |
signature.value | string | Only if state is COMPLETE | Signature value, base64 encoded. |
signature.algorithm | string | Only if state is COMPLETE | Signature algorithm used, one of
SHA256WithECEncryption,
SHA256WithRSAEncryption,
SHA384WithECEncryption,
SHA384WithRSAEncryption,
SHA512WithECEncryption or
SHA512WithRSAEncryption.
Start of this value reflects the hashType parameter supplied by user (SHA256, SHA384 or SHA512). If EC (Elliptic Curve) or RSA is used - this depends on which certificates the End User has available on the SIM-Card. If SIM-card has both types of certificates available then Application Provider selects the type of certificate by its internal preferences (these preferences can change over time). |
cert | string | Only if process was authentication and signature is present. | Authentication certificate used. DER + Base64 encoded.
From the certificate it is possible to obtain end user name, national identity number and country. See [mid-rest-java-client](https://github.com/SK-EID/mid-rest-java-client) or [mid-rest-php-client](https://github.com/SK-EID/mid-rest-php-client) for examples how to parse the certificate.
See also certificate owner´s personal data structure overview that can be parsed from the certificate´s Subject field: https://github.com/SK-EID/MID/wiki/Test-number-for-automated-testing-in-DEMO#personal-data-structure-overview-that-is-located-on-the-certificates-subject-field Signing process doesn't return a certificate. To obtain the certificate used to create the signature make a separate request (see 3.1.). NB! The authentication certificate can't be used to verify the signature returned by the signing process. |
time | datetime | Since 5.2.1 | Used by Application Provider for tracking application logs of any error report |
traceId | HEX number | Since 5.2.1 | Used by Application Provider for tracking application logs of any error report |
For authentication additional steps must be followed to verify that the authentication result is trustworthy and identity of the End User is confirmed:
- "result" has the value "OK"
- "signature.value" is a valid signature over the same "hash", which was submitted by the Relying Party.
- "signature.value" is a valid signature. This can be verified by using the public key taken from the certificate returned on the "cert" field.
- The person's certificate given in the "cert" is valid. This means it is:
- not expired
- signed by trusted certificate authority
- The identity of the authenticated person is in the "subject" field of the X.509 certificate included in "cert" field.
After successful authentication, the Relying Party must also invalidate user's browser or API session identifier and generate a new one.
Response when server is still waiting for user's response to arrive back from cellphone:
{
"state":"RUNNING",
"time": "2019-07-23T11:36:16",
"traceId": "460ef8a6be5730da"
}
Signing response after successful completion:
{
"state": "COMPLETE",
"result": "OK",
"signature": {
"value": "B+C9XVjIAZnCHH9vfBSv...",
"algorithm": "SHA256WithECEncryption"
},
"time": "2019-07-23T10:52:20",
"traceId": "d8de38e7bb5d8f8a"
}
Authentication response after successful completion (note that unlike signature response it also includes authentication certificate):
{
"state": "COMPLETE",
"result": "OK",
"signature": {
"value": "B+C9XVjIAZnCHH9vfBSv...",
"algorithm": "SHA256WithECEncryption"
},
"cert": "MIIFxjCCA66gAwIBAgIQZ6v2ut9...",
"time": "2019-07-23T10:52:20",
"traceId": "d8de38e7bb5d8f8a"
}
If user cancelled the operation:
{
"state": "COMPLETE",
"result": "USER_CANCELLED",
"time": "2019-07-23T11:36:38",
"traceId": "2f3bebf7036c51f1"
}
When response from end user's cell phone has not arrived within a timeout period set by Application Provider. The Application Provider has given up waiting for it to arrive and responds with:
{
"state": "COMPLETE",
"result": "TIMEOUT",
"time": "2019-07-23T11:36:11",
"traceId": "bc861f0cf0568570"
}
The following is a complete list of possible result codes returned by the service. For all of them a HTTP 200 status code and a JSON string is returned with "state": "COMPLETE" and "result" with one of the following values:
Result | Reason |
---|---|
OK | Session was completed successfully |
TIMEOUT | There was a timeout, i.e. end user did not confirm or refuse the operation within maximum time frame allowed (can change, around two minutes). |
NOT_MID_CLIENT | Given user has no active certificates and is not MID client. |
USER_CANCELLED | User cancelled the operation |
SIGNATURE_HASH_MISMATCH | Mobile-ID configuration on user's SIM card differs from what is configured on service provider's side. User needs to contact his/her mobile operator. |
PHONE_ABSENT | Sim not available |
DELIVERY_ERROR | SMS sending error |
SIM_ERROR | Invalid response from card |
Error code | Error message | Reason |
---|---|---|
400 | Required sessionId is missing | Required paramter sessionId is missing. |
401 | Failed to authorize user | User authorization by sessionId and IP-address fails |
404 | SessionID not found | Sessions expire within 5 minutes. |
405 | Method Not Allowed | Only GET and OPTIONS are allowed methods. |
500 | Internal error | MID-REST internal error. Try start the process again from the beginning. |
Method | URL |
---|---|
GET | BASE/version |
Version: 5.1.1. Built: 19.06.2019 21:06
Version: MAJOR.MINOR.PATCH. Built: dd.MM.yyyy hh:mm
Version numbering:
- MAJOR version is incremented when a new API is released or if there have been major internal changes. See chapter 2.7. for notes about API backwards compatibility.
- MINOR version is incremented when there are smaller internal changes, new request parameters or new response fields are added.
- PATCH version is incremented with backwards-compatible bug fixes. No fields are added with bug fixes.
Built timestamp refers when the release was built from source code.
Open link: https://tsp.demo.sk.ee/mid-api/version
There are client libraries provided for easier integration for Java and PHP and also demo applications that demonstrate usage of the client libraries.
Java Clint allows using all of the MID-REST functionality.
Provided PHP functionality only supports authentication and fetching the signing certificate.
The Online Certificate Status Protocol is an Internet protocol used for obtaining the revocation status of an X.509 digital certificate. See Validity Confirmation Services offered by SK for more information.
When digitally signing AsicE and Bdoc containers by standard then for the signature to be valid it is required to perform OCSP for signer's certificate at the time of signing and include OCSP response as part of the signature. MID-REST doesn't perform any OCSP requests.
Digidoc4j performs the OCSP during signing process and includes OCSP response it in the signature. For testing purposes, it is possible to use Test OCSP by building the signature Container with Test Configuration. To use test ocsp you need to upload your signing certificate here.
Configuration configuration = new Configuration(Configuration.Mode.TEST);
Container container = ContainerBuilder.aContainer()
.withConfiguration(configuration)
.withDataFile(uploadedFile)
.build();