Azure / azure-sdk-for-js

This repository is for active development of the Azure SDK for JavaScript (NodeJS & Browser). For consumers of the SDK we recommend visiting our public developer docs at https://docs.microsoft.com/javascript/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-js.
MIT License
2.07k stars 1.19k forks source link

Auth error using token authentication #9110

Closed matthewfarrell closed 4 years ago

matthewfarrell commented 4 years ago

Describe the bug When using token based authentication, the auth header sent to CosmosDb is empty

To Reproduce Steps to reproduce the behavior:

  1. Create a new cosmos client using resource tokens, and execute the delete method
const database = 'database1';
const collection = 'collection1';
const token = 'token string';
const endpoint = 'https://<endoint url>/';
const itemId = '1234';

const resourceTokens = {};
resourceTokens[`dbs/${database}/colls/${collection}`] = tokenString;

const cosmosClientOptions: CosmosClientOptions = {
  resourceTokens: resourceTokens,
  endpoint: endpoint,
  connectionPolicy: {
    enableEndpointDiscovery: false
  }
};
const dbClient = new CosmosClient(cosmosClientOptions);
const db = dbClient.database(database);

const container = db.container(collection);
await container.item(itemId).delete();

Cosmos returns 401 unauthorised. If you inspect the network request to Cosmos, the auth header is null.

Expected behavior The item should delete

Additional context When using tokens, the resourceId that is passed into the method getAuthorizationTokenUsingResourceTokens in src/auth.ts is passing the full path to the item id (not the collection): dbs/<database>/colls/<collection>/<item id>. I'm not sure if this is as intended?

To work around the issue, I added the following code to look for a token in a parent resource, though I wonder if the correct fix would be to pass in the resourceId for the collection instead of the item?

src/auth.ts line 71

// Look for a key for a parent of the resource Id
const resourceSegments = resourceId.split("/");
for (let i = resourceSegments.length; i > 0; i -= 1) {
  const partialPath = resourceSegments.slice(0, i).join('/');
  const id = decodeURI(partialPath);
  if (resourceTokens[id]) {
    return resourceTokens[id];
  }
}
southpolesteve commented 4 years ago

@matthewfarrell Thanks for the report. I'll do some investigating, but first glance this does look like a bug. I think your suggested fix is probably correct. cc @zfoster

middiu commented 4 years ago

Hi, any progress on this issue? it's affecting my project as well and it's quite important do being able to delete items....

Cheers

southpolesteve commented 4 years ago

Resolved in 3.7.1