Response verification

After receiving the transaction response from the session status API call the following algorithm must be used to decide

  • if the authentication result is trustworthy and what the identity of the authenticating end user is,

  • if the signature result is valid.

In App2App and Web2App flows, the response verification step must be performed after the user has returned via the callback URL, as described in Callback URLs page.

Response verification steps

The following steps perform the response verification algorithm. Note that the algorithm is applicable to both authentication and signature session flows. Specific differences, such as the conditional execution of Steps 1 and 3, are noted within the steps.

  1. Session secret verification (applicable only for sessions with flow type Web2App or App2App):

    1. Base64 decode the sessionSecret string received in the initial request.

    2. Calculate the SHA-256 digest of the Base64 decoded sessionSecret value.

    3. Encode the raw bytes of the calculated hash using Base64URL.

    4. Obtain the sessionSecretDigest value from the callback URL parameter visited by the user upon returning to the RP website or application.

    5. Verify that this Base64URL encoded hash result exactly matches the sessionSecretDigest obtained from the callback URL.

  2. Initial session response check:

    1. Verify the state field in the JSON response is exactly COMPLETE.

    2. Verify the result.endResult field is exactly OK.

    3. Verify the signatureProtocol field is exactly ACSP_V2 in case of authentication or RAW_DIGEST_SIGNATURE in case of signature.

    4. Ensure the cert, signature, and result objects are present and not null.

  3. User challenge verification (applicable only for authentication sessions with flow type Web2App or App2App):

    1. Obtain the userChallengeVerifier value from the callback URL parameter visited by the user upon returning to the RP website or application.

    2. Calculate the SHA-256 digest of the received userChallengeVerifier string.

    3. Encode the raw bytes of the calculated hash using Base64URL.

    4. Verify that this Base64URL encoded hash result exactly matches the signature.userChallenge string provided in the JSON response’s signature object.

  4. Certificate Chain Validation and Trust:

    1. Decode the Base64 encoded end-entity certificate string from cert.value and parse it into a standard X.509 certificate representation. The RP API provides only the end-entity certificate, the Relying Party must have the necessary root and intermediate CA certificates configured locally to allow the library to build the full certificate chain. For these certificates, see Certificates page.

    2. Using a standard cryptographic library, initiate the validation of the certificate chain starting from the end-entity certificate. Provide the end-entity certificate to the library, along with configuring it with the set of trusted CA certificates (trust anchors).

      • It’s important to note that some libraries use the system certificate store in addition to the provided CA certificates, this should be disabled and only the explicitly configured CA certificates should be used.

    3. For each certificate in the constructed chain (end-entity certificate and all intermediate CA certificates), perform the following checks. A standard cryptographic library will typically perform the following checks as part of its overall chain validation routine and report the result as a success or failure.

      1. Verify the certificate’s digital signature using the public key of its issuer certificate.

      2. Verify the certificate’s validity period against the current time, i.e., not before the notBefore date and not after the notAfter date.

      3. Verify that the certificate has not been revoked. This check should be performed using the Online Certificate Status Protocol (OCSP), utilizing the Authority Information Access (AIA) extension within the certificate to locate the OCSP responder URL. If OCSP fails or is unavailable, Certificate Revocation List (CRL) checking should be used as fallback.

        1. Note: Revocation checks (OCSP/CRL) are not performed on self-signed root CA certificates configured as trust anchors. Intermediate CA certificates can be revoked and must be checked.

        2. Note: OCSP responses are digitally signed. The certificate chain of the OCSP responder itself should also be verified, ensuring it is trusted and authorized to provide status for the certificate being checked.

      4. Verify basic constraints are appropriate: Intermediate CA certificates must have the Basic Constraints extension present with the cA boolean set to TRUE. For end-entity certificates, the Basic Constraints extension should either absent, or if present, its cA boolean should be set to FALSE.

  5. Smart-ID Scheme Identification (End-Entity Certificate):

    1. Before checking specific purposes, verify that the end-entity certificate belongs to the Smart-ID scheme.

      1. Examine the Certificate Policies extension of the end-entity certificate. The certificate must contain all the specific policy OIDs designated by SK ID Solutions for the Smart-ID scheme (as defined in Chapter 2.2.3 of the "Smart-ID Certificate and OCSP Profile" in Certificate Profiles page). These OIDs differentiate Smart-ID certificates from other types of certificates (e.g., Mobile-ID, Estonian ID-card). The Relying Party must consult the current official SK ID Solutions Certificate Policies for the definitive list of Smart-ID scheme policy OIDs. For these certificate policies, see Certificate Policies page.

      2. If not all the recognized Smart-ID scheme policy OIDs are present, the certificate should not be processed as a Smart-ID certificate, and the verification should fail for this context.

  6. End-Entity Certificate Purpose Validation (Smart-ID Context):

    1. Examine the end-entity certificate for extensions and attributes required by the certificate profile. For these certificate profiles, see Certificate Profiles page.

      1. For Smart-ID authentication: To confirm the certificate is suitable for authentication, it must contain one of the following:

        • The digitalSignature key usage and the Smart-ID authentication (1.3.6.1.4.1.62306.5.7.0) Extended Key Usage which is present in certificates issued April 2025 onwards.

        • The digitalSignature, keyEncipherment, dataEncipherment key usages and the id-kp-clientAuth (1.3.6.1.5.5.7.3.2) Extended Key Usage which is found in older, still valid certificates issued before April 2025.

      2. For digital signing: Check for appropriate key usage nonRepudiation.

  7. Assurance Level Check:

    1. Extract the assurance level string from cert.certificateLevel (e.g., ADVANCED, QUALIFIED).

    2. For qualified certificates, check that the extension values as defined by the certificate profile exist within the certificate from cert.value.

    3. Compare this level against the minimum assurance level required by the RP for the specific context or transaction. Ensure the certificate’s level meets or exceeds the required level (note that ADVANCED < QUALIFIED).

  8. Identity Match Check:

    1. Extract the authenticated user’s identifier from the end-entity certificate. For Smart-ID certificates serialNumber (OID 2.5.4.5) under Subject DN contain the national identity code, for example PNOEE-30001010004.

    2. If the RP initiated the authentication or signing for a specific known user, verify that the extracted identifier matches the expected identity for that session.

  9. Verification of signature Object (authentication/signature session):

    1. Only for authentication session: Reconstruct the exact ACSP_V2_payload string that was signed, as described under ACSP_V2 digest calculation. This is done by concatenating the fields in order, separated by the vertical bar character | (U+007C):

      'smart-id'|'ACSP_V2'|serverRandom|rpChallenge|userChallenge|BASE64(relyingPartyName)|BASE64(brokeredRpName)|BASE64(SHA-256(interactions))|interactionTypeUsed|initialCallbackUrl|flowType
    2. Only for signature session: Use the data-to-be-signed, a digest of which was initially sent when initiating the signature session (as described in RAW_DIGEST_SIGNATURE signature protocol).

    3. Decode the signature value from signature.value using Base64 decoding.

    4. Obtain the public key from the parsed end-entity user certificate (from Step 4).

    5. Only for authentication session: Using a cryptographic library, verify the decoded signature against the UTF-8 bytes of the reconstructed ACSP_V2_payload string.

    6. Only for signature session: Using a cryptographic library, verify the decoded signature against either the data-to-be-signed or the hash of the data-to-be-signed (there are libraries that provide options for either).

    7. Ensure the verification uses the algorithm specified in signature.signatureAlgorithm (e.g., rsassa-pss) and correctly applies the parameters from signature.signatureAlgorithmParameters (e.g., hash algorithm like SHA-512, MGF1 hash like SHA-512, salt length like 64, and the trailer field 0xbc).

  10. Session Management (Only for authentication sessions. Important: only perform if all the preceding steps (1-9) were successful):

    1. Invalidate any previous, unauthenticated session identifier associated with the user’s interaction (e.g., browser cookie or API token used before successful authentication).

    2. Generate a new, secure, and unique session identifier representing the now authenticated state.

    3. Associate the authenticated user’s identity (from Step 8) and potentially the assurance level (from Step 7) with this new session identifier in your server-side session store.

  11. After a successful action, the users should be able to view their actions or download the signed document. For more information, see Allowing users to verify operations section.