TypeError: не удалось получить в приложении расширения Google Chrome с помощью реакции

Я пытаюсь создать расширение Chrome, используя реакцию, и позволяю пользователям входить с помощью Google на мой внутренний сервер, который работает с моим передним сервером веб-приложения. Я могу предложить пользователю войти в систему с помощью Google и получить код с помощью потока oauth2. Однако, когда я пытаюсь получить свой внутренний маршрут, я получаю следующую ошибку:

TypeError: Failed to fetch at background.js:20:7

Вот мой код расширения Chrome: manifest.json

{
  "name": "my chrome extension",
  "description": "my chrome extension description",
  "version": "1.0.0",
  "manifest_version": 3,
  "author": "team creators",
  "icons": {
    "16" : "favicon.ico",
    "48" : "favicon.ico",
    "128" : "favicon.ico"
  },
  "action": {
    "default_popup": "index.html",
    "default_title": "my chrome extension"
  },
  "background": {
    "service_worker": "background.js"
  },
  "oauth2": {
    "client_id": "my client id",
    "scopes": [
      "openid", 
      "profile",
      "email",
      "https://www.googleapis.com/auth/calendar",
      "https://www.googleapis.com/auth/drive",
      "https://www.googleapis.com/auth/documents",
      "https://www.googleapis.com/auth/contacts",
      "https://www.googleapis.com/auth/contacts.readonly",
      "https://www.googleapis.com/auth/contacts.other.readonly",
      "https://mail.google.com/"
    ]
  },
  "content_security_policy": {
    "script-src": ["'self'", "https://accounts.google.com", "'wasm-unsafe-eval'", "'inline-speculation-rules'", "http://localhost:*", "http://127.0.0.1:*"]
  },
  "permissions": [
    "identity",
    "nativeMessaging",
    "tabs"
  ],
  "host_permissions": [
    "https://localhost:*/*",
    "http://localhost:*/*"
  ]
}

index.html

<!DOCTYPE html>
<html lang = "en">
  <head>
    <meta charset = "utf-8" />
    <link rel = "icon" href = "%PUBLIC_URL%/favicon.ico" />
    <meta name = "viewport" content = "width=device-width, initial-scale=1" />
    <meta name = "theme-color" content = "#000000" />
    <meta
      name = "description"
      content = "Web site created using create-react-app"
    />
    <link rel = "apple-touch-icon" href = "%PUBLIC_URL%/logo192.png" />
    
    <link rel = "manifest" href = "%PUBLIC_URL%/manifest.json" />
  
    <title>React App</title>
    <script type = "text/javascript" src = "oauth2.js"></script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id = "root"></div>
 
  </body>
</html>

oauth2.js

let clientId = 'my client id'
let redirectUri = `https://${chrome.runtime.id}.chromiumapp.org/`
let nonce = Math.random().toString(36).substring(2, 15)

function addClickEventToButton() {
    const button = document.getElementById('google-login-button');
    if (button) {
        console.info("we get here 3");
        button.addEventListener('click', function() {
            const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth');
          
            authUrl.searchParams.set('client_id', clientId);
            authUrl.searchParams.set('response_type', 'code');
            authUrl.searchParams.set('redirect_uri', redirectUri);

            var manifest = chrome.runtime.getManifest();
            authUrl.searchParams.set('scope', manifest.oauth2.scopes.join(' '));
            
            // authUrl.searchParams.set('scope', 'openid profile email');
            authUrl.searchParams.set('nonce', nonce);
            // Show the consent screen after login.
            authUrl.searchParams.set('prompt', 'consent');
        
            chrome.identity.launchWebAuthFlow(
                {
                  url: authUrl.href,
                  interactive: true,
                },
                async (redirectUrl) => {
                  if (redirectUrl) {
                    const codeRegex = /code=([^&]+)/;
                    const codeMatch = redirectUrl.match(codeRegex);
                    const code = codeMatch ? codeMatch[1] : null;

                    chrome.runtime.sendMessage({contentScriptQuery: "login", code: code}, function(response) {
                        console.info("reponse", response);
                    });
                    
                  }
                },
            );
        });
    } else {
        setTimeout(addClickEventToButton, 500);
    }
}

document.addEventListener('DOMContentLoaded', function() {
    addClickEventToButton();
});


фон.js

chrome.action.onClicked.addListener(function() {
  chrome.tabs.create({url: 'index.html'});
  console.info('action clicked');
});

chrome.runtime.onMessage.addListener(
  async function(request, sender, sendResponse) {
    if (request.contentScriptQuery == "login") {
      console.info("getting request", request);
      const url = "https://localhost:4000/google/auth/login";

      fetch(url, { // errors here
          method: "POST",
          mode: "cors",
          headers: {
              "Content-Type": "application/json",
          },
          body: JSON.stringify({ code: request.code, isExtensionLogin: true }),
      }).then(response => response.json())
        .then(response => sendResponse(response))
        .catch((err) => console.info("err", err))
      
      return true; 
    }
});

Вот мой бэкэнд server.js с соответствующей информацией

app.use((req, res, next) => {
    res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000,https://my-extension-id.chromiumapp.org/,chrome-extension://my-extension-id/"); // update to match the extension domain you will make the request from
    res.setHeader("Access-Control-Allow-Credentials", "true");
    res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,PATCH,DELETE");
    res.setHeader(
        "Access-Control-Allow-Headers",
        "Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, Content-Type, Authorization, Access-Control-Request-Method, Access-Control-Request-Headers"
    );
    next();
});

маршрут: "https://localhost:4000/google/auth/логин"

const handleGoogleSignin = async (req, res) => {
    try {
        const isExtensionLogin = req.body.isExtensionLogin;

        const { tokens } = await oauth2Client.getToken(req.body.code);
        const { sub } = jwt.decode(tokens.id_token);

        // check if user (google login user) exists
        const googleIntegrated = await ThirdParty.findOne({
            thirdPartyId: sub,
        });

        if (!googleIntegrated)
            return res.status(404).json({ message: "Google Account not in DB" });
        if (!googleIntegrated.isSignup)
            return res.status(404).json({
                message: "Google Account not associated with a login account",
        });

        // update google tokens

        ...

        const user = await User.findById(googleIntegrated.userId);
        const userToken = jwt.sign({ id: user._id }, process.env.JWT_SECRET);

        res.status(200).json({ token: userToken, user });
    } catch (err) {
        res.status(409).json({ message: err.message });
    }
};

Я нашел несколько вопросов по этой теме, но они мне не помогли Получение «TypeError: Failed to fetch», когда запрос на самом деле не завершился ошибкойВызов POST API возвращает ошибку CORS без https и ERR_CONNECTION_CLOSED безМанифест v3 получает данные из внешнего APIКак сделать кросс-оригинальный запрос в скрипте контента (в настоящее время заблокирован CORB, несмотря на правильные заголовки CORS)?

node должен быть mode в параметрах выборки. Также попробуйте удалить :* в host_permissions.
wOxxOm 12.04.2023 21:40

должно быть mode но я все равно получаю ту же ошибку

aj3409 12.04.2023 21:44

@wOxxOm Я тоже изменился :* все еще получаю ту же ошибку

aj3409 12.04.2023 23:40

@wOxxOm единственная другая проблема, которую я вижу, это content_security_policy; однако я не уверен, что изменить

aj3409 13.04.2023 00:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
204
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Отвечая на мой собственный вопрос:

Я должен быть "http://localhost:4000/google/auth/login", а не "https://localhost:4000/google/auth/login"

Другие вопросы по теме