1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Srmklive\Authy\Services; |
4
|
|
|
|
5
|
|
|
use Exception; |
6
|
|
|
use GuzzleHttp\Client as HttpClient; |
7
|
|
|
use Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable as TwoFactorAuthenticatable; |
8
|
|
|
use Srmklive\Authy\Contracts\Auth\TwoFactor\PhoneToken as SendPhoneTokenContract; |
9
|
|
|
use Srmklive\Authy\Contracts\Auth\TwoFactor\Provider as BaseProvider; |
10
|
|
|
use Srmklive\Authy\Contracts\Auth\TwoFactor\SMSToken as SendSMSTokenContract; |
11
|
|
|
|
12
|
|
|
class Authy implements BaseProvider, SendSMSTokenContract, SendPhoneTokenContract |
13
|
|
|
{ |
14
|
|
|
use CanSendToken; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Array containing configuration data. |
18
|
|
|
* |
19
|
|
|
* @var array |
20
|
|
|
*/ |
21
|
|
|
private $config; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Authy constructor. |
25
|
|
|
*/ |
26
|
|
|
public function __construct() |
27
|
|
|
{ |
28
|
|
|
if (!empty(config('authy.mode')) && (config('authy.mode') == 'sandbox')) { |
29
|
|
|
$this->config['api_key'] = config('authy.sandbox.key'); |
30
|
|
|
$this->config['api_url'] = 'http://sandbox-api.authy.com'; |
31
|
|
|
} else { |
32
|
|
|
$this->config['api_key'] = config('authy.live.key'); |
33
|
|
|
$this->config['api_url'] = 'https://api.authy.com'; |
34
|
|
|
} |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Determine if the given user has two-factor authentication enabled. |
39
|
|
|
* |
40
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
41
|
|
|
* |
42
|
|
|
* @return bool |
43
|
|
|
*/ |
44
|
|
|
public function isEnabled(TwoFactorAuthenticatable $user) |
45
|
|
|
{ |
46
|
|
|
return isset($user->getTwoFactorAuthProviderOptions()['id']); |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Register the given user with the provider. |
51
|
|
|
* |
52
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
53
|
|
|
* @param bool $sms |
54
|
|
|
* |
55
|
|
|
* @return void |
56
|
|
|
*/ |
57
|
|
|
public function register(TwoFactorAuthenticatable $user, $sms = false) |
58
|
|
|
{ |
59
|
|
|
$response = json_decode((new HttpClient())->post($this->config['api_url'].'/protected/json/users/new?api_key='.$this->config['api_key'], [ |
60
|
|
|
'form_params' => [ |
61
|
|
|
'user' => [ |
62
|
|
|
'email' => $user->getEmailForTwoFactorAuth(), |
63
|
|
|
'cellphone' => preg_replace('/[^0-9]/', '', $user->getAuthPhoneNumber()), |
64
|
|
|
'country_code' => $user->getAuthCountryCode(), |
65
|
|
|
], |
66
|
|
|
], |
67
|
|
|
])->getBody(), true); |
68
|
|
|
|
69
|
|
|
$user->setTwoFactorAuthProviderOptions([ |
70
|
|
|
'id' => $response['user']['id'], |
71
|
|
|
'sms' => $sms, |
72
|
|
|
]); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Send the user two-factor authentication token via SMS. |
77
|
|
|
* |
78
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
79
|
|
|
* |
80
|
|
|
* @return void |
81
|
|
|
*/ |
82
|
|
View Code Duplication |
public function sendSmsToken(TwoFactorAuthenticatable $user) |
|
|
|
|
83
|
|
|
{ |
84
|
|
|
try { |
85
|
|
|
$options = $user->getTwoFactorAuthProviderOptions(); |
86
|
|
|
|
87
|
|
|
$response = json_decode((new HttpClient())->get( |
88
|
|
|
$this->config['api_url'].'/protected/json/sms/'.$options['id']. |
89
|
|
|
'?force=true&api_key='.$this->config['api_key'] |
90
|
|
|
)->getBody(), true); |
91
|
|
|
|
92
|
|
|
return $response['success'] === true; |
93
|
|
|
} catch (Exception $e) { |
94
|
|
|
return false; |
95
|
|
|
} |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Start the user two-factor authentication via phone call. |
100
|
|
|
* |
101
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
102
|
|
|
* |
103
|
|
|
* @return void |
104
|
|
|
*/ |
105
|
|
View Code Duplication |
public function sendPhoneCallToken(TwoFactorAuthenticatable $user) |
|
|
|
|
106
|
|
|
{ |
107
|
|
|
try { |
108
|
|
|
$options = $user->getTwoFactorAuthProviderOptions(); |
109
|
|
|
|
110
|
|
|
$response = json_decode((new HttpClient())->get( |
111
|
|
|
$this->config['api_url'].'/protected/json/call/'.$options['id']. |
112
|
|
|
'?force=true&api_key='.$this->config['api_key'] |
113
|
|
|
)->getBody(), true); |
114
|
|
|
|
115
|
|
|
return $response['success'] === true; |
116
|
|
|
} catch (Exception $e) { |
117
|
|
|
return false; |
118
|
|
|
} |
119
|
|
|
} |
120
|
|
|
|
121
|
|
|
/** |
122
|
|
|
* Determine if the given token is valid for the given user. |
123
|
|
|
* |
124
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
125
|
|
|
* @param string $token |
126
|
|
|
* |
127
|
|
|
* @return bool |
128
|
|
|
*/ |
129
|
|
|
public function tokenIsValid(TwoFactorAuthenticatable $user, $token) |
130
|
|
|
{ |
131
|
|
|
try { |
132
|
|
|
$options = $user->getTwoFactorAuthProviderOptions(); |
133
|
|
|
|
134
|
|
|
$response = json_decode((new HttpClient())->get( |
135
|
|
|
$this->config['api_url'].'/protected/json/verify/'. |
136
|
|
|
$token.'/'.$options['id'].'?force=true&api_key='. |
137
|
|
|
$this->config['api_key'] |
138
|
|
|
)->getBody(), true); |
139
|
|
|
|
140
|
|
|
return $response['token'] === 'is valid'; |
141
|
|
|
} catch (Exception $e) { |
142
|
|
|
return false; |
143
|
|
|
} |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Delete the given user from the provider. |
148
|
|
|
* |
149
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
150
|
|
|
* |
151
|
|
|
* @return bool |
152
|
|
|
*/ |
153
|
|
|
public function delete(TwoFactorAuthenticatable $user) |
154
|
|
|
{ |
155
|
|
|
$options = $user->getTwoFactorAuthProviderOptions(); |
156
|
|
|
|
157
|
|
|
(new HttpClient())->post( |
158
|
|
|
$this->config['api_url'].'/protected/json/users/delete/'. |
159
|
|
|
$options['id'].'?api_key='.$this->config['api_key'] |
160
|
|
|
); |
161
|
|
|
|
162
|
|
|
$user->setTwoFactorAuthProviderOptions([]); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Determine if the given user should be sent two-factor authentication token via SMS/phone call. |
167
|
|
|
* |
168
|
|
|
* @param \Srmklive\Authy\Contracts\Auth\TwoFactor\Authenticatable $user |
169
|
|
|
* |
170
|
|
|
* @return bool |
171
|
|
|
*/ |
172
|
|
|
public function canSendToken(TwoFactorAuthenticatable $user) |
173
|
|
|
{ |
174
|
|
|
if ($this->isEnabled($user)) { |
175
|
|
|
if ($user->getTwoFactorAuthProviderOptions()['sms'] || |
176
|
|
|
$user->getTwoFactorAuthProviderOptions()['phone'] || |
177
|
|
|
$user->getTwoFactorAuthProviderOptions()['email']) { |
178
|
|
|
return true; |
179
|
|
|
} |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
return false; |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.