azure cosmosdb - Cosmos DB REST API using Resource Token gives 403 Forbidden - Stack Overflow
A resource token is created in cosmos db and when that is used to do REST API Call, CosmosDb gives 403 Unauthorized error. The same resource token when used in CosmosDb donot sdk, it works. So definitely something is wrong in the way i am doing REST API call. Here is the code.
using Microsoft.Azure.Cosmos;
using System.Net.Http.Formatting;
namespace CosmosDb_Rest_DotNet
{
internal class Program
{
static readonly string endpoint = "https://localhost:8081/";
static readonly string masterKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";
static readonly Uri baseUri = new Uri(endpoint);
static readonly string databaseId = "SampleDb";
static readonly string collectionId = "Lists";
static readonly string documentId = "cbd77fac-f7f0-46fb-a2f3-f6b48c11670c";
static readonly string partitionKey = "MyPartitionKey";
static readonly string userId = "userId";
static readonly string utc_date = DateTime.UtcNow.ToString("r");
static void Main(string[] args)
{
Console.WriteLine(DateTime.UtcNow.ToString("r"));
string resourceToken = "";
using (var cosmosClient = new CosmosClient(endpoint, masterKey))
{
Database cosmosdb = cosmosClient.GetDatabase(databaseId);
var listsContainer = cosmosdb.GetContainer(collectionId);
//Create user
try
{
var result = cosmosdb.CreateUserAsync(userId).Result;
}
catch (Exception)
{
//user already exists
}
var cosmosUser = cosmosdb.GetUser(userId);
Console.WriteLine($"Created Cosmos User: {cosmosUser.Id}");
//create permission and get ResourceToken. Resource Token permission is restricted to Partition Key
var listsContainerPermissionProps = new PermissionProperties($"{listsContainer.Id}-{cosmosUser.Id}",
PermissionMode.All,
listsContainer,
new PartitionKey(partitionKey));
var listsContainerPermissionResponse = cosmosUser.UpsertPermissionAsync(listsContainerPermissionProps, (int)TimeSpan.FromMinutes(30).TotalSeconds).Result;
resourceToken = listsContainerPermissionResponse.Resource.Token;
Console.WriteLine("Successfully received Resource Token.");
}
Console.WriteLine("Using Resource Token in CosmosClient SDK to query document.");
//TEST resourceToken using Cosmos SDK
using (CosmosClient resoureceTokenCosmosClient = new CosmosClient(endpoint, resourceToken))
{
Database resourceTokenCosmosDb = resoureceTokenCosmosClient.GetDatabase(databaseId);
var resourceTokenListsContainer = resourceTokenCosmosDb.GetContainer(collectionId);
var query = new QueryDefinition("SELECT * FROM c where c.Aid = 'MyPartitionKey'");
var queryResponse = resourceTokenListsContainer.GetItemQueryIterator<dynamic>(query, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("MyPartitionKey") });
while (queryResponse.HasMoreResults)
{
var items = queryResponse.ReadNextAsync().Result;
foreach (var item in items)
{
Console.WriteLine($"Received Item using CosmosClient with resource token: Name: {item.Name}, id: {item.id}");
}
}
Console.WriteLine("Resource Token Successfully worked and returned documents");
}
Console.WriteLine("Using same Resource Token in REST API Test");
//REST Client TEST
using (var client = new System.Net.Http.HttpClient())
{
string response = string.Empty;
string authHeader = string.Empty;
string verb = string.Empty;
string resourceType = string.Empty;
string resourceId = string.Empty;
string resourceLink = string.Empty;
client.DefaultRequestHeaders.Add("x-ms-date", DateTime.UtcNow.ToString("r"));
client.DefaultRequestHeaders.Add("x-ms-version", "2020-07-15");
client.DefaultRequestHeaders.Add("x-ms-documentdb-isquery", "True");
try
{
//EXECUTE a query
verb = "POST";
resourceType = "docs";
resourceLink = string.Format("dbs/{0}/colls/{1}/docs", databaseId, collectionId);
//url encode resource token
authHeader = Uri.EscapeDataString(resourceToken);
client.DefaultRequestHeaders.Remove("authorization");
client.DefaultRequestHeaders.Add("authorization", authHeader);
var qry = new SqlQuerySpec { query = "SELECT * FROM c where c.Aid = 'MyPartitionKey'" };
var r = client.PostWithNoCharSetAsync(new Uri(baseUri, resourceLink), qry).Result;
Console.WriteLine(r.Content.ReadAsStringAsync().Result);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
private static string GenerateMasterKeyAuthorizationSignature(string verb, string resourceId, string resourceType, string key, string keyType, string tokenVersion)
{
var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
string payLoad = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}\n{1}\n{2}\n{3}\n{4}\n",
verb.ToLowerInvariant(),
resourceType.ToLowerInvariant(),
resourceId,
utc_date.ToLowerInvariant(),
""
);
byte[] hashPayLoad = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payLoad));
string signature = Convert.ToBase64String(hashPayLoad);
return System.Web.HttpUtility.UrlEncode(String.Format(System.Globalization.CultureInfo.InvariantCulture, "type={0}&ver={1}&sig={2}",
keyType,
tokenVersion,
signature));
}
}
//This is used when executing a query via REST
//DocumentDB expects a specific Content-Type for queries
//When setting the Content-Type header it must not have a charset, currently.
//This custom class sets the correct Content-Type and clears the charset
public class NoCharSetJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
public override void SetDefaultContentHeaders(Type type, System.Net.Http.Headers.HttpContentHeaders headers, System.Net.Http.Headers.MediaTypeHeaderValue mediaType)
{
base.SetDefaultContentHeaders(type, headers, new System.Net.Http.Headers.MediaTypeHeaderValue("application/query+json"));
headers.ContentType.CharSet = "";
}
}
//A custom extension of HttpClient that adds a new PostWithNoCharSet async method
//that uses the custom MediaTypeFormatter class to post with the correct Content-Type header
public static class HttpClientExtensions
{
public static async Task<HttpResponseMessage> PostWithNoCharSetAsync<T>(this HttpClient client, Uri requestUri, T value) { return await client.PostAsync(requestUri, value, new NoCharSetJsonMediaTypeFormatter()); }
}
class SqlQuerySpec
{
public string query { get; set; }
}
}
Here is the output
Created Cosmos User: userId
Successfully received Resource Token.
Using Resource Token in CosmosClient SDK to query document.
Received Item using CosmosClient with resource token: Name: Test Doc, id: cbd77fac-f7f0-46fb-a2f3-f6b48c11670c
Resource Token Successfully worked and returned documents
Using same Resource Token in REST API Test
{"code":"Forbidden","message":"Insufficient permissions provided in the authorization header for the corresponding request. Please retry with another authorization header.\r\nActivityId: 723c8bc1-2d11-463e-a5bc-7f3ef038e59f, Microsoft.Azure.Documents.Common/2.14.0"}
Anyone should be able to run the code for local cosmos db emulator.
最新文章
- 谷歌正在复制苹果模式?(图)
- excel - When loading my userform i get Run-Time Error 381: Could not set the list property. Invalid property array index - Stack
- rust - Why do I have to use &char instead of char to index a key in a HashMap<char, i32>? - Stack Overflow
- swift - How do I know how many times a thread context switch happens on an xcode Instruments? - Stack Overflow
- powerbi - I have two table Fact table and Dimention table and I am trying to calculate Past year sales .Value its not working -
- amazon web services - How to create a CloudWatch alarm for an EventBridge Pipe's stopped state in AWS? - Stack Overflow
- git - SourceTree - "This is not a valid source pathURL" error attempting to clone a GitHub repository - Stack
- python - Can't run pytest with a `FileNotFoundError: [Errno 2] No such file or directory: 'tmppip-build-env-3fag
- python - calculate the absorption coefficient of the particles using pymiescatt - Stack Overflow
- python - Wrap_lon of the regionmask does not work with data span from -180 to 180 - Stack Overflow
- flutter - Retrieving tokens from aad_b2c_webview - Stack Overflow
- Blender Python Script isn't positioning meshes right from the image - Stack Overflow
- node.js - How to Deploy an Angular 19 SSR App on AWS Amplify? - Stack Overflow
- window - Strawberry Perl doesn't include Win32::shortcut? - Stack Overflow
- python - Newton raphson fails to approximate beyond two decimal points - Stack Overflow
- Clicking on Android Studio on Mac makes Chrome window disaapear - Stack Overflow
- Spring Boot Application in Docker Container Shuts Down Immediately After Startup - Stack Overflow