ESIA Provider for OAuth 2.0 Client
, (*1)
Allows to authenticate in ESIA and get authenticated individual personal information., (*2)
Implemented as adapter to the PHP League's OAuth 2.0 Client., (*3)
Installing
To install, use composer:, (*4)
composer require ekapusta/oauth2-esia
Usage
Usage is the same as the normal client, using Ekapusta\OAuth2Esia\Provider\EsiaProvider
as the provider:, (*5)
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 has toolpath
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 to openssl
tool. For dockers pass to it something like docker 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., (*6)
// 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., (*7)
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., (*8)
vendor/bin/phpunit --debug
About ESIA
There are three ESIA user identification levels:, (*9)
- simple
- standard
- confrimed
Information system can ask info about user from individuals register., (*10)
ESIA user could be:, (*11)
- 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., (*12)
User info
After user's permission his/her info can be read through REST., (*13)
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., (*14)
Scope is analog of permissions in mobile apps, but for user's data., (*15)
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., (*16)
Security algos
ESIA REST supports both RSA2048+SHA256 and GOST3410-2001+GOST341194 algos., (*17)
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., (*18)
For legal entities OpenID Connect is used., (*19)
Terms
ESIA from Russian "ΠΠ‘ΠΠ", which is "ΠΠ΄ΠΈΠ½Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ ΠΈ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ".
Translated as "Unified identification and authentication system"., (*20)
Links
-
ΠΠ΄ΠΈΠ½Π°Ρ ΡΠΈΡΡΠ΅ΠΌΠ° ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ ΠΈ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ
- Methodical recommendations