Skip to content

Commit

Permalink
Merge pull request #1 from prestonchoate/feature/initial-module
Browse files Browse the repository at this point in the history
Initial commit
  • Loading branch information
prestonchoate authored Dec 1, 2021
2 parents 77ac335 + 7d936d7 commit a854d11
Show file tree
Hide file tree
Showing 10 changed files with 300 additions and 0 deletions.
50 changes: 50 additions & 0 deletions Model/Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
declare(strict_types=1);

namespace PrestonChoate\CardingPrevention\Model;

use Magento\Framework\App\Config\ScopeConfigInterface;

class Config
{
const CARDING_PREVENTION_ENABLED_CONFIG_PATH = 'carding_prevention/general/enabled';
const CARDING_PREVENTION_THRESHOLD_CONFIG_PATH = 'carding_prevention/general/threshold';

/** @var ScopeConfigInterface */
protected $scopeConfig;

/**
* Config constructor.
* @param ScopeConfigInterface $scopeConfig
*/
public function __construct(
ScopeConfigInterface $scopeConfig
) {
$this->scopeConfig = $scopeConfig;
}

/**
* @param string $scopeType
* @param null $scopeCode
* @return bool
*/
public function getEnabled($scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null): bool
{
return $this->scopeConfig->getValue(self::CARDING_PREVENTION_ENABLED_CONFIG_PATH, $scopeType, $scopeCode) ? true : false;
}

/**
* @param string $scopeType
* @param null $scopeCode
* @return string
*/
public function getThreshold($scopeType = ScopeConfigInterface::SCOPE_TYPE_DEFAULT, $scopeCode = null): string
{
return $this->scopeConfig->getValue(self::CARDING_PREVENTION_THRESHOLD_CONFIG_PATH, $scopeType, $scopeCode);
}
}
70 changes: 70 additions & 0 deletions Plugin/Magento/Checkout/Model/CardingPreventionPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
declare(strict_types=1);

namespace PrestonChoate\CardingPrevention\Plugin\Magento\Checkout\Model;
use PrestonChoate\CardingPrevention\Model\Config;
use Magento\Checkout\Model\GuestPaymentInformationManagement;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\Exception\AuthorizationException;
use Magento\Quote\Api\Data\AddressInterface;
use Magento\Quote\Api\Data\PaymentInterface;

class CardingPreventionPlugin
{
/** @var CacheInterface */
protected $cache;

/** @var Config */
protected $config;

/**
* CardingPreventionPlugin constructor.
* @param CacheInterface $cache
* @param Config $config
*/
public function __construct(
CacheInterface $cache,
Config $config
) {
$this->cache = $cache;
$this->config = $config;
}

/**
* @param GuestPaymentInformationManagement $subject
* @param $cartId
* @param $email
* @param PaymentInterface $paymentMethod
* @param AddressInterface|null $billingAddress
* @throws AuthorizationException
*/
public function beforeSavePaymentInformationAndPlaceOrder(
GuestPaymentInformationManagement $subject,
$cartId,
$email,
PaymentInterface $paymentMethod,
AddressInterface $billingAddress = null)
{
$lifetime = $this->config->getThreshold();
$lifetime = ctype_digit($lifetime) ? intval($lifetime) : 0;
if ($this->config->getEnabled() && $lifetime > 0) {
$data = 'cart id already used';
$tags = ['carding_prevention'];

// Check if cartId has been used to post a transaction in the last $threshold seconds
// then save this instance of that cartId being used and if a value was previously found
// then throw an exception to drop the connection
$value = $this->cache->load($cartId);
$this->cache->save($data, $cartId, $tags, $lifetime);
if ($value) {
throw new AuthorizationException(__('Too many requests'));
}

}
}
}
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# PrestonChoate CardingPrevention

```#bash
PrestonChoate/module-carding-prevention
```

- [Main Functionalities](#markdown-header-main-functionalities)
- [Installation](#markdown-header-installation)
- [Configuration](#markdown-header-configuration)
- [Specifications](#markdown-header-specifications)

## Main Functionalities

This module adds a plugin before `\Magento\Checkout\Model\GuestPaymentInformationManagement::savePaymentInformationAndPlaceOrder` that will log the used cart ID to the configured caching service (most likely redis). If that cart ID is used again within the configured threshold the transaction will be canceled.

## Installation

To install via Composer you need to add this repository to your Magneto project.

`composer config repositories.prestonchoate '{"type": "vcs","url": "[email protected]:prestonchoate/CardingModule.git"}'`

Then require the module with:

`composer require PrestonChoate/module-carding-prevention`

Finally run the following commands to fully install the module:

```#bash
bin/magento module:enable PrestonChoate_CardingModule
bin/magento setup:upgrade
bin/magento cache:flush
```

## Configuration

There are two configurations for this module. They both are located at Stores -> Configuration -> Security -> Carding Prevention

- General
- Enabled - This controls enabling and disabling the module as a whole
- Threshold
- This will set the number of seconds between requests that a user must wait to post another transaction with the same Cart ID

## Specifications

A model is supplied for retrieving configurations at `\PrestonChoate/CardingPrevention/Model/Config.php`.
The main plugin exists at `\PrestonChoate\CardingPrevention\Plugin\Magento\Checkout\Model\CardingPreventionPlugin`
13 changes: 13 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "prestonchoate/module-carding-prevention",
"description": "Module to prevent carding attacks at M2 checkout",
"minimum-stability": "stable",
"license": "GPL-3.0-or-later",
"require": {},
"autoload": {
"files": ["registration.php"],
"psr-4": {
"PrestonChoate\\CardingPrevention\\": ""
}
}
}
24 changes: 24 additions & 0 deletions etc/acl.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" ?>
<!--
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Acl/etc/acl.xsd">
<acl>
<resources>
<resource id="Magento_Backend::admin">
<resource id="Magento_Backend::stores">
<resource id="Magento_Backend::stores_settings">
<resource id="Magento_Config::config">
<resource id="PrestonChoate_CardingPrevention::config_prestonchoate_cardingprevention" title="carding_prevention"/>
</resource>
</resource>
</resource>
</resource>
</resources>
</acl>
</config>
32 changes: 32 additions & 0 deletions etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" ?>
<!--
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="carding_prevention" translate="label" type="text" sortOrder="700" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Carding Prevention</label>
<tab>security</tab>
<resource>PrestonChoate_CardingPrevention::config_prestonchoate_cardingprevention</resource>
<group id="general" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" translate="label">
<label>General Config</label>
<field id="enabled" translate="label" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1" type="select">
<label>Enable Carding Prevention</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="threshold" translate="label comment" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1" type="text">
<label>TTL For Transaction ID</label>
<comment>Number of seconds to hold onto a previously used transaction ID. If another transaction occurs with this same ID the transaction will be denied.</comment>
<validate>validate-number validate-digits validate-not-negative-number</validate>
<depends>
<field id="carding_prevention/general/enabled">1</field>
</depends>
</field>
</group>
</section>
</system>
</config>
18 changes: 18 additions & 0 deletions etc/config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" ?>
<!--
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<carding_prevention>
<general>
<enabled>0</enabled>
<threshold>60</threshold>
</general>
</carding_prevention>
</default>
</config>
17 changes: 17 additions & 0 deletions etc/di.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" ?>
<!--
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Checkout\Model\GuestPaymentInformationManagement">
<plugin name="PrestonChoate_Checkout_Carding_Prevention"
sortOrder="10"
type="PrestonChoate\CardingPrevention\Plugin\Magento\Checkout\Model\CardingPreventionPlugin"
disabled="false"/>
</type>
</config>
16 changes: 16 additions & 0 deletions etc/module.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" ?>
<!--
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="PrestonChoate_CardingPrevention" setup_version="1.0.0">
<sequence>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
14 changes: 14 additions & 0 deletions registration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* @package PrestonChoate/CardingPrevention
* @author Preston Choate <[email protected]>
* @copyright Copyright © 2021. All rights reserved.
*/
declare(strict_types=1);
use Magento\Framework\Component\ComponentRegistrar;

ComponentRegistrar::register(
ComponentRegistrar::MODULE,
'PrestonChoate_CardingPrevention',
__DIR__
);

0 comments on commit a854d11

Please sign in to comment.