Repository navigation
Expand file tree
/
Copy pathTwoFactorAuthentication.php
More file actions
105 lines (87 loc) · 2.89 KB
/
Copy pathTwoFactorAuthentication.php
File metadata and controls
105 lines (87 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php
namespace ProcessMaker;
use Illuminate\Support\Facades\Notification;
use OTPHP\TOTP;
use ParagonIE\ConstantTime\Base32;
use ProcessMaker\Models\User;
use ProcessMaker\Notifications\TwoFactorAuthNotification;
use Twilio\Rest\Client;
class TwoFactorAuthentication
{
const EMAIL = 'By email';
const SMS = 'By message to phone number';
const AUTH_APP = 'Authenticator App';
public function sendCode(User $user): void
{
// Get methods to send the code
$methods = config('password-policies.2fa_method', []);
if (in_array(self::EMAIL, $methods) || in_array(self::SMS, $methods)) {
// Get code
$code = $this->getCodeForEmailSms($user);
// Send OTP
if (in_array(self::EMAIL, $methods)) {
Notification::send($user, new TwoFactorAuthNotification($user, $code));
}
if (in_array(self::SMS, $methods)) {
$this->sendSms($user, $code);
}
} elseif (in_array(self::AUTH_APP, $methods)) {
session()->put('2fa-auth-app', true);
}
}
private function generateSecret(User $user): string
{
$base = $user->uuid . '_' . $user->username;
$secret = trim(Base32::encodeUpper($base), '=');
return $secret;
}
private function createOtpInstance(User $user)
{
// Get secret
$secret = $this->generateSecret($user);
// Config OTP
$otp = TOTP::createFromSecret($secret);
$otp->setDigest('sha512');
$otp->setIssuer('ProcessMaker');
$otp->setLabel($user->username);
$otp->setDigits(8);
$otp->setPeriod(300);
return $otp;
}
private function getCodeForEmailSms(User $user): string
{
// Create OTP instance
$otp = $this->createOtpInstance($user);
// Return current code
return $otp->now();
}
public function validateCode(User $user, string $code)
{
// Create OTP instance
$otp = $this->createOtpInstance($user);
// Validate code
return $otp->verify($code);
}
private function sendSms(User $user, string $code)
{
// Get config parameters for Twilio
$sid = config('twilio.sid');
$token = config('twilio.token');
$from = config('twilio.active_phone_number');
// Format the number to send the code
$to = '+' . ltrim($user->cell, '+');
// Build body
$body = $user->username . PHP_EOL . PHP_EOL;
$body .= __('This is your security code: :code', ['code' => $code]) . PHP_EOL . PHP_EOL;
$body .= _('Regards') . PHP_EOL;
$body .= 'ProcessMaker';
// Send SMS using Twilio SDK
$twilio = new Client($sid, $token);
$twilio->messages->create($to,
[
'from' => $from,
'body' => $body
]
);
}
}