diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..e026050 --- /dev/null +++ b/composer.json @@ -0,0 +1,45 @@ +{ + "name": "anwar/bankid", + "description": "BankID authentication and filesinging for laravel implementation from dimafi/\u001b[D6/bank-id", + "license": "MIT", + "homepage": "https://github.com/dimafe6/bank-id", + "homepage": "https://github.com/ringkubd/bankid", + "authors": [ + { + "name": "MD ANWAR JAHID", + "email": "ajr.jahid@gmail.com" + }, + { + "name": "Dmitry Feshchenko", + "email": "dimafe2000@gmail.com" + }, + { + "name": "Oleg Davudyuk", + "email": "ilveann@gmail.com" + }, + { + "name": "Anders Fajerson", + "email": "anders@perifer.se" + }, + { + "name": "Puggan", + "email": "puggan@spiro.se" + } + ], + "autoload": { + "psr-4": { + "Anwar\\": "src/" + } + }, + "require": { + "php" : ">=5.6.0", + "ext-soap":"*" + }, + "extra": { + "laravel": { + "providers": [ + "Anwar\\Bankid\\BankidServiceProvider" + ] + } + } +} diff --git a/src/BankidController.php b/src/BankidController.php new file mode 100644 index 0000000..b5cce46 --- /dev/null +++ b/src/BankidController.php @@ -0,0 +1,157 @@ + [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'allow_self_signed' => true, + ], + ]); + $options['stream_context'] = $context; + } + $this->wsdlUrl = $wsdlUrl; + $this->soapOptions = $options; + $this->client = new SoapClient($this->wsdlUrl, $this->soapOptions); + } + /** + * @return array + * @author Dmytro Feshchenko + */ + private function availableMethods() { + $class = new ReflectionClass(__CLASS__); + $constants = $class->getConstants(); + $results = array_filter($constants, function ($constant) { + return false !== strpos($constant, 'METHOD_'); + }, ARRAY_FILTER_USE_KEY); + return array_values($results); + } + /** + * @param $method + * @return bool + * @author Dmytro Feshchenko + */ + private function isMethodAvailable($method) { + return in_array($method, $this->availableMethods()); + } + /** + * @param string $method + * @param array $parameters + * @return mixed + * @author Dmytro Feshchenko + */ + public function soapCall($method, $parameters) { + return $this->client->__soapCall($method, $parameters); + } + /** + * @param string $method + * @param array $parameters + * @return mixed + * @throws \SoapFault + * @throws \OutOfBoundsException + * @author Dmytro Feshchenko + */ + public function call($method, $parameters) { + if (!$this->isMethodAvailable($method)) { + throw new OutOfBoundsException("Invalid method '$method'"); + } + if (!is_array($parameters)) { + throw new \InvalidArgumentException('parameters must be is an array'); + } + return $this->soapCall($method, $parameters); + } + /** + * @param $personalNumber + * @param $userVisibleData + * @param null $userHiddenData + * @return OrderResponse + */ + public function getSignResponse($personalNumber, $userVisibleData, $userHiddenData = null) { + $parameters = [ + 'personalNumber' => $personalNumber, + 'userVisibleData' => base64_encode($userVisibleData), + ]; + if (!empty($userHiddenData)) { + $parameters['userNonVisibleData'] = base64_encode($userHiddenData); + } + $options = ['parameters' => $parameters]; + $response = $this->call(self::METHOD_SIGN, $options); + $orderResponse = new OrderResponse(); + $orderResponse->orderRef = $response->orderRef; + $orderResponse->autoStartToken = $response->autoStartToken; + return $orderResponse; + } + /** + * @param $personalNumber + * @return OrderResponse + * @throws \SoapFault + */ + public function getAuthResponse($personalNumber) { + $parameters = [ + 'personalNumber' => $personalNumber, + ]; + $options = ['parameters' => $parameters]; + $response = $this->call(self::METHOD_AUTH, $options); + $orderResponse = new OrderResponse(); + $orderResponse->orderRef = $response->orderRef; + $orderResponse->autoStartToken = $response->autoStartToken; + return $orderResponse; + } + /** + * @param string $orderRef + * @return CollectResponse + * @throws \SoapFault + */ + public function collectResponse($orderRef) { + $response = $this->call(self::METHOD_COLLECT, ['orderRef' => $orderRef]); + $collect = new CollectResponse(); + $collect->progressStatus = $response->progressStatus; + if ($collect->progressStatus == CollectResponse::PROGRESS_STATUS_COMPLETE) { + $collect->userInfo = $response->userInfo; + $collect->signature = $response->signature; + $collect->ocspResponse = $response->ocspResponse; + } + return $collect; + } +} diff --git a/src/BankidController.php-tmp b/src/BankidController.php-tmp new file mode 100644 index 0000000..2be6d40 --- /dev/null +++ b/src/BankidController.php-tmp @@ -0,0 +1,157 @@ + [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'allow_self_signed' => true, + ], + ]); + $options['stream_context'] = $context; + } + $this->wsdlUrl = $wsdlUrl; + $this->soapOptions = $options; + $this->client = new SoapClient($this->wsdlUrl, $this->soapOptions); + } + /** + * @return array + * @author Dmytro Feshchenko + */ + private function availableMethods() { + $class = new ReflectionClass(__CLASS__); + $constants = $class->getConstants(); + $results = array_filter($constants, function ($constant) { + return false !== strpos($constant, 'METHOD_'); + }, ARRAY_FILTER_USE_KEY); + return array_values($results); + } + /** + * @param $method + * @return bool + * @author Dmytro Feshchenko + */ + private function isMethodAvailable($method) { + return in_array($method, $this->availableMethods()); + } + /** + * @param string $method + * @param array $parameters + * @return mixed + * @author Dmytro Feshchenko + */ + public function soapCall($method, $parameters) { + return $this->client->__soapCall($method, $parameters); + } + /** + * @param string $method + * @param array $parameters + * @return mixed + * @throws \SoapFault + * @throws \OutOfBoundsException + * @author Dmytro Feshchenko + */ + public function call($method, $parameters) { + if (!$this->isMethodAvailable($method)) { + throw new OutOfBoundsException("Invalid method '$method'"); + } + if (!is_array($parameters)) { + throw new \InvalidArgumentException('parameters must be is an array'); + } + return $this->soapCall($method, $parameters); + } + /** + * @param $personalNumber + * @param $userVisibleData + * @param null $userHiddenData + * @return OrderResponse + */ + public function getSignResponse($personalNumber, $userVisibleData, $userHiddenData = null) { + $parameters = [ + 'personalNumber' => $personalNumber, + 'userVisibleData' => base64_encode($userVisibleData), + ]; + if (!empty($userHiddenData)) { + $parameters['userNonVisibleData'] = base64_encode($userHiddenData); + } + $options = ['parameters' => $parameters]; + $response = $this->call(self::METHOD_SIGN, $options); + $orderResponse = new OrderResponse(); + $orderResponse->orderRef = $response->orderRef; + $orderResponse->autoStartToken = $response->autoStartToken; + return $orderResponse; + } + /** + * @param $personalNumber + * @return OrderResponse + * @throws \SoapFault + */ + public function getAuthResponse($personalNumber) { + $parameters = [ + 'personalNumber' => $personalNumber, + ]; + $options = ['parameters' => $parameters]; + $response = $this->call(self::METHOD_AUTH, $options); + $orderResponse = new OrderResponse(); + $orderResponse->orderRef = $response->orderRef; + $orderResponse->autoStartToken = $response->autoStartToken; + return $orderResponse; + } + /** + * @param string $orderRef + * @return CollectResponse + * @throws \SoapFault + */ + public function collectResponse($orderRef) { + $response = $this->call(self::METHOD_COLLECT, ['orderRef' => $orderRef]); + $collect = new CollectResponse(); + $collect->progressStatus = $response->progressStatus; + if ($collect->progressStatus == CollectResponse::PROGRESS_STATUS_COMPLETE) { + $collect->userInfo = $response->userInfo; + $collect->signature = $response->signature; + $collect->ocspResponse = $response->ocspResponse; + } + return $collect; + } +} diff --git a/src/BankidServiceProvider.php b/src/BankidServiceProvider.php new file mode 100644 index 0000000..dcde42d --- /dev/null +++ b/src/BankidServiceProvider.php @@ -0,0 +1,28 @@ +app->make('Anwar\Bankid\BankidController'); + $this->app->bind('BankID', function () { + return new BankidController; + }); + } +} diff --git a/src/BankidServiceProvider.php-tmp b/src/BankidServiceProvider.php-tmp new file mode 100644 index 0000000..ce6a810 --- /dev/null +++ b/src/BankidServiceProvider.php-tmp @@ -0,0 +1,28 @@ +app->make('Anwar\Bankid\BankidController'); + $this->app->bind('BankID', function () { + return new BankidController; + }); + } +} diff --git a/src/Facade.php b/src/Facade.php new file mode 100644 index 0000000..0b9f477 --- /dev/null +++ b/src/Facade.php @@ -0,0 +1,24 @@ + + */ +class CollectResponse { + const PROGRESS_STATUS_OUTSTANDING_TRANSACTION = 'OUTSTANDING_TRANSACTION'; + const PROGRESS_STATUS_NO_CLIENT = 'NO_CLIENT'; + const PROGRESS_STATUS_STARTED = 'STARTED'; + const PROGRESS_STATUS_USER_SIGN = 'USER_SIGN'; + const PROGRESS_STATUS_USER_REQ = 'USER_REQ'; + const PROGRESS_STATUS_COMPLETE = 'COMPLETE'; + /** + * @var string + */ + public $progressStatus; + /** + * String (b64). XML-signature. (If the order is COMPLETE). The content of the + * signature is described in BankID Signature Profile specification. + * + * @var string|null + */ + public $signature; + /** + * UserInfoType (If the order is COMPLETE) + * + * @var UserInfo|null + */ + public $userInfo; + /** + * String (b64). OCSP-response (If the order is COMPLETE). The OCSP response + * is signed by a certificate that has the same issuer as the certificate + * being verified. The OSCP response has an extension for Nonce. + * The nonce is calculated as: + * SHA-1 hash over the base 64 XML signature encoded as UTF-8. + * 12 random bytes is added after the hash + * The nonce is 32 bytes (20 + 12) + * + * @var string|null + */ + public $ocspResponse; +} \ No newline at end of file diff --git a/src/Helper/CollectResponse.php-tmp b/src/Helper/CollectResponse.php-tmp new file mode 100644 index 0000000..a1d59c3 --- /dev/null +++ b/src/Helper/CollectResponse.php-tmp @@ -0,0 +1,53 @@ + + */ +class CollectResponse { + const PROGRESS_STATUS_OUTSTANDING_TRANSACTION = 'OUTSTANDING_TRANSACTION'; + const PROGRESS_STATUS_NO_CLIENT = 'NO_CLIENT'; + const PROGRESS_STATUS_STARTED = 'STARTED'; + const PROGRESS_STATUS_USER_SIGN = 'USER_SIGN'; + const PROGRESS_STATUS_USER_REQ = 'USER_REQ'; + const PROGRESS_STATUS_COMPLETE = 'COMPLETE'; + /** + * @var string + */ + public $progressStatus; + /** + * String (b64). XML-signature. (If the order is COMPLETE). The content of the + * signature is described in BankID Signature Profile specification. + * + * @var string|null + */ + public $signature; + /** + * UserInfoType (If the order is COMPLETE) + * + * @var UserInfo|null + */ + public $userInfo; + /** + * String (b64). OCSP-response (If the order is COMPLETE). The OCSP response + * is signed by a certificate that has the same issuer as the certificate + * being verified. The OSCP response has an extension for Nonce. + * The nonce is calculated as: + * SHA-1 hash over the base 64 XML signature encoded as UTF-8. + * 12 random bytes is added after the hash + * The nonce is 32 bytes (20 + 12) + * + * @var string|null + */ + public $ocspResponse; +} \ No newline at end of file diff --git a/src/Helper/OrderResponse.php b/src/Helper/OrderResponse.php new file mode 100644 index 0000000..b6f6fde --- /dev/null +++ b/src/Helper/OrderResponse.php @@ -0,0 +1,26 @@ + + */ +class OrderResponse { + /** + * @var string + */ + public $orderRef; + /** + * @var string + */ + public $autoStartToken; +} \ No newline at end of file diff --git a/src/Helper/OrderResponse.php-tmp b/src/Helper/OrderResponse.php-tmp new file mode 100644 index 0000000..0b359bd --- /dev/null +++ b/src/Helper/OrderResponse.php-tmp @@ -0,0 +1,26 @@ + + */ +class OrderResponse { + /** + * @var string + */ + public $orderRef; + /** + * @var string + */ + public $autoStartToken; +} \ No newline at end of file diff --git a/src/Helper/UserInfo.php b/src/Helper/UserInfo.php new file mode 100644 index 0000000..771700d --- /dev/null +++ b/src/Helper/UserInfo.php @@ -0,0 +1,47 @@ + + * @author Anwar Jahid + */ +class UserInfo { + /** + * @var string + */ + public $givenName; + /** + * @var string + */ + public $surname; + /** + * @var string + */ + public $name; + /** + * @var string + */ + public $personalNumber; + /** + * @var string + */ + public $notBefore; + /** + * @var string + */ + public $notAfter; + /** + * @var string + */ + public $ipAddress; +} \ No newline at end of file diff --git a/src/Helper/UserInfo.php-tmp b/src/Helper/UserInfo.php-tmp new file mode 100644 index 0000000..0425e8e --- /dev/null +++ b/src/Helper/UserInfo.php-tmp @@ -0,0 +1,47 @@ + + * @author Anwar Jahid + */ +class UserInfo { + /** + * @var string + */ + public $givenName; + /** + * @var string + */ + public $surname; + /** + * @var string + */ + public $name; + /** + * @var string + */ + public $personalNumber; + /** + * @var string + */ + public $notBefore; + /** + * @var string + */ + public $notAfter; + /** + * @var string + */ + public $ipAddress; +} \ No newline at end of file