This has me baffled.
I can request the document content as base64 with curl , no problem.
curl https://demo.docusign.net/restapi/v2/accounts/<id>/envelopes/<id>/documents<id> -H"Authorization : Bearer <token>" -H "Content-Transfer-Encoding: base64" -o <filename>
Return headers are
Content-Disposition: file; filename="blah"; documentid="1"
Content-Transfer-Encoding: base64
and the file is returned in base64 format.
Using the Apache oltu oauth2 library which underneath uses HttpURLConnection I cannot get the response to be sent in base 64. I have the request headers set to
Content-Transfer-Encoding: base64
Accept : */*
Authorisation : Bearer <token>
But all I ever get back is the binary version of the file which ultimately bombs out because the library saves the stream as a string which screws up the pdf.
I can't trace the return header , but the request header definitely has the above fields set.
Is there anything in the Docusign endpoints which look at the User-Agent or anything else to determine whether to do the base 64 encoding ? Why else would it only ever return the binary stream ?
I suspect your Java output is not the same and the best way to confirm this is to capture exact JSON/SOAP request posted by your API calls via Java to DocuSign by following steps explained at this DocuSign support article https://support.docusign.com/guides/ndse-user-guide-api-request-logging
Please post these and I am sure it will be we will be able to deduce the library "add" that is changing the actual output.
OK thanks #david for the advice on logging the requests in docusign. I find that the "Transfer-Content-Encoding" header has mysteriously disappeared on arrival at the Docusign server. Some digging indicates that
a. this header is dodgy anyway for non-email uses and that
b. in the Java HttpUrlConnection class it is "removed" as security measure. You can apparently set some flags to revert to previous behaviour. See https://bugs.openjdk.java.net/browse/JDK-6996110
In any case I worked around the problem by implementing a class which reads the response as an InputStream and not worrying about base64.
Hopefully this helps a Java OAuth library user save a day of their lives banging their heads against a wall !
Related
I'm having some trouble while trying to send a PDF file to Microsoft's Form Recognizer service.
Instead of sending the PDF Url location, I need to send the PDF file. On my experience, sending files could be done using base64 but it seems that Microsoft service is not compatible with base64 format. Whenever I try sending the file the server responses:
{
"error": {
"code": "1000",
"message": "Invalid input file."
}
}
I need to know how I should convert my PDF to the required application/pdf "Binary PDF data". I can't find any documentation referring to this conversion.
The Form Recognizer API webpage is: https://brazilsouth.dev.cognitive.microsoft.com/docs/services/form-recognizer-api-v2-1-preview-3/operations/AnalyzeWithCustomForm
And here you can find the complete documentation webpage: https://learn.microsoft.com/en-us/azure/cognitive-services/form-recognizer/quickstarts/client-library?tabs=preview%2Cv2-1&pivots=programming-language-rest-api
Thanks!
You are correct that base64-encoded requests are not supported.
If you are using curl and you want to send a local file, run this:
curl -i https://{endpoint}/formrecognizer/v2.1-preview.3/custom/models/{modelId}/analyze -H 'Content-Type: application/pdf' \
-H 'Ocp-Apim-Subscription-Key: {subscription key}' --data-binary #/path/to/your/file.pdf
The key parts are the Content-Type header, which must match a supported value, and the --data-binary flag, which is the path to a local PDF file. Be sure to include the -i flag so that you can see the Operation-Location header in the response, which is where you can retrieve the analyze results.
You may also want to take a look at the Form Recognizer SDKs for C#, Java, JavaScript, and Python.
The DocuSign documentation goes through an easy to follow authorization flow for code grant. I'm able to get the "code" from the initial GET request to /oath/auth but getting the tokens gives me an error of "invalid_grant" when I try in postman. I've followed the steps and have a request that looks like this using account-d.docusign.com for host:
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic MjMwNTQ2YTctOWM1NS00MGFkLThmYmYtYWYyMDVkNTQ5NGFkOjMwODc1NTVlLTBhMWMtNGFhOC1iMzI2LTY4MmM3YmYyNzZlOQ==
grant_type=authorization_code&code=ey2dj3nd.AAAA39djasd3.dkn4449d21d
Two other members of my team have also tried with their developer accounts and all are getting invalid_grant errors. Is this no longer supported or are there common errors associated with this error that we might be able to investigate?
Re-check all of your values.
I was also getting the same invalid_grant response and could not figure out why at first. It turns out that I had a typo in the Content-Type header. I was using application/x-www-form-urlencode instead of application/x-www-form-urlencoded.
You may not be, but if you are submitting the exact Authorization Header as you've posted it here in your question (MjMwNTQ2YTctOWM1NS00MGFkLThmYmYtYWYyMDVkNTQ5NGFkOjMwODc1NTVlLTBhMWMtNGFhOC1iMzI2LTY4MmM3YmYyNzZlOQ==) it will fail with that message.
That is the base64 value for the sample integration key and sample secret key provided in their documentation. If you decode that string with an online base64decoder it will result in 230546a7-9c55-40ad-8fbf-af205d5494ad:3087555e-0a1c-4aa8-b326-682c7bf276e9. This is the same sample integration key and secret in the documentation.
Check the Authorization header you are submitting by encoding your integration key and secret (integrationKey:secret) using this online base64encoder. This will make sure the issue isn't with your base64 encoding of your integration key and secret. Once you have that value make sure your Authorization uses the word Basic before the value you got from this website. (Basic base64stringFromOnlineEncoder)
Check that the code your are submitting in the body of the post is not the sample code from their documentation. ey2dj3nd.AAAA39djasd3.dkn4449d21d is the sample code from their documentation. You may just be using that in your question as a placeholder but if you are submitting any of those values it will return invalid_grant. Make sure that the body of your post does not have any leading or trailing spaces.
Have the correct Content-Type set application/x-www-form-urlencoded
Have the correct Authorization header set Basic base64EncodedIntegrationKey:Secret
Have the correct body using the valid code received from the GET request to /oauth/auth with no leading or trailing spaces, making sure you're not using the values from your question.
If you are still having trouble and you are not doing a user application but are doing a service integration you can use Legacy Authentication to get your oAuth2 token.
Alternative Method using Legacy Authentication for Service Integrations
This method does not use a grant code. You pass in the integration key, username and password into the X-DocuSign-Authentication header in JSON format.
Demo Server: demo.docusign.net
Production Server: www.docusign.net API
Version: v2
POST https://{server}/restapi/{apiVersion}/oauth2/token
Content-Type: application/x-www-form-urlencoded
X-DocuSign-Authentication: {"IntegratorKey":"your_integrator_key","Password":"docusign_account_password","Username":"docusign_account_username"}
grant_type=password&client_id=your_integrator_key&username=docusign_account_username&password=docusign_account_password&scope=api
If you are building a user application that requires the user enter their docusign credentials to generate the token, this alternative will not work for you.
For anyone who is facing this error, I'd like to point out this note in the documentation:
Note: The obtained authorization code is only viable for 2 minutes. If more then two minutes pass between obtaining the authorization code and attempting to exchange it for an access token, the operation will fail.
I was struggling with the same error until I spotted the note and sped up my typing to meet the 2 minutes.
Hope it helps someone else.
In my case the problem was related to having set a wrong value for Content-Type header, namely "application/x-www-form-URIencoded" instead of the correct "application/x-www-form-urlencoded". Note though that in my case the problem was not a "typo" but an excessive trust in DocuSign documentation.
Indeed the wrong Content-Type is, at the time of writing, suggested directly into the documentation page where they describe the Authorization Code Grant workflow, see the image below for the relevant part.
Hopefully they will fix the documentation soon but for the time being be careful not to blindly copy & paste the code from their examples without thinking, as I initially did.
anyone have an idea what is wrong here I am getting a BadRequest with the following
{"error":"invalid_grant","error_description":"unauthorized_client"}
var client = new RestClient(ESIGNURL);
var request = new RestRequest("/oauth/token");
request.Method = Method.POST;
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(integrationkey+ ":" + secret)));
string body = "grant_type=authorization_code&code=" + code;
request.Parameters.Clear();
request.AddParameter("application/x-www-form-urlencoded", body, ParameterType.RequestBody);
var response = client.Execute(request);
I was getting this error as well. What I realized is I was appending the state at the end of the code before passing it to the oauth token endpoint.
This snippet is from Docusign explaining what are some other reasons for getting that error.
Invalid-error explanation
I just spent a day doing this (in NodeJS). I'll add a couple of things to the answers from before. First, I had to put:
"Content-Type": "application/x-www-form-urlencoded"
in the header. Otherwise it gave me the message:
{
"error": "invalid_grant",
"error_description": "unsupported_grant_type"
}
Second, the base64 encoding:
I used this in NodeJS and it worked
const integration_key = process.env.INTEGRATION_KEY;
const secret_key = process.env.SECRET_KEY;
const authinfo =
integration_key.toString("utf8") + ":" + secret_key.toString("utf8");
const buff2 = Buffer(authinfo, "utf8").toString("base64");
If you use "base64url" it dosen't work because it strips the == off of the end of the string. The = symbol is used as padding and apparently it's needed. You see a similar difference on this site https://www.base64encode.org/ when you toggle the url safe encoding option. If you don't have the padding on the end of your base64 encoded string (or if it's generally incorrect) you get this message:
{
"error": "invalid_grant",
"error_description": "unauthorized_client"
}
Finally, if you're using Postman (I'm using DocuSign's Postman Collection) remember to reset and save the codeFromUrl variable after you update it. Otherwise it doesn't update and you get the message:
{
"error": "invalid_grant",
"error_description": "expired_client_token"
}
This means the old URL code has expired and your new one didn't save.
I'm trying to upload a jpeg file for profile image using the Profiles REST API to IBM Connections_v5.0. I however get an error message "The type of the photo file you provided is not supported".
I'm however able to upload the same file directly using the Connections UI interface directly. I'm setting the MIME type correctly as "image/jpeg".
Also tried with GIF and PNG images but get the same error message.
Any pointers would be very helpful.
I'm just using FF restclient addon to fire a REST call. So basically doing a PUT on /profiles/photo.do?key=....
Content-Type is set as "image/jpeg" and the payload consists of the image data in binary (base 64) encoded.
The payload should just be the binary of the image, there is no need to Base64 encode it.
You should refer to Adding a Profile Photo
You need to use a Key (great stackoverflow post here)
If you know the key for a user's profile you can do the following:
key — This is generated by Connections itself during the population
process. It is used to define the users profile within the context of
Profiles and provides Connections with the ability to associate
content with a user when the users LDAP information has been altered.
It provides a separation of identity and helps facilitate user content
synchronization for Connections.
Once you have a key, you make the following request
URL: https://profiles.enterprise.example.com/profiles/photo.do?key=
b559403a-9r32-2c81-c99w-ppq8bb69442
METHOD: PUT
CONTENT-TYPE: image/png
input the binary content on the stream
you should be able to use "image/jpeg", "image/jpg", "image/png" or "image/gif"
If you have an error after the PUT method, you should add the SystemOut.log lines which are relevant.
Im trying to use the chrome.downloads.download method and i need to send post data to the server, i use options.body="?keyName=value" on the download options but it doesn't work. Maybe someone knows better the api, the documentation is not very explicit about this subject.
'cause Chrome doesn't set request content-type for you, you can verify this through this script:
<?php
header('Content-Type: text/plain; charset="utf-8"');
var_dump($_SERVER['REQUEST_METHOD']);
var_dump($_GET);
var_dump($_POST);
var_dump($_SERVER['CONTENT_TYPE']);
var_dump(file_get_contents('php://input')); // $HTTP_RAW_POST_DATA
?>
So, you should use parse_str($HTTP_RAW_POST_DATA, $post_params) to get the values of the parameters. PHP won't parse the post body if content-type is not properly set. (application/x-www-form-urlencoded, application/www-url-encoded, etc.)
I am trying to make a simple REST call to the Set Blob Properties API (http://msdn.microsoft.com/en-us/library/windowsazure/hh452235) to just turn off/on logging. I have gotten the REST API call to successfully work for retrieving Blob Properties, so I know my hashing algorithms, headers-setting, and Authentication signature creation works, but I can't seem to get it working on the Set Properties side of things. I keep getting an error on the Authentication Header, so I know I'm not doing something right there.
I have copied below what is being created and eventually hashed and put into the auth header string. The online documentation (http://msdn.microsoft.com/en-us/library/windowsazure/dd179428) does not really help in determining which of these fields are absolutely required for this particular type of Blob request, so I've tried filling most of them in, but I don't seem to get a difference response regardless of what I fill in. I've also tried the Shared Key Lite authentication, which would be preferred since it's much more lightweight, but that doesn't seem to work either when I fill in all 5 of those fields.
Shared Key Authentication for Blob Services:
PUT\n
\n
\n
130\n
(MD5_CONTENT_HASH)
\n
\n
\n
\n
\n
\n
\n
x-ms-date:Tue, 19 Jun 2012 19:53:58 GMT\n
x-ms-version:2009-09-19\n
/(MY_ACCOUNT)/\n
comp:properties\n
restype:service
Is there anything obvious I'm missing here? The values (MD5_CONTENT_HASH) and (MY_ACCOUNT) are of course filled in when I make the request call, and the similar request call to "GET" the properties works fine when I send it. The only difference between that one and this is that I'm sending the MD5_content, along with the content-length. I may be missing something obvious here, though.
Any advice would be greatly appreciated! Thanks in advance.
-Vincent
EDIT MORE INFO:
Programming Language I'm using: Objective-C (iOS iPhone)
I'm also using ASIHTTPRequest to make the request. I simply define the request, setRequestMethod:#"PUT", then I create the request body and convert it to NSData to calculate the length. I attach the request-body data via the appendPostData method to the request. I then build the auth string above, hash the whole thing, and attach it to the request as a header called "Authorization".
Request Body String I'm using:
<?xml version=\"1.0\" encoding=\"utf-8\"?><StorageServiceProperties><Logging><Version>1</Version></Logging></StorageServiceProperties>
I know this is an incomplete request body, but I was planning on waiting for it to give a failure on "missing request body element" or something similar, until I proceeded on creating the full XML there. (could that be my issue?)
Error I get from the server:
<?xml version="1.0" encoding="utf-8"?><Error><Code>AuthenticationFailed</Code><Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.
RequestId:accc4fac-2701-409c-b1a7-b3a528ce7e8a
Time:2012-06-20T14:36:50.5313236Z</Message><AuthenticationErrorDetail>The MAC signature found in the HTTP request '(MY_HASH)' is not the same as any computed signature. Server used following string to sign: 'POST
130
x-ms-date:Wed, 20 Jun 2012 14:36:50 GMT
x-ms-version:2009-09-19
/(MY_ACCOUNT)/
comp:properties
restype:service'.</AuthenticationErrorDetail></Error>
What's odd is that the error I get back from the server seems to look like that, no matter how many parameters I pass into the Authentication signature.
Thanks for any help you can offer!
Comparing your signed string and the error message indicates that you're sending a POST request but signing as though you're sending a PUT.