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\Traits\CompanyAuth;
6use Illuminate\Http\Request;
7use App\Events\User\LoggedIn;
8use App\Http\Models\Auth\User;
9use Illuminate\Http\JsonResponse;
10use App\Http\Controllers\Controller;
11use App\Http\Models\Passport\Client;
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                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}