config = $config; $this->encrypter = $encrypter; $this->repository = $repository; } /** * Generate a 2FA token and store it in the database before returning the * QR code URL. This URL will need to be attached to a QR generating service in * order to function. * * @param \Pterodactyl\Models\User $user * @return string * * @throws \Pterodactyl\Exceptions\Model\DataValidationException * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException */ public function handle(User $user): string { $secret = ''; try { for ($i = 0; $i < $this->config->get('pterodactyl.auth.2fa.bytes', 16); $i++) { $secret .= substr(self::VALID_BASE32_CHARACTERS, random_int(0, 31), 1); } } catch (Exception $exception) { throw new RuntimeException($exception->getMessage(), 0, $exception); } $this->repository->withoutFreshModel()->update($user->id, [ 'totp_secret' => $this->encrypter->encrypt($secret), ]); $company = preg_replace('/\s/', '', $this->config->get('app.name')); return sprintf( 'otpauth://totp/%1$s:%2$s?secret=%3$s&issuer=%1$s', rawurlencode($company), rawurlencode($user->email), rawurlencode($secret) ); } }