Ошибка при использовании авторизации на предъявителя для синхронизации PouchDB с Cloudant - PullRequest
0 голосов
/ 28 мая 2019

Я опытный программист JavaScript, но плохо знаком с PouchDB, Cloudant и oAuth. Когда я пытаюсь синхронизировать PouchDB и Cloudant с помощью Bearer Authorization, я получаю сообщение об ошибке:

"_reader access is required for this request", status: 401

Я пытаюсь написать демонстрационное веб-приложение, используя PouchDB и Cloudant. Я создал учетную запись IBM. Я создал один сервис под названием Cloudant-xx. Я выбрал метод аутентификации: IBM Cloud IAM (я не выбрал «и устаревший ...»). Я пошел на панель инструментов для этого сервиса и 1) создал базу данных (myDatabase), и 2) выбрал профиль головы в левой части экрана, затем [CORS] и отключил CORS (для разработки).

Я вернулся в службу, выбрал [Учетные данные службы] и создал новые учетные данные службы. Это дало мне объект с {"apikey": "ELB4lEVA ... IO", ..., "username": "451c ... 74-bluemix"}.

Я использовал curl для получения токена доступа:

curl -k -X POST \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --header "Accept: application/json" \
  --data-urlencode "grant_type=urn:ibm:params:oauth:grant-type:apikey" \
  --data-urlencode "apikey=ELB4lEVA...IO" \
  "https://iam.cloud.ibm.com/identity/token"

который вернул {"access_token":"eyJra...6fJns","token_type":"Bearer","expires_in":3600,"expiration":1558965151,"scope":"ibm openid"}

В течение часа я скопировал и вставил токен доступа в свой код javascript, запустил код и получил ошибку «Доступ _reader требуется для этого запроса» (см. Выше). Я не могу найти, где установить _reader доступ. Кто-нибудь может мне помочь? Спасибо!

    let localDb;
    const localName = "myDatabase";
    const remoteUrl = "https://451...d974-bluemix.cloudantnosqldb.appdomain.cloud/myDatabase";
    const token = "eyJra...6fJns";
    const syncOptions = {
        live: true,
        retry: true,
        continuous: true,
        ajax: {
            headers: {
                Authorization: "Bearer " + token,
            },
        },
    };
    localDb = new PouchDB(localName);
    localDb.sync(remoteUrl, syncOptions).on('change', function (info) {
        console.log(8888, "change", info);
    }).on('paused', function (info) {
        console.log(8888, "paused", info);
    }).on('active', function (info) {
        console.log(8888, "active", info);
    }).on('denied', function (err) {
        console.log(8888, "denied", err);
    }).on('complete', function (info) {
        console.log(8888, "denied", info);
    }).on('error', function (err) {
        console.log(8888, "error", err);
    });
    console.log(4444, localDb);

В консоли вижу:

4444 PouchDB {__opts: {…}, auto_compaction: undefined, prefix: "_pouch_", name: "myDatabase", _adapter: "idb", …}
index.js:194 

451...d974-bluemix.cloudantnosqldb.appdomain.cloud/:1 GET https://451...d974-bluemix.cloudantnosqldb.appdomain.cloud/myDatabase/ 401
index.js:192

8888 "error" CustomPouchError {error: "unauthorized", reason: "_reader access is required for this request", status: 401, name: "unauthorized", message: "_reader access is required for this request", …}

1 Ответ

1 голос
/ 28 мая 2019

Я ответил на свой вопрос. Оказывается, я следовал устаревшим примерам. В PouchDB 7.0 {ajax: {headers: {}} был заменен на fetch: function (url, opts) {}. Кроме того, мне пришлось использовать экземпляр PouchDB вместо строки для удаленной базы данных.

https://pouchdb.com/api.html#create_database

Опции для удаленных баз данных:

fetch (url, opts): перехватывает или переопределяет HTTP-запрос, вы можете добавить или изменить любые заголовки или параметры, относящиеся к http-запросу, а затем вернуть новое извлечение Promise.

Теперь это работает.

    let localDb;
    const localName = "myDatabase";
    const remoteUrl = "https://451...74-bluemix.cloudantnosqldb.appdomain.cloud/myDatabase";
    const token = "eyJ...448";
    const remoteOptions = {
        fetch: function (url, opts) {
            opts.headers.set("Authorization", "Bearer " + token);
            return PouchDB.fetch(url, opts);
        }
    };
    const syncOptions = {
        live: true,
        retry: true,
        continuous: true,
    };
    localDb = new PouchDB(localName);
    const remoteDb = new PouchDB(remoteUrl, remoteOptions);
    localDb.sync(remoteDb, syncOptions).on("change", function (info) {
        console.log(8888, "change", info);
    }).on("paused", function (info) {...})...
...