Completed
Push — master ( 608d8b...b7ceed )
by Tharanga
06:16
created

authenticate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 17
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 30-12-2018
5
 *
6
 * This is similar to the Default version. But this also stores the vendor token user details in a given storage by mapping the client application user record.
7
 * use this if you want to connect & use multiple vendor login such as Facebook and/or Google.
8
 */
9
10
namespace TSK\SSO\Auth;
11
12
use TSK\SSO\AppUser\AppUser;
13
use TSK\SSO\AppUser\ExistingAppUser;
14
use TSK\SSO\Storage\Exception\DataCannotBeStoredException;
15
use TSK\SSO\Storage\FileSystemThirdPartyStorageRepository;
16
use TSK\SSO\Storage\ThirdPartyStorageRepository;
17
use TSK\SSO\ThirdParty\Exception\NoThirdPartyEmailFoundException;
18
use TSK\SSO\ThirdParty\Exception\ThirdPartyConnectionFailedException;
19
use TSK\SSO\ThirdParty\VendorConnection;
20
21
/**
22
 * @package TSK\SSO\Auth
23
 * @see PersistingAuthenticator
24
 *
25
 * Use this to validate and connect other accounts belong to the same vendor.
26
 * You need to use PersistingAuthenticator when the user is NOT logged in yet.
27
 *
28
 * ex: A user can have three(3) Google Mail accounts.
29
 *
30
 * You may want to let users connect the rest of their account while they are LOGGED IN (aka user aware).
31
 */
32
class AppUserAwarePersistingAuthenticator implements Authenticator
33
{
34
    /**
35
     * @var AppUser
36
     */
37
    private $appUser;
38
39
    /**
40
     * @var ThirdPartyStorageRepository
41
     */
42
    private $storageRepository;
43
44
    /**
45
     * @param AppUser $appUser client application user which can be used to connect multiple other vendor accounts.
46
     * @param ThirdPartyStorageRepository $storageRepository a storage implementation to store the third party auth
47
     *        data. By default uses file system as the storage.
48
     */
49
    public function __construct(AppUser $appUser, ThirdPartyStorageRepository $storageRepository = null)
50
    {
51
        $this->appUser = $appUser;
52
        $this->storageRepository = is_null($storageRepository)
53
            ? new FileSystemThirdPartyStorageRepository()
54
            : $storageRepository;
55
    }
56
57
    /**
58
     * This will try to authenticate a user using any given vendor connection.
59
     * Upon a successful attempt, returns the authenticated user.
60
     *
61
     * @param VendorConnection $thirdPartyConnection vendor connection to use to perform an auth
62
     * @return AppUser
63
     *
64
     * @throws DataCannotBeStoredException
65
     * @throws NoThirdPartyEmailFoundException
66
     * @throws ThirdPartyConnectionFailedException
67
     */
68
    public function authenticate(VendorConnection $thirdPartyConnection)
69
    {
70
        $accessToken = $thirdPartyConnection->grantNewAccessToken();
71
72
        $thirdPartyUser = $thirdPartyConnection->getSelf($accessToken);
73
74
        /**
75
         * Resolving a new app user by taking
76
         *  - the known user's application id
77
         *  - and the incoming new vendor account's email
78
         */
79
        $derivedAppUser = new ExistingAppUser($this->appUser->id(), $thirdPartyUser->email());
80
81
        // Let's store this new third party user mapping against the existing user
82
        $this->storageRepository->save($derivedAppUser, $thirdPartyUser, $accessToken);
83
84
        return $derivedAppUser;
85
    }
86
}
87