Create Multi-Factor Authentication methods

Edit on GitHub

This document describes how to create and implement Multi-Factor Authentication (MFA) methods.

To lean more about MFA methods, see Multi-Factor Authentication feature overview.

An MFA method consists of two components:

  • MFA type plugin
  • Code Sender Strategy plugin

Prerequisites

Install the Multi-Factor Authentication feature

1) Create an MFA type plugin

Create one of the following plugins depending on the application:

  • Yves: Implements \Spryker\Shared\MultiFactorAuthExtension\Dependency\Plugin\MultiFactorAuthPluginInterface and calls a client method
  • Zed: Resides in the Zed layer, implements \Spryker\Zed\MultiFactorAuthExtension\Dependency\Plugin\MultiFactorAuthTypePluginInterface, and delegates the logic through the Facade
Pyz\Yves\MultiFactorAuth\Plugin\Factors\YourMultiFactorAuthType\YourMfaTypePlugin.php
<?php

namespace Pyz\Yves\MultiFactorAuth\Plugin\Factors\YourMultiFactorAuthType;

use Generated\Shared\Transfer\CustomerMultiFactorAuthTypeTransfer;
use Generated\Shared\Transfer\CustomerTransfer;
use Spryker\Yves\Kernel\AbstractPlugin;
use Spryker\Shared\MultiFactorAuthExtension\Dependency\Plugin\MultiFactorAuthPluginInterface;

class YourMfaTypePlugin extends AbstractPlugin implements MultiFactorAuthPluginInterface
{
    /**
     * @var string
     */
    protected const YOUR_MULTI_FACTOR_AUTH_TYPE = 'your-multi-factor-auth-type';
    
    /**
     * {@inheritDoc}
     *
     * @api
     * 
     * @var string
     */
    public function getName(): string
    {
        return static::YOUR_MULTI_FACTOR_AUTH_TYPE;
    }
    
    /**
     * {@inheritDoc}
     *
     * @api
     *
     * @param string $multiFactorAuthMethod
     *
     * @return bool
     */
    public function isApplicable(string $multiFactorAuthMethod): bool
    {
        return $multiFactorAuthMethod === static::YOUR_MULTI_FACTOR_AUTH_TYPE;
    }

    /**
     * {@inheritDoc}
     *
     * @api
     *
     * @param \Generated\Shared\Transfer\MultiFactorAuthTransfer $multiFactorAuthTransfer
     *
     * @return void
     */
    public function sendCode(MultiFactorAuthTransfer $multiFactorAuthTransfer): void
    {
        $this->getClient()->sendCustomerCode($multiFactorAuthTransfer);
    }
}

2) Create a code sender strategy plugin

Create a sender strategy that implements \Spryker\Shared\MultiFactorAuthExtension\Dependency\Plugin\SendStrategyPluginInterface. Here’s an example based on the email implementation:

Pyz\Zed\MultiFactorAuth\Communication\Plugin\Sender\Customer\YourMfaCodeSenderStrategyPlugin.php
<?php

namespace Pyz\Zed\MultiFactorAuth\Communication\Plugin\Sender\Customer;

use Generated\Shared\Transfer\MultiFactorAuthTransfer;
use Spryker\Shared\MultiFactorAuthExtension\Dependency\Plugin\SendStrategyPluginInterface;
use Spryker\Zed\Kernel\Communication\AbstractPlugin;

class YourMfaCodeSenderStrategyPlugin extends AbstractPlugin implements SendStrategyPluginInterface
{
    /**
     * @var string
     */
    protected const YOUR_MFA_TYPE = 'your-multi-factor-auth-type';

    /**
     * @param \Generated\Shared\Transfer\MultiFactorAuthTransfer $multiFactorAuthTransfer
     *
     * @return bool
     */
    public function isApplicable(MultiFactorAuthTransfer $multiFactorAuthTransfer): bool
    {
        return $multiFactorAuthTransfer->getType() === static::YOUR_MFA_TYPE;
    }

    /**
     * @param \Generated\Shared\Transfer\MultiFactorAuthTransfer $multiFactorAuthTransfer
     *
     * @return \Generated\Shared\Transfer\MultiFactorAuthTransfer
     */
    public function send(MultiFactorAuthTransfer $multiFactorAuthTransfer): MultiFactorAuthTransfer
    {
        // Implement your code sending logic here
        // For example, send via SMS, authenticator app, etc.

        return $multiFactorAuthTransfer;
    }
}

3) Register the plugins

Register the plugins in the dependency providers:

  • Back Office users: Use the MultiFactorAuthDependencyProvider::getUserMultiFactorAuthPlugins() class in the Zed module
  • Agents: Use the MultiFactorAuthDependencyProvider::getAgentMultiFactorAuthPlugins() method
  • Universal plugin for all users: Use the MultiFactorAuthDependencyProvider::getUserSendStrategyPlugins() method

src/Pyz/Yves/MultiFactorAuth/MultiFactorAuthDependencyProvider.php

<?php

namespace Pyz\Yves\MultiFactorAuth;

use Spryker\Yves\MultiFactorAuth\MultiFactorAuthDependencyProvider as SprykerMultiFactorAuthDependencyProvider;

class MultiFactorAuthDependencyProvider extends SprykerMultiFactorAuthDependencyProvider
{
    /**
     * @return array<\Spryker\Zed\MultiFactorAuthExtension\Dependency\Plugin\MultiFactorAuthTypePluginInterface>
     */
    protected function getCustomerMultiFactorAuthPlugins(): array
    {
        return [
            // ... other plugins
            new YourMfaTypePlugin(),
        ];
    }
}

src/Pyz/Zed/MultiFactorAuth/MultiFactorAuthDependencyProvider.php

<?php

namespace Pyz\Zed\MultiFactorAuth;

use Spryker\Zed\MultiFactorAuth\MultiFactorAuthDependencyProvider as SprykerMultiFactorAuthDependencyProvider;

class MultiFactorAuthDependencyProvider extends SprykerMultiFactorAuthDependencyProvider
{
    /**
     * @return array<\Spryker\Shared\MultiFactorAuthExtension\Dependency\Plugin\SendStrategyPluginInterface>
     */
    protected function getCustomerSendStrategyPlugins(): array
    {
        return [
            new YourMfaCodeSenderStrategyPlugin(),
        ];
    }
}