PHPackages                             vatsake/smart-id-php-client - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. vatsake/smart-id-php-client

ActiveLibrary[API Development](/categories/api)

vatsake/smart-id-php-client
===========================

Smart-ID Relying Party PHP Api client

2.3.3.2(6mo ago)05MITPHPPHP &gt;=7.4

Since Dec 29Pushed 5mo agoCompare

[ Source](https://github.com/vatsake/smart-id-php-client)[ Packagist](https://packagist.org/packages/vatsake/smart-id-php-client)[ Docs](https://github.com/vatsake/smart-id-php-client)[ RSS](/packages/vatsake-smart-id-php-client/feed)WikiDiscussions master Synced today

READMEChangelog (2)Dependencies (2)Versions (3)Used By (0)

Signing functionality
---------------------

[](#signing-functionality)

```
$this->client = new Client();
$this->client
    ->setRelyingPartyUUID( '00000000-0000-0000-0000-000000000000' ) // In production replace with your UUID
    ->setRelyingPartyName( 'DEMO' ) // In production replace with your name
    ->setHostUrl( 'https://sid.demo.sk.ee/smart-id-rp/v2/' ) // In production replace with production service URL
        // in production replace with correct server SSL key
    ->setPublicSslKeys("sha256//Ps1Im3KeB0Q4AlR+/J9KFd/MOznaARdwo4gURPCLaVA=");

$semanticsIdentifier = SemanticsIdentifier::builder()
    ->withSemanticsIdentifierType('PNO')
    ->withCountryCode('LT')
    ->withIdentifier('30303039914')
    ->build();

try {
  $resp = $client->signature()->createCertificateChoice()
      ->withSemanticsIdentifier($semanticsIdentifier)
      ->withCertificateLevel('QUALIFIED')
      ->chooseCertificate();
} catch (\Exception $e) { // Use exceptions below
    throw new RuntimeException("Smart-ID authentication process failed for uncertain reason: " . $e);
}

$data = new SignatureHash('12312312312312');
$data->setHashType('SHA256');
echo "Verification code: " . $data->calculateVerificationCode();

try {
  $resp = $client->signature()->createSignature()
      ->withDocumentNumber($resp->getDocumentNumber())
      ->withCertificateLevel('QUALIFIED')
      ->withSignableData($data)
      ->withAllowedInteractionsOrder([
          Interaction::ofTypeVerificationCodeChoice('Kood')
      ])
      ->sign();
} catch (\Exception $e) { // Use exceptions below
  throw new RuntimeException("Smart-ID authentication process failed for uncertain reason: " . $e);
}

// Or skip cert choice entirely
try {
  $resp = $client->signature()->createSignature()
      ->withSemanticsIdentifier($semanticsIdentifier)
      ->withCertificateLevel('QUALIFIED')
      ->withSignableData($data)
      ->withAllowedInteractionsOrder([
          Interaction::ofTypeVerificationCodeChoice('Kood')
      ])
      ->sign();
} catch (\Exception $e) { // Use exceptions below
    throw new RuntimeException("Smart-ID authentication process failed for uncertain reason: " . $e);
}
```

Breaking changes
----------------

[](#breaking-changes)

- AuthenticationResponseValidator now requires FULL path to folder (removed the trusted\_certificates suffix)

Minor changes
-------------

[](#minor-changes)

- Renamed AuthenticationSessionRequest -&gt; SessionRequest
- Renamed AuthenticationSessionResponse -&gt; SessionResponse

ORIGINAL DOCUMENTATION
======================

[](#original-documentation)

[![Tests](https://github.com/SK-EID/smart-id-php-client/actions/workflows/tests.yaml/badge.svg)](https://github.com/SK-EID/smart-id-php-client/actions/workflows/tests.yaml)[![Latest Version](https://camo.githubusercontent.com/5d53a2013e2730cb69f0761a7d6dcef859219f07ea5f3638ca5511742a9f4049/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736b2d69642d736f6c7574696f6e732f736d6172742d69642d7068702d636c69656e743f6c6162656c3d76657273696f6e)](https://packagist.org/packages/sk-id-solutions/smart-id-php-client/)[![License: MIT](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](https://opensource.org/licenses/MIT)

Smart-ID PHP client
===================

[](#smart-id-php-client)

Introduction
------------

[](#introduction)

The Smart-ID PHP client can be used for easy integration of the Smart-ID solution to information systems or e-services.

Features
--------

[](#features)

- Simple interface for user authentication

Smart-ID PHP client works with PHP 7.4 and PHP 8+

**This PHP client cannot be used to create digitally signed containers because PHP does not have a library like DigiDoc4J.**

Installation
------------

[](#installation)

The recommended way to install Smart-ID PHP Client is through [Composer](http://getcomposer.org):

```
composer require sk-id-solutions/smart-id-php-client "2.3.3"

```

See [packagist](https://packagist.org/packages/sk-id-solutions/smart-id-php-client) for latest published version and [changelog](CHANGELOG.md) for details.

How to use it
=============

[](#how-to-use-it)

Configure client details and https pinning
------------------------------------------

[](#configure-client-details-and-https-pinning)

Used to prevent man-in-the-middle attacks. [More on man in the middle attacks in case of using smart id.](https://github.com/SK-EID/smart-id-documentation#226-rp-api-endpoint-authentication)

Setting the client to trust specific public keys. Production SSL certificates used can be found [here](https://www.skidsolutions.eu/en/repository/certs/)and demo environment certificates are [here](https://www.skidsolutions.eu/resources/certificates/#Test-certificates).

The setPublicSslKeys method requires a string of sha256 hashes of the public keys used delimited with ";". You can extract hashes from certificates using next openssl command.

```
openssl x509 -inform PEM -in certificate.pem -noout -pubkey | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -binary | openssl enc -base64

```

The supplied string should be of format sha256//sha256-hash-of-the-public-key;

```
$this->client = new Client();
$this->client
    ->setRelyingPartyUUID( '00000000-0000-0000-0000-000000000000' ) // In production replace with your UUID
    ->setRelyingPartyName( 'DEMO' ) // In production replace with your name
    ->setHostUrl( 'https://sid.demo.sk.ee/smart-id-rp/v2/' ) // In production replace with production service URL
        // in production replace with correct server SSL key
    ->setPublicSslKeys("sha256//Ps1Im3KeB0Q4AlR+/J9KFd/MOznaARdwo4gURPCLaVA=");
```

Authenticating with semantics identifier
----------------------------------------

[](#authenticating-with-semantics-identifier)

Following example also demonstrates how to validate authentication result and how to handle exceptions.

```
$semanticsIdentifier = SemanticsIdentifier::builder()
    ->withSemanticsIdentifierType('PNO')
    ->withCountryCode('LT')
    ->withIdentifier('30303039914')
    ->build();

// For security reasons a new hash value must be created for each new authentication request
$authenticationHash = AuthenticationHash::generate();

$verificationCode = $authenticationHash->calculateVerificationCode();

// display verification code to the user
echo "Verification code: " . $verificationCode . "\n";

$authenticationResponse = null;
try
{
  $authenticationResponse = $this->client->authentication()
      ->createAuthentication()
      ->withSemanticsIdentifier( $semanticsIdentifier )
      ->withAuthenticationHash( $authenticationHash )
      ->withCertificateLevel( CertificateLevelCode::QUALIFIED ) // Certificate level can either be "QUALIFIED" or "ADVANCED"
      ->withAllowedInteractionsOrder((array(
          Interaction::ofTypeVerificationCodeChoice("Enter awesome portal?"),
          Interaction::ofTypeDisplayTextAndPIN("Enter awesome portal?"))))
      ->authenticate(); // this blocks until user has responded
}
catch (UserRefusedException $e) {
  throw new RuntimeException("You pressed cancel in Smart-ID app.");
}
catch (UserSelectedWrongVerificationCodeException $e) {
  throw new RuntimeException("You selected wrong verification code in Smart-ID app. Please try again. ");
}
catch (SessionTimeoutException $e) {
  throw new RuntimeException("Session timed out (you didn't enter PIN1 in Smart-ID app).");
}
catch (UserAccountNotFoundException $e) {
  throw new RuntimeException("User does not have a Smart-ID account");
}
catch (UserAccountException $e) {
  throw new RuntimeException("Unable to authenticate due to a problem with your Smart-ID account.");
}
catch (EnduringSmartIdException $e) {
  throw new RuntimeException("Problem with connecting to Smart-ID service. Please try again later.");
}
catch (SmartIdException $e) {
  throw new RuntimeException("Smart-ID authentication process failed for uncertain reason: ". $e);
}

// create a folder with name "trusted_certificates" and set path to that folder here:
$pathToFolderWithTrustedCertificates = __DIR__ . '/../../../resources';

$authenticationResponseValidator = new AuthenticationResponseValidator($pathToFolderWithTrustedCertificates);
$authenticationResult = $authenticationResponseValidator->validate( $authenticationResponse );

if ($authenticationResult->isValid()) {
  echo "Hooray! Authentication result is valid";
}
else {
   throw new RuntimeException("Error! Response is not valid! Error(s): ". implode(",", $authenticationResult->getErrors()));
}

$authenticationIdentity = $authenticationResult->getAuthenticationIdentity();

echo "hello name: " . $authenticationIdentity->getGivenName() . ' ' . $authenticationIdentity->getSurName() . "\n";
echo "from " . $authenticationIdentity->getCountry() . "\n";
echo "born " . $authenticationIdentity->getDateOfBirth()->format("D d F o") . "\n";

// you might need this if you want to start authentication with document number
echo "Authenticated user documentNumber is: ".$authenticationResponse->getDocumentNumber(). "\n";
```

### Validate authentication result

[](#validate-authentication-result)

To validate the authentication result (that it was signed by Smart-ID and not some man-in-the-middle or accidentally connecting to demo environment from production). You need to create directory trusted\_certificates and place smart-id certificates in there. You can get the needed certificates from links that are described in the "https pinning" chapter above.

Example path to resource directory: $resourceLocation = '/path/to/resource'; where it will look for directory named trusted\_certificates and read certs from there. If no path is specified it will take trusted certs, that are provided by client itself. They are located at src/resources/trusted\_certificates.

#### Note about verification code and validating the signature

[](#note-about-verification-code-and-validating-the-signature)

This what happens behind the scenes (all the steps besides step #5 are performed by this library):

1. For every new authentication the library generates a random value (stored into variable 'dataToSign')
2. A digest (SHA-512, SHA-384 or SHA-256) is calculated out of this random value (stored into variable 'hash')
3. Verification code that is displayed to the end user is calculated out of this digest.
4. The authentication request (together with value of 'hash') is sent out to the server.
5. Now signing process takes place in user's the phone and the Smart-ID REST service returns the signature and the authentication certificate of the user.
6. The library verifies that the signature value that was returned is really a valid signature. (For the verification it uses the value of 'dataToSign' (and not the digest that is stored in 'hash') together with the authentication signature.)

### Extract date of birth of the authenticated person

[](#extract-date-of-birth-of-the-authenticated-person)

All Estonian and Lithuanian national identity numbers contain date-of-birth info ant his is why getDateOfBirth() function always returns a correct value for them. Also birthdate info is present within old type of Latvian national identity numbers.

```
echo "born " . $authenticationIdentity->getDateOfBirth()->format("D d F o") . "\n";

```

For persons with new type of Latvian national identity number the date-of-birth is parsed from a separate field of the certificate but for some older Smart-id accounts (issued between 2017-07-01 and 2021-05-20) the value might be missing.

More info about the availability of this separate field in the certificates:

Authenticating with document number
-----------------------------------

[](#authenticating-with-document-number)

It might be needed to use document number instead of semantics identifier when you are (for some reason) re-authenticating the user in a short period of time and you want the user to use the same device as previously.

If user has several Smart-ID accounts (for example one in phone and one in tablet) then when authenticating with semantics identifier both of the devices initiate the flow (user can pick either one of the devices and type in PIN there). Since document number is device-specific then when you use document number only one of user devices starts the authentication flow.

You get the documentNumber of the user after successful authentication. See the example above where documentNumber is logged out in the end.

```
$authenticationResponse = $this->client->authentication()
  ->createAuthentication()
  ->withDocumentNumber( 'PNOLT-30303039914-MOCK-Q' )
  ->withAuthenticationHash( $authenticationHash )
  ->withCertificateLevel( CertificateLevelCode::QUALIFIED ) // Certificate level can either be "QUALIFIED" or "ADVANCED"
  ->withAllowedInteractionsOrder((array(
      Interaction::ofTypeVerificationCodeChoice("Enter awesome portal?"),
      Interaction::ofTypeDisplayTextAndPIN("Enter awesome portal?"))))
  ->authenticate(); // this blocks until user has responded
```

Authenticate with polling every 5 seconds
-----------------------------------------

[](#authenticate-with-polling-every-5-seconds)

Previous examples block until the user has typed in PIN code or pressed cancel or authentication has failed for some other reason (like timeout). This example demonstrates polling the status every 5 seconds.

```
$sessionId = null;
try
{
  $sessionId = $this->client->authentication()
      ->createAuthentication()
      ->withSemanticsIdentifier( $semanticsIdentifier ) // or with document number: ->withDocumentNumber( 'PNOEE-10101010005-Z1B2-Q' )
      ->withAuthenticationHash( $authenticationHash )
      ->withCertificateLevel( CertificateLevelCode::QUALIFIED ) // Certificate level can either be "QUALIFIED" or "ADVANCED"
      ->withAllowedInteractionsOrder((array(
          Interaction::ofTypeVerificationCodeChoice("Ready to poll?"),
          Interaction::ofTypeDisplayTextAndPIN("Ready to poll status repeatedly?"))))
      ->startAuthenticationAndReturnSessionId();
}
catch (SmartIdException $e) {
  // Handle exception (more on exceptions in "Handling intentional exceptions")
  throw new RuntimeException("Authentication failed. NB! Use exception handling blocks from above example: ". $e);
}

$authenticationResponse = null;
try
{
  for ( $i = 0; $i client->authentication()
        ->createSessionStatusFetcher()
        ->withSessionId( $sessionId )
        ->withAuthenticationHash( $authenticationHash )
        ->withSessionStatusResponseSocketTimeoutMs( 10000 )
        ->getAuthenticationResponse();

    if ( !$authenticationResponse->isRunningState() )
    {
      break;
    }
    sleep( 5 );
  }
}
catch (SmartIdException $e) {
  throw new RuntimeException("Authentication failed. NB! Use exception handling blocks from above example.". $e);
}

// validate authentication result, get authentication person details
```

###  Health Score

31

—

LowBetter than 66% of packages

Maintenance69

Regular maintenance activity

Popularity3

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity36

Early-stage or recently created project

 Bus Factor2

2 contributors hold 50%+ of commits

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

2

Last Release

184d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/06799e5d32624d2538e602535a169a38953809b00459d0f7e6ddfcc97ffdc61c?d=identicon)[vatsake](/maintainers/vatsake)

---

Top Contributors

[![jalukse](https://avatars.githubusercontent.com/u/19568991?v=4)](https://github.com/jalukse "jalukse (36 commits)")[![jeserkin](https://avatars.githubusercontent.com/u/183512?v=4)](https://github.com/jeserkin "jeserkin (36 commits)")[![aasaru](https://avatars.githubusercontent.com/u/6773052?v=4)](https://github.com/aasaru "aasaru (12 commits)")[![alvar-sk](https://avatars.githubusercontent.com/u/28784388?v=4)](https://github.com/alvar-sk "alvar-sk (10 commits)")[![sk-natalja](https://avatars.githubusercontent.com/u/70746337?v=4)](https://github.com/sk-natalja "sk-natalja (7 commits)")[![vatsake](https://avatars.githubusercontent.com/u/36108180?v=4)](https://github.com/vatsake "vatsake (5 commits)")[![edgarsn](https://avatars.githubusercontent.com/u/6625918?v=4)](https://github.com/edgarsn "edgarsn (1 commits)")[![ttoomema](https://avatars.githubusercontent.com/u/17985911?v=4)](https://github.com/ttoomema "ttoomema (1 commits)")[![rkaalma](https://avatars.githubusercontent.com/u/25532263?v=4)](https://github.com/rkaalma "rkaalma (1 commits)")[![DonRico](https://avatars.githubusercontent.com/u/1980276?v=4)](https://github.com/DonRico "DonRico (1 commits)")[![mikk125](https://avatars.githubusercontent.com/u/7293004?v=4)](https://github.com/mikk125 "mikk125 (1 commits)")

---

Tags

apismart-idrelyingparty

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/vatsake-smart-id-php-client/health.svg)

```
[![Health](https://phpackages.com/badges/vatsake-smart-id-php-client/health.svg)](https://phpackages.com/packages/vatsake-smart-id-php-client)
```

###  Alternatives

[sk-id-solutions/smart-id-php-client

Smart-ID PHP client

231.0M2](/packages/sk-id-solutions-smart-id-php-client)[n1ebieski/ksef-php-client

PHP API client that allows you to interact with the API Krajowego Systemu e-Faktur

9067.8k](/packages/n1ebieski-ksef-php-client)[comgate/sdk

Comgate PHP SDK

13373.6k](/packages/comgate-sdk)[soneso/stellar-php-sdk

Stellar PHP SDK for the Stellar Network

4154.3k4](/packages/soneso-stellar-php-sdk)[culqi/culqi-php

Cliente Culqi API para PHP

41370.5k1](/packages/culqi-culqi-php)[satispay/gbusiness-api-php-sdk

Satispay GBusiness API PHP SDK

19218.9k4](/packages/satispay-gbusiness-api-php-sdk)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
