SalesforceAuthorization::handle()   A
last analyzed

Complexity

Conditions 4
Paths 14

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 14
nop 1
dl 0
loc 16
ccs 10
cts 10
cp 1
crap 4
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
namespace DMT\Salesforce\Auth\Authorization;
4
5
use DMT\Auth\AuthorizationException;
6
use DMT\Auth\AuthorizationInterface;
7
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
8
use Psr\Http\Message\RequestInterface;
9
use Psr\SimpleCache\CacheInterface;
10
use Psr\SimpleCache\InvalidArgumentException;
11
use Stevenmaguire\OAuth2\Client\Provider\Salesforce;
12
use Stevenmaguire\OAuth2\Client\Token\AccessToken;
13
14
/**
15
 * Class SalesforceAuthorization
16
 *
17
 * @package DMT\Salesforce\Auth
18
 */
19
class SalesforceAuthorization implements AuthorizationInterface
20
{
21
    /**
22
     * @static string The key where the access token is stored for later use.
23
     */
24
    const CACHE_KEY = 'salesforce_access_token';
25
26
    /**
27
     * @static int Salesforce does not say when token expires, it is set to 1 hour for now.
28
     */
29
    const CACHE_TTL = 3600;
30
31
    /**
32
     * @var Salesforce
33
     */
34
    protected $provider;
35
36
    /**
37
     * @var array
38
     */
39
    protected $credentials;
40
41
    /**
42
     * @var CacheInterface|null
43
     */
44
    protected $cache;
45
46
    /**
47
     * SalesforceAuthorization constructor.
48
     *
49
     * @param Salesforce $provider
50
     * @param string $username The username of the user to logon.
51
     * @param string $password The password appended by the securityToken for the user.
52
     * @param CacheInterface|null $cache
53
     */
54 10
    public function __construct(Salesforce $provider, string $username, string $password, CacheInterface $cache = null)
55
    {
56 10
        $this->provider = $provider;
57 10
        $this->credentials = compact('username', 'password');
58 10
        $this->cache = $cache;
59 10
    }
60
61
    /**
62
     * Get a request with the headers associated with the authorization.
63
     *
64
     * @param RequestInterface $request
65
     *
66
     * @return RequestInterface
67
     * @throws AuthorizationException
68
     * @throws InvalidArgumentException
69
     */
70 10
    public function handle(RequestInterface $request): RequestInterface
71
    {
72
        try {
73 10
            $accessToken = $this->fetchAccessTokenFromCache() ?? $this->fetchAccessToken();
74
75 4
            $endPoint = parse_url($accessToken->getInstanceUrl(), PHP_URL_HOST);
76
77 4
            if ($endPoint !== $request->getUri()->getHost()) {
78 4
                $request = $request->withUri($request->getUri()->withHost($endPoint));
79
            }
80
81 4
            return $request->withHeader('Authorization', sprintf('Bearer %s', $accessToken));
82 6
        } catch (InvalidArgumentException $exception) {
83 3
            throw $exception;
84 3
        } catch (\Throwable $exception) {
85 3
            throw new AuthorizationException("Authentication failed: " . $exception->getMessage(), 0, $exception);
86
        }
87
    }
88
89
    /**
90
     * Get AccessToken using the grant_type password flow.
91
     *
92
     * @return AccessToken
93
     * @throws IdentityProviderException
94
     * @throws InvalidArgumentException
95
     * @throws \UnexpectedValueException
96
     */
97 7
    protected function fetchAccessToken(): AccessToken
98
    {
99
        /** @var AccessToken $accessToken */
100 7
        $accessToken = $this->provider->getAccessToken('password', $this->credentials);
101
102 4
        if ($this->cache !== null) {
103 3
            $this->cache->set(static::CACHE_KEY, json_encode($accessToken), static::CACHE_TTL);
104
        }
105
106 3
        return $accessToken;
107
    }
108
109
    /**
110
     * Get a access token from cache.
111
     *
112
     * @return null|AccessToken
113
     * @throws InvalidArgumentException
114
     */
115 10
    protected function fetchAccessTokenFromCache(): ?AccessToken
116
    {
117
        try {
118 10
            if ($this->cache !== null && $this->cache->has(static::CACHE_KEY)) {
119 9
                return new AccessToken(json_decode($this->cache->get(static::CACHE_KEY), true));
120
            }
121 3
        } catch (\InvalidArgumentException $exception) {
122
            // The cache will be corrected when the AccessToken is retrieved
123
        }
124
125 7
        return null;
126
    }
127
}
128