Пытаюсь перенаправить клиента на Google OAuth, получаю ошибку 405

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

Ответ на предварительный запрос не проходит проверку управления доступом: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin». Таким образом, доступ к источнику 'http://localhost:8080' запрещен. В ответе был код состояния HTTP 405.

По большей части я следовал этому руководству: https://developers.google.com/identity/protocols/OAuth2WebServer с помощью клиентской библиотеки node.js.

Насколько я понимаю, кажется, что Google не настроил свой сервер для приема запросов из разных источников, чего я не понимаю, так это того, как я должен перенаправлять своих пользователей на их страницу авторизации, если я не могу отправить запрос из своего домена.

Вот соответствующий код:

export function authorize(req, res, callback): any {
  let auth = new googleAuth();
  let oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
  if (// Check if we have previously stored a token.) {
    oauth2Client.credentials = //get token;
    callback(oauth2Client);
  } else {
    //redirect to google authentication page
    let authUrl = oauth2Client.generateAuthUrl({
      access_type: 'offline',
      state: '/',
      scope: SCOPES
    });
    res.redirect(authUrl);
  }
}

person Anoop Dhillon    schedule 10.08.2017    source источник
comment
405 означает «метод не разрешен», и поэтому в этом контексте сервер вообще не разрешает запросы OPTIONS к URL-адресу authUrl, который вы пытаетесь нажать. Я думаю, что это, вероятно, не имеет никакого отношения к тому, принимает ли сервер запросы из разных источников или нет, но вы можете подтвердить это, используя curl или postman или какой-либо другой инструмент, чтобы отправить запрос OPTIONS на этот URL-адрес authUrl и посмотреть, что вы получите в ответ. . Держу пари, ты получишь 405.   -  person sideshowbarker    schedule 10.08.2017
comment
В любом случае, пока этот сервер выдает 405 на запросы OPTIONS, вы никак не сможете успешно получить доступ к его ответам из кода JavaScript внешнего интерфейса. Вместо этого вам нужно будет сделать запрос из вашего внутреннего кода. Для сервисов на основе OAuth это почти всегда так: вы не сможете использовать XHR или Fetch API для получения от них ответов, к которым может получить доступ ваш интерфейсный код JavaScript.   -  person sideshowbarker    schedule 10.08.2017
comment
@sideshowbarker Запрос OPTIONS — это предварительный запрос от браузера, а не то, что я делаю целенаправленно. Вы правы, у меня возникает та же проблема с использованием почтальона, но запросы 405 to OPTIONS по-прежнему являются проблемой, которую мне придется решать, поскольку я делаю запрос CORS, верно? Если я запрашиваю серверную часть, как пользователь аутентифицируется? Например, если ссылка из примера Google просит вас войти в систему и предоставить доступ к области примера. Мне все еще нужно, чтобы пользователи вошли в систему/предоставили доступ к моему приложению.   -  person Anoop Dhillon    schedule 10.08.2017
comment
Извините за дерьмовое форматирование, вот ссылка: accounts.google.com/o/oauth2/ v2/авторизация? scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.metadata.readonly& access_type=offline& include_granted_scopes=true& state=state_parameter_passthrough_value& redirect_uri=http%3A%2F%2Foauth2.example.com%2Fcallback& response_type=code& client_id= ID клиента   -  person Anoop Dhillon    schedule 10.08.2017
comment
Да, извините за краткость — я знаю, что запрос OPTIONS — это предварительная проверка из браузера. Я хотел сказать, что именно в этом проблема, потому что браузер никогда не будет включать какие-либо учетные данные в этот запрос OPTIONS и не будет выполнять какую-либо иную аутентификацию при его выполнении. Поэтому, чтобы он работал с запросами из внешнего кода JavaScript с использованием XHR или Fetch, сервер не должен требовать аутентификации/учетных данных. Но это так.   -  person sideshowbarker    schedule 10.08.2017
comment
Во всяком случае, я вижу пример JavaScript на developers.google.com/google-apps/ calendar/quickstart/js, который показывает, как Google на самом деле поддерживает использование API из веб-приложения. И на developers.google.com/google-apps/calendar/overview#quickstarts Я вижу ссылки на множество других поддерживаемых способов сделать это в различных средах выполнения/языках бэкэнда. Кажется, что лучший способ заставить что-то работать - это использовать один из этих поддерживаемых примеров в качестве отправной точки и изменить его, как вам нужно, чтобы интегрировать его в существующий код.   -  person sideshowbarker    schedule 10.08.2017


Ответы (3)


Оказывается, когда AJAX получает код состояния 300, браузер автоматически отправляет другой запрос GET в возвращенное местоположение от имени клиента. Даже если бы я решил проблему с CORS, мне пришлось бы вручную загружать html-страницу, поскольку запрос был сделан от имени клиента. Что я действительно хочу, так это чтобы браузер делал запрос на auth uri.

Поэтому мое решение этой проблемы состоит в том, чтобы обнаруживать перенаправления на внешнем интерфейсе и заставлять браузер выдавать совершенно новый запрос GET. Все еще кажется, что это обходной путь, поэтому, если у кого-то еще есть лучшее решение, я хотел бы его услышать.

person Anoop Dhillon    schedule 11.08.2017

Если кто-то использует React или аналогичную SPA Framework для решения этой проблемы, связанной с OAuth 2, прочитайте это:

Не перенаправлять на стороне сервера. Не делайте этого (node.js/express в качестве примера):

router.get('/go', errorHandler(async (req, res, next) => {
    res.redirect(authenticationUrl);
})
);

СДЕЛАЙ ЭТО:

router.get('/go', errorHandler(async (req, res, next) => {
    res.json({
        redirectUrl: 'https://google.com'
    })
})
);

А затем на вашем внешнем клиенте получите ответ и сделайте перенаправление. Пример:

getUrl = async () => {
    try {
        const res = await API.get(`/go`);
        window.location = res.data.redirectUrl;
    } catch (err) {
        console.log(err);
    }
}

Работа в Реакте. Проверено!

person Nastro    schedule 31.01.2019

В соответствии с потоком он отображается как Браузер (APP) -> API (Сервер) -> Google auth (перенаправление). Это очень распространенный путь с серверами поставщиков удостоверений, такими как AWS, Google Auth и т. д. дополнительный заголовок ALLOW ORIGIN, поэтому браузер отклоняет запрос, когда дело доходит до точки перенаправления

Теперь приходит решение тренировки.

  1. Домен приложения (http://localhost:3000) должен быть добавлен в качестве доверенного домена на сервере IDP.

  2. Запрос к серверу API для инициации аутентификации должен быть

    window.location.href = 'http://localhost:5000/api/v1/auth/login-google';

person Harsh Bhardwaj    schedule 15.06.2021