| <?php |
|
|
| namespace App\Http\Controllers\Auth; |
|
|
| use App\Http\Controllers\Controller; |
| use App\Models\User; |
| use App\Providers\RouteServiceProvider; |
| use Illuminate\Http\RedirectResponse; |
| use Illuminate\Http\Request; |
| use Illuminate\Support\Carbon; |
| use Illuminate\Support\Facades\Auth; |
| use Illuminate\Support\Facades\Hash; |
| use Illuminate\Support\Facades\Http; |
| use Illuminate\Support\Str; |
|
|
| class GoogleAuthController extends Controller |
| { |
| public function redirect(Request $request): RedirectResponse |
| { |
| if (! $this->isGoogleLoginConfigured()) { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Login Google belum dikonfigurasi. Isi GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, dan GOOGLE_REDIRECT_URI terlebih dulu.', |
| ]); |
| } |
|
|
| $state = Str::random(40); |
|
|
| $request->session()->put('google_oauth_state', $state); |
|
|
| $query = http_build_query([ |
| 'client_id' => (string) config('services.google.client_id'), |
| 'redirect_uri' => (string) config('services.google.redirect'), |
| 'response_type' => 'code', |
| 'scope' => 'openid profile email', |
| 'prompt' => 'select_account', |
| 'access_type' => 'offline', |
| 'state' => $state, |
| ]); |
|
|
| return redirect()->away('https://accounts.google.com/o/oauth2/v2/auth?'.$query); |
| } |
|
|
| public function callback(Request $request): RedirectResponse |
| { |
| $storedState = (string) $request->session()->pull('google_oauth_state', ''); |
| $returnedState = (string) $request->string('state'); |
|
|
| if ($request->filled('error')) { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Login Google dibatalkan atau ditolak oleh pengguna.', |
| ]); |
| } |
|
|
| if ($storedState === '' || ! hash_equals($storedState, $returnedState)) { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Sesi login Google tidak valid. Coba ulangi lagi.', |
| ]); |
| } |
|
|
| if (! $this->isGoogleLoginConfigured()) { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Login Google belum dikonfigurasi di server.', |
| ]); |
| } |
|
|
| $tokenResponse = Http::asForm() |
| ->timeout(20) |
| ->post('https://oauth2.googleapis.com/token', [ |
| 'code' => (string) $request->string('code'), |
| 'client_id' => (string) config('services.google.client_id'), |
| 'client_secret' => (string) config('services.google.client_secret'), |
| 'redirect_uri' => (string) config('services.google.redirect'), |
| 'grant_type' => 'authorization_code', |
| ]); |
|
|
| if (! $tokenResponse->ok() || ! $tokenResponse->json('access_token')) { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Google tidak mengembalikan access token yang valid.', |
| ]); |
| } |
|
|
| $googleProfile = Http::withToken((string) $tokenResponse->json('access_token')) |
| ->timeout(20) |
| ->get('https://openidconnect.googleapis.com/v1/userinfo'); |
|
|
| if (! $googleProfile->ok()) { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Profil akun Google tidak bisa diambil saat ini.', |
| ]); |
| } |
|
|
| $profile = $googleProfile->json(); |
| $googleId = trim((string) data_get($profile, 'sub', '')); |
| $email = Str::lower(trim((string) data_get($profile, 'email', ''))); |
|
|
| if ($googleId === '' || $email === '') { |
| return redirect()->route('login')->withErrors([ |
| 'google' => 'Data akun Google tidak lengkap. Pastikan email tersedia di akun Google Anda.', |
| ]); |
| } |
|
|
| $user = User::query() |
| ->where('google_id', $googleId) |
| ->orWhere('email', $email) |
| ->first(); |
|
|
| if (! $user) { |
| $user = User::create([ |
| 'name' => trim((string) data_get($profile, 'name', Str::before($email, '@'))), |
| 'email' => $email, |
| 'google_id' => $googleId, |
| 'email_verified_at' => data_get($profile, 'email_verified') ? Carbon::now() : null, |
| 'password' => Hash::make(Str::random(40)), |
| ]); |
| } else { |
| $user->forceFill([ |
| 'name' => $user->name ?: trim((string) data_get($profile, 'name', Str::before($email, '@'))), |
| 'google_id' => $user->google_id ?: $googleId, |
| ]); |
|
|
| if (! $user->email_verified_at && data_get($profile, 'email_verified')) { |
| $user->email_verified_at = Carbon::now(); |
| } |
|
|
| $user->save(); |
| } |
|
|
| Auth::login($user, true); |
| $request->session()->regenerate(); |
|
|
| return redirect()->intended(RouteServiceProvider::HOME); |
| } |
|
|
| private function isGoogleLoginConfigured(): bool |
| { |
| return filled(config('services.google.client_id')) |
| && filled(config('services.google.client_secret')) |
| && filled(config('services.google.redirect')); |
| } |
| } |
|
|