<?php
namespace Abap\LoginGovBundle\Service;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
class LoginGovClient
{
/**
* @var array
*/
private $config;
public function __construct(ParameterBagInterface $params)
{
$this->config = $this->prepareConfig($params);
}
public function getSAMLRequest(): string
{
$process = new Process(explode(' ', $this->prepareAuthnRequestCommand()));
$process->setWorkingDirectory($this->config['connector_app_dir']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
return $process->getOutput();
}
public function getSSOUrl()
{
return $this->config['sso_login_url'];
}
public function artifactResolve($artifact): array
{
$process = new Process(explode(' ', $this->prepareArtifactResolveCommand($artifact)));
$process->setWorkingDirectory($this->config['connector_app_dir']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
$saml = $process->getOutput();
$parser = new SimpleLoginGovParser($saml);
$error = $parser->getResponseErrorForArtifactResponseIfPresent();
if (count($error)) {
return [
'saml' => $saml,
'error' => $error,
];
}
return [
'saml' => $saml,
'data' => array_merge(
$parser->getAssertionAttributesForArtifactResponse(),
$parser->getNameIdAndSessionIndexForArtifactResponse()
),
];
}
public function sendLogoutRequest($nameId, $sessionIndex): bool
{
$process = new Process(explode(' ', $this->prepareLogoutRequestCommand($nameId, $sessionIndex)));
$process->setWorkingDirectory($this->config['connector_app_dir']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
$xmlContent = $process->getOutput();
$xmlContent = trim(preg_replace('/\s\s+/', ' ', $xmlContent));
return (bool) preg_match('/<saml2p:StatusCode.+Success"\/>/i', $xmlContent);
}
public function sendAddDocumentToSigningRequest($documentXmlPath, $successUrl, $failureUrl): string
{
$process = new Process(explode(' ', $this->prepareAddDocumentToSigningRequestCommand($documentXmlPath, $successUrl, $failureUrl)));
$process->setWorkingDirectory($this->config['connector_app_dir']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
$xmlContent = $process->getOutput();
$xmlContent = trim(preg_replace('/\s\s+/', ' ', $xmlContent));
return $xmlContent;
}
public function sendGetSignedDocumentRequest($documentId, $documentXmlPath): string
{
$process = new Process(explode(' ', $this->prepareGetSignedDocumentRequestCommand($documentId, $documentXmlPath)));
$process->setWorkingDirectory($this->config['connector_app_dir']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
$xmlContent = $process->getOutput();
$xmlContent = trim(preg_replace('/\s\s+/', ' ', $xmlContent));
return $xmlContent;
}
public function sendEpuapDocument(string $fileToSend, ?string $additionalData = null, bool $isProbing = false, string $outputFormat = 'xml', ?string $documentFileName = null): string
{
$process = new Process(explode(' ', $this->prepareEpuapDocumentSendCommand($fileToSend, $additionalData, $isProbing, $outputFormat, $documentFileName)));
$process->setWorkingDirectory($this->config['connector_app_dir']);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
return $process->getOutput();
}
private function prepareAuthnRequestCommand(): string
{
$command = 'java -jar ' . $this->config['connector_app_jar'];
$command .= ' -sks ' . $this->config['sig_keystore_path'];
$command .= ' -sksp ' . $this->config['sksp'];
$command .= ' -o AuthnRequest';
$command .= ' -acs ' . $this->config['acs'];
$command .= ' -ds ' . $this->config['authn_request_ds'];
$command .= ' -is ' . $this->config['is'];
if(array_key_exists('provider_name', $this->config) && $this->config['provider_name']) {
$command .= ' -pn ' . $this->config['provider_name'];
}
$command .= ' -of base64';
// $command .= ' -l';
return $command;
}
private function prepareArtifactResolveCommand($artifact): string
{
$command = 'java -jar ' . $this->config['connector_app_jar'];
$command .= ' -sks ' . $this->config['sig_keystore_path'];
$command .= ' -sksp ' . $this->config['sksp'];
$command .= ' -eks ' . $this->config['enc_keystore_path'];
$command .= ' -eksp ' . $this->config['eksp'];
$command .= ' -o ArtifactResolve';
$command .= ' -ds ' . $this->config['artifact_resolve_ds'];
$command .= ' -is ' . $this->config['is'];
$command .= ' -af ' . $artifact;
$command .= ' -of xml';
// $command .= ' -l';
return $command;
}
private function prepareLogoutRequestCommand($nameId, $sessionIndex): string
{
$command = 'java -jar ' . $this->config['connector_app_jar'];
$command .= ' -sks ' . $this->config['sig_keystore_path'];
$command .= ' -sksp ' . $this->config['sksp'];
$command .= ' -o LogoutRequest';
$command .= ' -is ' . $this->config['is'];
$command .= ' -ds ' . $this->config['logout_request_ds'];
$command .= ' -ni ' . $nameId;
$command .= ' -si ' . $sessionIndex;
$command .= ' -of xml';
// $command .= ' -l';
return $command;
}
private function prepareAddDocumentToSigningRequestCommand($documentXmlPath, $successUrl, $failureUrl): string
{
$javaOpts = '--add-exports=java.xml.crypto/org.jcp.xml.dsig.internal.dom=ALL-UNNAMED -Dfile.encoding=utf-8';
$command = 'java ' . $javaOpts . ' -jar ' . $this->config['connector_app_jar'];
$command .= ' -sks ' . $this->config['epuap_keystore_path'];
$command .= ' -sksp ' . $this->config['epuap_keystore_password'];
$command .= ' -o AddDocumentToSigning';
$command .= ' -ds ' . $this->config['adddocumenttosigning_request_ds'];
$command .= ' -fts ' . $documentXmlPath;
$command .= ' -su ' . $successUrl;
$command .= ' -fu ' . $failureUrl;
$command .= ' -of xml';
//$command .= ' -l';
return $command;
}
private function prepareGetSignedDocumentRequestCommand($documentId, $documentXmlPath): string
{
$javaOpts = '--add-exports=java.xml.crypto/org.jcp.xml.dsig.internal.dom=ALL-UNNAMED -Dfile.encoding=utf-8';
$command = 'java ' . $javaOpts . ' -jar ' . $this->config['connector_app_jar'];
$command .= ' -sks ' . $this->config['epuap_keystore_path'];
$command .= ' -sksp ' . $this->config['epuap_keystore_password'];
$command .= ' -o GetSignedDocument';
$command .= ' -ds ' . $this->config['getsigneddocument_request_ds'];
$command .= ' -di ' . $documentId;
$command .= ' -wsf ' . $documentXmlPath;
$command .= ' -of xml';
//$command .= ' -l';
return $command;
}
private function prepareAddDocumentToSigning(string $unsignedXmlDocumentPath): string
{
$javaOpts = '--add-exports=java.xml.crypto/org.jcp.xml.dsig.internal.dom=ALL-UNNAMED -Dfile.encoding=utf-8';
$command = 'java ' . $javaOpts . ' -jar ' . $this->config['connector_app_jar'];
$command .= ' -ll ';
$command .= ' -sks ' . $this->config['epuap_keystore_path'];
$command .= ' -sksp ' . $this->config['epuap_keystore_password'];
$command .= ' -o AddDocumentToSigning';
$command .= ' -ds ' . $this->config['authn_request_ds'];
$command .= ' -is ' . $this->config['is'];
$command .= ' -id ' . $unsignedXmlDocumentPath;
$command .= ' -of xml';
//$command .= ' -l';
return $command;
}
private function prepareEpuapDocumentSendCommand(string $fileToSend, ?string $additionalData, bool $isProbing, string $outputFormat, ?string $documentFileName = null): string
{
$javaOpts = '--add-exports=java.xml.crypto/org.jcp.xml.dsig.internal.dom=ALL-UNNAMED -Dfile.encoding=utf-8';
$command = 'java ' . $javaOpts . ' -jar ' . $this->config['connector_app_jar'];
$command .= ' -o EpuapDocumentSend';
// Użyj alternatywnej konfiguracji keystore jeśli jest zdefiniowana, w przeciwnym razie użyj standardowej
$keystorePath = !empty($this->config['epuapdocumentsend_keystore_path'])
? $this->config['epuapdocumentsend_keystore_path']
: $this->config['epuap_keystore_path'];
$keystorePassword = !empty($this->config['epuapdocumentsend_keystore_password'])
? $this->config['epuapdocumentsend_keystore_password']
: $this->config['epuap_keystore_password'];
$payload = [
'sig_keystore' => $keystorePath,
'sig_keystore_password' => $keystorePassword,
'endpoint_url' => $this->config['epuapdocumentsend_endpoint_url'],
'address_from' => $this->config['epuapdocumentsend_address_from'],
'address_to' => $this->config['epuapdocumentsend_address_to'],
'provider_id' => $this->config['epuapdocumentsend_provider_id'],
'file_to_send' => $fileToSend,
'output_format' => $outputFormat,
];
if ($additionalData !== null) {
$payload['additional_data'] = $additionalData;
}
if ($isProbing) {
$payload['is_probing'] = true;
}
if ($documentFileName !== null) {
$payload['file_name'] = $documentFileName;
}
$jsonPayload = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
if ($jsonPayload === false) {
throw new \RuntimeException('Unable to encode ePUAP document send payload as JSON.');
}
$command .= ' -p ' . base64_encode($jsonPayload);
return $command;
}
private function prepareConfig(ParameterBagInterface $params)
{
$projectDir = $params->get('kernel.project_dir');
$config = $params->get('abap_login_gov.client_config', []);
array_walk($config, function (&$item) use ($projectDir) {
$item = str_replace('%kernel.project_dir%', $projectDir, $item);
});
return $config;
}
}