0
votes

I'm trying to get documents from CosmosDB (SQL) through the REST API. With an Azure Function I determine the authorization string according to the code in the documentation.

I call this code with the following parameters:

GenerateAuthToken("GET", "docs", "dbs/vacancies/colls/items/docs", "masterkey", "master", "1.0");

I just want to get the documents in the database vacancies and in the collection items. These entities exist in CosmosDB (case sensitive match), and there is a document in that collection.

Then I use postman to call the Cosmos REST API. I do a HTTP GET to https://mycosmosdbaccount.documents.azure.com/dbs/vacancies/colls/items/docs headers:

x-ms-version : 2017-02-22
Accept: application/json
Authorization: type%3dmaster%26ver%3d1.0%26sig%3dDU1O3I0hMJzF76fedro4M2VnfOhE03aIWgccaVWRBIc%3d
x-ms-date: thu, 18 jan 2018 10:53:23 gmt

I get back:

{
    "code": "Unauthorized",
    "message": "The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'get\ndocs\ndbs/vacancies/colls/items\nthu, 18 jan 2018 14:31:43 gmt\n\n'\r\nActivityId: 637276f1-c4ec-4d5d-8199-022d680b31d2, Microsoft.Azure.Documents.Common/1.19.162.2"
}

I've tried about a hundred different combinations of the resourceLink (dbs/vacancies/colls/items/docs) and the http get URL with always the same result.

Please let me know what dumb thing I'm doing wrong.

1
Hi,any updates now? - Jay Gong
I have the same code as you do, and the resourcelink wasnt the problem. Since I was already using an Azure Function I Just used the dotnet sdk in it. - JurgenW
The resourcelink was set to 'dbs/vacancies/colls/items/docs' in your post, it need to be set to 'dbs/vacancies/colls/items' when you want to get documents. - Jay Gong

1 Answers

0
votes

According to your error code , it supposed to be the issue of Authorization arguments in Request Header.

I tested Get documents Rest API with java code locally and it works for me.

Please refer to the code as below :

import com.sun.org.apache.xml.internal.security.utils.Base64;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

public class ListDataBaseRest {

    private static final String account = "***";
    private static final String key = "***";


    public static void main(String args[]) throws Exception {

        String urlString = "https://" + account + ".documents.azure.com/dbs/db/colls/coll/docs";
        HttpURLConnection connection = (HttpURLConnection) (new URL(urlString)).openConnection();
        getFileRequest(connection, key);
        connection.connect();


        System.out.println("Response message : " + connection.getResponseMessage());
        System.out.println("Response code : " + connection.getResponseCode());

        BufferedReader br = null;
        if (connection.getResponseCode() != 200) {
            br = new BufferedReader(new InputStreamReader((connection.getErrorStream())));
        } else {
            br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
        }
        System.out.println("Response body : " + br.readLine());
    }

    public static void getFileRequest(HttpURLConnection request, String key)
            throws Exception {
        SimpleDateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss");
        fmt.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = fmt.format(Calendar.getInstance().getTime()) + " GMT";
        String stringToSign = "GET".toLowerCase() + "\n"
                + "docs".toLowerCase() + "\n"
                + "dbs/db/colls/coll" + "\n"
                + date.toLowerCase() + "\n"
                + "" + "\n";
        System.out.println("stringToSign : " + stringToSign);
        String auth = getAuthenticationString(stringToSign);

        request.setRequestMethod("GET");
        request.setRequestProperty("x-ms-date", date);
        request.setRequestProperty("x-ms-version", "2017-02-22");
        request.setRequestProperty("Authorization", auth);
        request.setRequestProperty("Content-Type", "application/query+json");

    }

    private static String getAuthenticationString(String stringToSign) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(Base64.decode(key), "HmacSHA256"));
        String authKey = new String(Base64.encode(mac.doFinal(stringToSign.getBytes("UTF-8"))));
        System.out.println("authkey:" + authKey);
        String auth = "type=master&ver=1.0&sig=" + authKey;
        auth = URLEncoder.encode(auth);
        System.out.println("authString:" + auth);
        return auth;
    }

}

I noticed that the ResourceLink parameter in your GenerateAuthToken method is incorrect.

It should be dbs/vacancies/colls/items ,not dbs/vacancies/colls/items/docs.

Hope it helps you.