Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 98 |
|
0.00% |
0 / 10 |
CRAP | |
0.00% |
0 / 1 |
SocialLoginController | |
0.00% |
0 / 98 |
|
0.00% |
0 / 10 |
272 | |
0.00% |
0 / 1 |
provider | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
0 | |||
username | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
login | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
validateLogin | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
attemptLogin | |
0.00% |
0 / 52 |
|
0.00% |
0 / 1 |
72 | |||
generateJwt | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
2 | |||
base64UrlEncode | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getUser | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getLoginMeta | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getOAuthClient | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace App\Http\Controllers\v1\Auth; |
4 | |
5 | use App\Traits\CompanyAuth; |
6 | use Illuminate\Http\Request; |
7 | use App\Events\User\LoggedIn; |
8 | use App\Http\Models\Auth\User; |
9 | use Illuminate\Http\JsonResponse; |
10 | use App\Http\Controllers\Controller; |
11 | use App\Http\Models\Passport\Client; |
12 | use Illuminate\Support\Facades\Log; |
13 | use Laravel\Socialite\Facades\Socialite; |
14 | |
15 | abstract class SocialLoginController extends Controller |
16 | { |
17 | use CompanyAuth; |
18 | |
19 | abstract public function provider(); |
20 | |
21 | public function username() |
22 | { |
23 | return 'email'; |
24 | } |
25 | |
26 | public function login(Request $request) |
27 | { |
28 | $this->validateLogin($request); |
29 | |
30 | return $this->attemptLogin($request); |
31 | } |
32 | |
33 | public function validateLogin(Request $request) |
34 | { |
35 | $request->validate([ |
36 | 'token' => 'required|string', |
37 | ]); |
38 | } |
39 | |
40 | public function attemptLogin(Request $request): JsonResponse |
41 | { |
42 | $client = $this->getOAuthClient(); |
43 | $authData = [ |
44 | 'grant_type' => 'social', |
45 | 'client_id' => $client->id, |
46 | 'client_secret' => $client->secret, |
47 | 'provider' => $this->provider(), |
48 | 'access_token' => $request->get('token'), |
49 | ]; |
50 | |
51 | $authRequest = Request::create(route('passport.token'), 'POST', $authData); |
52 | $response = app()->handle($authRequest); |
53 | $data = json_decode($response->getContent(), true); |
54 | |
55 | if (!empty($data)) { |
56 | if (array_key_exists("error", $data) && $data["error"] == "invalid_grant") { |
57 | $data = ['error' => trans('auth.failed')]; |
58 | return response()->json(data: $data, status: 400); |
59 | } |
60 | } |
61 | |
62 | $providerUser = Socialite::driver($this->provider())->stateless()->userFromToken($request->get('token')); |
63 | $email = $providerUser->getEmail(); |
64 | $user = $this->getUser($email); |
65 | $user->is_poc = $user->isPOC(); |
66 | |
67 | $about = $this->handleAdminInvitation($user); |
68 | |
69 | if ($about && $about['company_poc']) { |
70 | $data['is_company_poc'] = $about['company_poc']; |
71 | } |
72 | |
73 | $data = array_merge($data, [ |
74 | 'session_expires_in' => intval( |
75 | config('auth.passport.refresh_token_expiry') |
76 | ), |
77 | 'user_details' => $user, |
78 | 'company' => $user?->company?->slug, |
79 | 'provider' => $this->provider() |
80 | ]); |
81 | |
82 | Log::info('SocialLoginController::attemptLogin', [ |
83 | 'user' => $user, |
84 | 'email' => $email, |
85 | 'provider' => $this->provider(), |
86 | 'company' => $user?->company?->slug, |
87 | 'request' => $request->all(), |
88 | ]); |
89 | |
90 | $requireExtension = $request->get('include_extension'); |
91 | if (!$requireExtension) { |
92 | $prov = $this->provider(); |
93 | if (str_contains($prov, 'linkedin')) { |
94 | $prov = 'linkedin'; |
95 | } |
96 | |
97 | $url = config('app.url') . '/romeo/api/v1/user/auth/login/' . $prov; |
98 | |
99 | $request = Request::create($url, 'POST', [ |
100 | 'token' => $request->get('token'), |
101 | 'include_extension' => true |
102 | ]); |
103 | |
104 | $response = app()->handle($request); |
105 | $extensionData = json_decode($response->getContent(), true); |
106 | |
107 | $data['extension'] = $extensionData['result']; |
108 | } |
109 | |
110 | LoggedIn::dispatch($user, ['email' => $email, 'signin_source' => $this->provider()]); |
111 | |
112 | return response()->json($data); |
113 | } |
114 | |
115 | protected function generateJwt($user) |
116 | { |
117 | // Header |
118 | $header = json_encode([ |
119 | 'typ' => 'JWT', |
120 | 'alg' => 'HS256', |
121 | ]); |
122 | $base64UrlHeader = $this->base64UrlEncode($header); |
123 | |
124 | // Payload |
125 | $now = time(); |
126 | $common = [ |
127 | 'iat' => $now, |
128 | 'jti' => md5($now . rand()), |
129 | ]; |
130 | |
131 | $secret = 'GPn5ch5eLuyKXrtwDcesqkY8NQzYzDHm3HNdmTHAZ08='; |
132 | $companyExternalId = 1414; |
133 | $companyName = 'vengreso'; |
134 | $companyWebsite = 'https://vengreso.com'; |
135 | |
136 | $user_attributes = [ |
137 | 'user_external_id' => $user['id'], |
138 | 'user_email' => $user['email'], |
139 | 'user_first_name' => $user['first_name'], |
140 | 'user_last_name' => $user['last_name'], |
141 | 'company_external_id' => $user['id'], |
142 | 'company_name' => $companyName . '_' . $user['email'], |
143 | 'company_website' => 'https://' . $companyName . $user['email'] . '.com', |
144 | ]; |
145 | |
146 | $payload = json_encode(array_merge($common, $user_attributes)); |
147 | $base64UrlPayload = $this->base64UrlEncode($payload); |
148 | |
149 | // JWT |
150 | $message = $base64UrlHeader . '.' . $base64UrlPayload; |
151 | $signature = hash_hmac('sha256', $message, $secret, true); |
152 | $base64UrlSignature = $this->base64UrlEncode($signature); |
153 | $jwt = $base64UrlHeader . '.' . $base64UrlPayload . '.' . $base64UrlSignature; |
154 | |
155 | return $jwt; |
156 | } |
157 | |
158 | protected function base64UrlEncode($text) |
159 | { |
160 | return str_replace( |
161 | ['+', '/', '='], |
162 | ['-', '_', ''], |
163 | base64_encode($text) |
164 | ); |
165 | } |
166 | |
167 | protected function getUser($username) |
168 | { |
169 | return User::where($this->username(), $username)->first(); |
170 | } |
171 | |
172 | protected function getLoginMeta() |
173 | { |
174 | return []; |
175 | } |
176 | |
177 | protected function getOAuthClient() |
178 | { |
179 | $searchArray = ['password_client' => true]; |
180 | |
181 | return Client::where($searchArray)->first(); |
182 | } |
183 | } |