Thursday 28 March 2019

Signature

security:
    # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
    providers:
        in_memory: { memory: ~ }
        api_key_user_provider:
            id: App\Security\ApiUserProvider
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
           
        api_firewall:
            pattern: ^/(.*)
            stateless: true
            simple_preauth:
                authenticator: App\Security\ApiAuthenticator
            provider: api_key_user_provider
        # main:
            # anonymous: true
           

            # activate different ways to authenticate

            # http_basic: true
            # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate

            # form_login: true
            # https://symfony.com/doc/current/security/form_login_setup.html

    # Easy way to control access for large sections of your site
    # Note: Only the *first* access control that matches will be used
    access_control:
        # - { path: ^/admin, roles: ROLE_ADMIN }
        # - { path: ^/profile, roles: ROLE_USER }




<?php
namespace App\Security;

use Symfony\Component\Security\Http\Authentication\SimplePreAuthenticatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\PreAuthenticatedToken;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use App\Security\ApiUserProvider;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\ORM\EntityManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;

class ApiAuthenticator implements SimplePreAuthenticatorInterface
{
    /* protected $userProvider;
    protected $em;
    protected $container; */

    /* public function __construct(ApiUserProvider $userProvider, EntityManager $em, ContainerInterface $container)
    {
        $this->userProvider = $userProvider;
        $this->em = $em;
        $this->container = $container;
    } */

    public function createToken(Request $request, $providerKey)
    {
        $route = $request->get("_route");
        if((strpos($route, 'nelmio_api_doc_index') !== false) || $route == "app.swagger" || $route == "app.swagger_ui") {
            $token = "anonymous";
        }else{
            $signature = $request->headers->get('Signature');
            $timeStamp = $request->headers->get('Timestamp');
           
            $token = $request->headers->get('Token');
           
            if (!isset($token)) {
                $token = "anonymous";
            }
           
            if (!$signature || !$timeStamp) {
                throw new HttpException(Response::HTTP_BAD_REQUEST, "Missing Mandatory  Parameters in header");
            }
           
            $privateKey = '765022d2f23b3ae5b24abcc6a165449dff002ee16080b232cb4119a449e4aa70';// $this->container->getParameter('app_private_key');
            if(!$privateKey) {
                throw new HttpException(Response::HTTP_BAD_REQUEST, "Missing PrivateKey Parameters");
            }
           
            $generatedSignature = $this->generateSignature($privateKey, $timeStamp);
            if($signature != $generatedSignature) {
                throw new HttpException(Response::HTTP_BAD_REQUEST, "Invalid Signature");
            }
        }
       
        return new PreAuthenticatedToken(
                'anon.',
                $token,
                $providerKey
        );
    }

    public function authenticateToken(TokenInterface $token, UserProviderInterface $userProvider, $providerKey)
    {
        $apiKey = $token->getCredentials();
       
        if (!$userProvider instanceof ApiUserProvider) {
            throw new \InvalidArgumentException(
                sprintf(
                    'The user provider must be an instance of ApiKeyUserProvider (%s was given).',
                    get_class($userProvider)
                    )
                );
        }
        $user = $userProvider->loadUserByUsername($apiKey);

        return new PreAuthenticatedToken(
                $user,
                $apiKey,
                $providerKey,
                $user->getRoles()
        );
    }

    public function supportsToken(TokenInterface $token, $providerKey)
    {
        return $token instanceof PreAuthenticatedToken && $token->getProviderKey() === $providerKey;
    }
   
    public function generateSignature($privateKey, $timeStamp)
    {
        return urlencode(base64_encode(hash_hmac('sha256', $timeStamp.$privateKey, $privateKey, true)));
    }
}




<?php
namespace App\Security;

use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\User;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;

class ApiUserProvider implements UserProviderInterface
{
    private $em;
   
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function loadUserByUsername($username)
    {
        if($username == 'anonymous') {
            return new User(
                    $username,
                    null,
                    array('IS_AUTHENTICATED_ANONYMOUSLY')
            );
        }
       
        $request = Request::createFromGlobals();
        $api = explode("/", $request->getPathInfo());
        if (isset($api) && $api['1'] == "customerapi") {
            return $this->em->getRepository('AppBundle:CustomerReg')->loadUserByAuthToken($username);
        }
       
    }

    public function refreshUser(UserInterface $user)
    {
        throw new UnsupportedUserException();
    }

    public function supportsClass($class)
    {
        return ('Symfony\Component\Security\Core\User\User' === $class || 'AppBundle\Entity\CustomerReg' === $class);
    }
}

No comments:

Post a Comment