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