Completed
Push — master ( fc9832...a3f12b )
by Flo
02:20
created

Csrf::_getSessionManager()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Faulancer\Security;
4
5
use Faulancer\Exception\ServiceNotFoundException;
6
use Faulancer\Service\SessionManagerService;
7
use Faulancer\ServiceLocator\ServiceInterface;
8
use Faulancer\ServiceLocator\ServiceLocator;
9
10
/**
11
 * Class Csrf
12
 *
13
 * @package Faulancer\Security
14
 * @author Florian Knapp <[email protected]>
15
 */
16
class Csrf
17
{
18
    /**
19
     * Generates a token and save it to session
20
     *
21
     * @param string $identifier
22
     *
23
     * @return string
24
     *
25
     * @throws ServiceNotFoundException
26
     */
27
    public static function getToken(string $identifier = '') :string
28
    {
29
        $token = self::_getSessionManager()->get('csrf' . $identifier);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Faulancer\ServiceLocator\ServiceInterface as the method get() does only exist in the following implementations of said interface: Faulancer\Service\SessionManagerService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
30
31
        if (!self::_getSessionManager()->has('csrf' . $identifier)) {
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Faulancer\ServiceLocator\ServiceInterface as the method has() does only exist in the following implementations of said interface: Faulancer\Service\SessionManagerService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
32
            $token = bin2hex(openssl_random_pseudo_bytes(16));
33
            self::saveToSession($token, $identifier);
34
        }
35
36
        return $token;
37
    }
38
39
    /**
40
     * Check if token is valid
41
     *
42
     * @param string $token
43
     * @param string $identifier
44
     *
45
     * @return bool
46
     *
47
     * @throws ServiceNotFoundException
48
     */
49
    public static function isValid(string $token, string $identifier = '') :bool
50
    {
51
        $sessionToken = self::_getSessionManager()->get('csrf' . $identifier);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Faulancer\ServiceLocator\ServiceInterface as the method get() does only exist in the following implementations of said interface: Faulancer\Service\SessionManagerService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
52
        $isValid      = $token === $sessionToken;
53
54
        if ($isValid) {
55
            self::_getSessionManager()->delete('csrf' . $identifier);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Faulancer\ServiceLocator\ServiceInterface as the method delete() does only exist in the following implementations of said interface: Faulancer\Service\SessionManagerService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
56
            return true;
57
        }
58
59
        return false;
60
    }
61
62
    /**
63
     * Saves token into session
64
     *
65
     * @param string $token
66
     * @param string $identifier
67
     *
68
     * @return void
69
     *
70
     * @throws ServiceNotFoundException
71
     */
72
    private static function saveToSession(string $token, string $identifier = '')
73
    {
74
        self::_getSessionManager()->set('csrf' . $identifier, $token);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Faulancer\ServiceLocator\ServiceInterface as the method set() does only exist in the following implementations of said interface: Faulancer\Service\SessionManagerService.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
75
    }
76
77
    /**
78
     * @return SessionManagerService|ServiceInterface
79
     *
80
     * @throws ServiceNotFoundException
81
     */
82
    private static function _getSessionManager()
83
    {
84
        return ServiceLocator::instance()->get(SessionManagerService::class);
0 ignored issues
show
Bug Compatibility introduced by
The expression \Faulancer\ServiceLocato...ManagerService::class); of type Faulancer\ServiceLocator...ocator\FactoryInterface adds the type Faulancer\ServiceLocator\FactoryInterface to the return on line 84 which is incompatible with the return type documented by Faulancer\Security\Csrf::_getSessionManager of type Faulancer\ServiceLocator\ServiceInterface.
Loading history...
85
    }
86
87
}