missing('code')) { if (env('APP_DEBUG')) { return response()->json([ 'larascord_message' => config('larascord.error_messages.missing_code', 'The authorization code is missing.'), 'code' => 400 ]); } else { return redirect('/')->with('error', config('larascord.error_messages.missing_code', 'The authorization code is missing.')); } } // Getting the access_token from the Discord API. try { $accessToken = $this->getDiscordAccessToken($request->get('code')); } catch (\Exception $e) { if (env('APP_DEBUG')) { return response()->json([ 'larascord_message' => config('larascord.error_messages.invalid_code', 'The authorization code is invalid.'), 'message' => $e->getMessage(), 'code' => $e->getCode() ]); } else { return redirect('/')->with('error', config('larascord.error_messages.invalid_code', 'The authorization code is invalid.')); } } // Using the access_token to get the user's Discord ID. try { $user = $this->getDiscordUser($accessToken->access_token); } catch (\Exception $e) { if (env('APP_DEBUG')) { return response()->json([ 'larascord_message' => config('larascord.error_messages.authorization_failed', 'The authorization failed.'), 'message' => $e->getMessage(), 'code' => $e->getCode() ]); } else { return redirect('/')->with('error', config('larascord.error_messages.authorization_failed', 'The authorization failed.')); } } // Making sure the current logged-in user's ID is matching the ID retrieved from the Discord API. if (Auth::check() && (Auth::id() !== $user->id)) { Auth::logout(); return redirect('/')->with('error', config('larascord.error_messages.invalid_user', 'The user ID doesn\'t match the logged-in user.')); } // Confirming the session in case the user was redirected from the password.confirm middleware. if (Auth::check()) { $request->session()->put('auth.password_confirmed_at', time()); } // Trying to create or update the user in the database. try { $user = $this->createOrUpdateUser($user, $accessToken->refresh_token); } catch (\Exception $e) { if (env('APP_DEBUG')) { return response()->json([ 'larascord_message' => config('larascord.error_messages.database_error', 'There was an error while trying to create or update the user.'), 'message' => $e->getMessage(), 'code' => $e->getCode() ]); } else { return redirect('/')->with('error', config('larascord.error_messages.database_error', 'There was an error while trying to create or update the user.')); } } // Authenticating the user if the user is not logged in. if (!Auth::check()) { Auth::login($user); } // Redirecting the user to the intended page or to the home page. return redirect()->intended(RouteServiceProvider::HOME); } /** * Handles the Discord OAuth2 callback. * * @param string $code * @return object * @throws \Illuminate\Http\Client\RequestException */ private function getDiscordAccessToken(string $code): object { $this->tokenData['code'] = $code; $response = Http::asForm()->post($this->tokenURL, $this->tokenData); $response->throw(); return json_decode($response->body()); } /** * Handles the Discord OAuth2 login. * * @param string $access_token * @return object * @throws \Illuminate\Http\Client\RequestException */ private function getDiscordUser(string $access_token): object { $response = Http::withToken($access_token)->get($this->apiURLBase); $response->throw(); return json_decode($response->body()); } /** * Handles the creation or update of the user. * * @param object $user * @param string $refresh_token * @return User * @throws \Exception */ private function createOrUpdateUser(object $user, string $refresh_token): User { return User::updateOrCreate( [ 'id' => $user->id, ], [ 'username' => $user->username, 'discord_nickname' => isset($user->global_name) ? $user->global_name : NULL, 'discriminator' => $user->discriminator, 'email' => isset($user->email) ? $user->email : NULL, 'avatar' => $user->avatar ?: NULL, 'verified' => isset($user->verified) ? $user->verified : 0, 'locale' => $user->locale, 'mfa_enabled' => $user->mfa_enabled, 'refresh_token' => $refresh_token ] ); } }