ekapusta / oauth2-esia
Allows to authenticate in ESIA and get authenticated individual personal information.
Installs: 159 063
Dependents: 1
Suggesters: 0
Security: 0
Stars: 67
Watchers: 13
Forks: 48
Open Issues: 8
Requires
- php: ^5.6 || ^7.0
- lcobucci/jwt: ^3.2.2
- league/oauth2-client: ^2.4.1
- psr/log: ^1.0
- ramsey/uuid: ^3.0 || ^4.0
Requires (Dev)
- bramus/monolog-colored-line-formatter: ^2.0
- monolog/monolog: ^1.24
- phpunit/phpunit: ^6
- satooshi/php-coveralls: ^1.0
README
Allows to authenticate in ESIA and get authenticated individual personal information.
Implemented as adapter to the PHP League's OAuth 2.0 Client.
Installing
To install, use composer:
composer require ekapusta/oauth2-esia
Usage
Usage is the same as the normal client, using Ekapusta\OAuth2Esia\Provider\EsiaProvider
as the provider:
Configure provider
use Ekapusta\OAuth2Esia\Provider\EsiaProvider; use Ekapusta\OAuth2Esia\Security\JWTSigner\OpenSslCliJwtSigner; use Ekapusta\OAuth2Esia\Security\Signer\OpensslPkcs7; $provider = new EsiaProvider([ 'clientId' => 'XXXXXX', 'redirectUri' => 'https://your-system.domain/auth/finish/', 'defaultScopes' => ['openid', 'fullname', '...'], // For work with test portal version // 'remoteUrl' => 'https://esia-portal1.test.gosuslugi.ru', // 'remotePublicKey' => EsiaProvider::RESOURCES.'esia.test.public.key', // For work with GOST3410_2012_256 signatures (instead of default RS256) // 'remoteCertificatePath' => EsiaProvider::RESOURCES.'esia.gost.prod.public.key', ], [ 'signer' => new OpensslPkcs7('/path/to/public/certificate.cer', '/path/to/private.key'), // For work with GOST3410_2012_256 signatures (instead of default RS256) // 'remoteSigner' => new OpenSslCliJwtSigner('/path/to/openssl'), ]);
Which signer to use?
- If you use RSA keys, then
OpensslPkcs7
is enough. - If you use GOST keys and compiled PHP with GOST ciphers, then
OpensslPkcs7
is enough. - If you use GOST keys and have openssl-compatible tool, then use
OpensslCli
. It hastoolpath
param. - If you use GOST keys and you are docker-addict, then you can use
'toolpath' => 'docker run --rm -i -v $(pwd):$(pwd) -w $(pwd) rnix/openssl-gost openssl'
.
Which remote signer to use?
- If your system electronic signature algorythm is default RS256, then do nothing. Under the hood it uses Sha256 remote signer.
- If you use GOST3410_2012_256 signature, then use
OpenSslCliJwtSigner
, passing to it path toopenssl
tool. For dockers pass to it something likedocker run --rm -i -v $(pwd):$(pwd) -v /tmp/tmp -w $(pwd) rnix/openssl-gost openssl'
./tmp
volume is important there!
Auth flow
Auth flow is standard.
// https://your-system.domain/auth/start/ $authUrl = $provider->getAuthorizationUrl(); $_SESSION['oauth2.esia.state'] = $provider->getState(); header('Location: '.$authUrl); exit; // https://your-system.domain/auth/finish/?state=...&code=... if ($_SESSION['oauth2.esia.state'] !== $_GET['state']) { exit('The guard unravels the crossword.'); } $accessToken = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]); $esiaPersonData = $provider->getResourceOwner($accessToken); var_export($esiaPersonData->toArray());
Simplified facade
If you don't like classes with about 20 public methods, there is simplified facade-class.
use Ekapusta\OAuth2Esia\EsiaService; $service = new EsiaService($provider); // https://your-system.domain/auth/start/ $_SESSION['oauth2.esia.state'] = $service->generateState(); $authUrl = $service->getAuthorizationUrl($_SESSION['oauth2.esia.state']); header('Location: '.$authUrl); exit; // https://your-system.domain/auth/finish/?state=...&code=... $esiaPersonData = $service->getResourceOwner($_SESSION['oauth2.esia.state'], $_GET['state'], $_GET['code']) var_export($esiaPersonData->toArray());
Example $esiaPersonData
{ "resourceOwnerId": 1000404446, "stateFacts": [ "EntityRoot" ], "firstName": "Имя006", "lastName": "Фамилия006", "middleName": "Отчество006", "birthDate": "26.05.2000", "birthPlace": "Москва", "gender": "F", "trusted": true, "citizenship": "RUS", "snils": "000-000-600 06", "inn": "585204118212", "updatedOn": 1523386683, "contacts": { "stateFacts": [ "hasSize" ], "size": 3, "eTag": "5F535ACCAEB3018D0AAA8C46027E3CF2C4BD0197", "elements": [ { "stateFacts": [ "Identifiable" ], "id": 14216773, "type": "EML", "vrfStu": "VERIFIED", "value": "EsiaTest006@yandex.ru", "verifyingValue": "EsiaTest006@yandex.ru", "vrfValStu": "VERIFYING", "isCfmCodeExpired": true, "eTag": "17DCA3945F1B8B54496F59EB146BDC7DADAD7BC8" }, { "stateFacts": [ "Identifiable" ], "id": 14249750, "type": "PHN", "vrfStu": "NOT_VERIFIED", "value": "+7(840)0000006", "eTag": "943C1145E4973324599CD0E4FF136186502C93C5" }, { "stateFacts": [ "Identifiable" ], "id": 14244504, "type": "MBT", "vrfStu": "VERIFIED", "value": "+7(000)0000006", "verifyingValue": "+7(111)1111111", "vrfValStu": "VERIFYING", "isCfmCodeExpired": true, "eTag": "F3AA3B18B35BC12E53E0B7A7EAF13EC41EBD02AD" } ] }, "addresses": { "stateFacts": [ "hasSize" ], "size": 2, "eTag": "47B43F0210344E272F338073C382C5955651C5E2", "elements": [ { "stateFacts": [ "Identifiable" ], "id": 530, "type": "PLV", "addressStr": "г Чебоксары, пр-кт Мира", "fiasCode": "bb5f4fab-64ea-4042-a61b-9b2bdb55442d", "flat": "1", "countryId": "RUS", "house": "1", "zipCode": "428022", "city": "Чебоксары", "street": "Мира", "region": "Чувашская Республика", "eTag": "3553085EBBC08CEBFD73957B7D5BAFDFDA096CCA" }, { "stateFacts": [ "Identifiable" ], "id": 15893, "type": "PRG", "addressStr": "г Чебоксары, пр-кт Мира", "fiasCode": "bb5f4fab-64ea-4042-a61b-9b2bdb55442d", "flat": "1", "countryId": "RUS", "house": "1", "zipCode": "428022", "city": "Чебоксары", "street": "Мира", "region": "Чувашская Республика", "eTag": "C90BE244DC0650255C9D3078C7C7EDEA8013BB6E" } ] }, "documents": { "stateFacts": [ "hasSize" ], "size": 2, "eTag": "E752C6CFC8CBAE112527BF2AA07CB0A173143065", "elements": [ { "stateFacts": [ "EntityRoot" ], "id": 3571, "type": "RF_PASSPORT", "vrfStu": "VERIFIED", "series": "5303", "number": "925695", "issueDate": "01.01.2006", "issueId": "006006", "issuedBy": "УФМС006", "eTag": "2E1F79E93B9DF6F5A579F95069630742D41C6AFB" }, { "stateFacts": [ "EntityRoot" ], "id": 21213, "type": "RF_DRIVING_LICENSE", "vrfStu": "NOT_VERIFIED", "series": "1222", "number": "884455", "issueDate": "01.09.2014", "expiryDate": "01.08.2024", "eTag": "E9D14F10321D0021A1267B8D363B22B102387735" } ] }, "vehicles": { "stateFacts": [ "hasSize" ], "size": 1, "eTag": "9D0855F880F882EBCFD93C329C4720D5DB4058D9", "elements": [ { "stateFacts": [ "Identifiable" ], "id": 17743, "name": "Моя птичка", "numberPlate": "А123АА111", "regCertificate": { "series": "1231", "number": "231231" }, "eTag": "A99823275D311CB97A371A420A59AA6BB08B42B7" } ] }, "status": "REGISTERED", "verifying": false, "rIdDoc": 3571, "containsUpCfmCode": false, "eTag": "61F2A6BF9D17B97E6B56F8B10EB28A7C814FF0B4" }
Testing
Node is used for interactive headless chrome auth bot.
vendor/bin/phpunit --debug
About ESIA
There are three ESIA user identification levels:
- simple
- standard
- confrimed
Information system can ask info about user from individuals register.
ESIA user could be:
- individual
- individual entrepreneur (individual + flag "is entrepreneur")
- individual connected to legal entities accounts
- individual connected to public authorities accounts
Users after individual can be only of confirmed identification level.
User info
After user's permission his/her info can be read through REST.
Scopes
To get some info about user system should ask it through "scope" param. Same param entered in paper-written application for connection to ESIA.
Scope is analog of permissions in mobile apps, but for user's data.
Here are list of possible scopes: fullname, birthdate, gender, snils, inn, id_doc, birthplace, medical_doc, military_doc, foreign_passport_doc, drivers_licence_doc, vehicles, email, mobile, contacts, kid_fullname.
Security algos
ESIA REST supports both RSA2048+SHA256 and GOST3410-2001+GOST341194 algos.
Authentication methods
There are two ways to authenticate user: SAML 2.0 and OpenID Connect 1.0 (OAuth 2.0 extension). SAML 2.0 is only for public authorities.
For legal entities OpenID Connect is used.
Terms
ESIA from Russian "ЕСИА", which is "Единая система идентификации и аутентификации". Translated as "Unified identification and authentication system".