Datastore API always returning "dsid: Missing Value" error - dropbox

I'm trying to follow the datastore API tutorial and this simple request (sent via Fiddler):
POST https://api.dropbox.com/1/datastores/get_or_create_datastore HTTP/1.1
User-Agent: Fiddler
Host: api.dropbox.com
Content-Length: 12
Authorization: Bearer [snipped]
dsid=default
always results in this error response:
HTTP/1.1 400 Bad Request
{"error": {"dsid": "Missing value"}}
The access token was created from the developer app console, and my test app has full dropbox permissions. Running the list_datastores API call succeeds and reports that I do have one datastore with a dsid of default.

I think you'll need a header of Content-Type: application/x-www-form-url-encoded, since you're sending form-encoded parameters.

Related

Socket Hang Up while trying to hit APIs hosted on AWS via Postman

I am trying to test an API hosted using AWS API Gateway and always getting following error:
Error: socket hang up
Request Headers
clientId: system
Authorization: //Correct Auth Token
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Host: //API Host URL
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
However, when I pass in an invalid Auth Token (like TEST), I actually receive a 403 error as expected. I can also see logs in CloudWatch confirming the call reached the authorizer.
CloudWatch Logs
The same API works for other people perfectly fine.
I have tried almost every resolution I found online related to this issue like I turned off 'SSL Certificate Verification' in Postman and kept proxy settings same as my colleagues. Tried to hit the API after disconnecting VPN as well but nothing worked for me.
Could anyone please help me with this.
Thanks in advance.

Attach a file (picture) to a conversation

I would like to be able to attach a file to a conversation, using the REST API. Is it possible? There is a «attachments» to /conversations/{convId}/messages/{itemId} but is that usable? How? The description of that field is not available.
The file API of Circuit supports the upload of attachments. As soon as you received your access token you can POST a message with the byte data. The following example wold upload a file with name test.jpg
POST /rest/v2/fileapi HTTP/1.1
Host: local.circuit.com
Authorization: Bearer <access token>
Content-Length: 100
Content-Disposition: attachment; filename="test.jpg"
Cache-Control: no-cache
<your content in binary form here>
Usually I am using Postman for my tests since it is very easy to use and supports OAuth 2.0 token generation (https://www.getpostman.com/)
You will receive an result that looks like
{"fileId":"fb211fd6-df53-4b82-824d-986dac47b3e7","attachmentId":"ZmIyMT..."}
If you want to validate your upload you can check it via
GET /rest/v2/fileapi?fileid=fb211fd6-df53-4b82-824d-986dac47b3e7 HTTP/1.1
Host: local.circuit.com
Authorization: Bearer <access token>
Cache-Control: no-cache
Well that was the easy part, now that you have uploaded the file to the backend you must attach it to a conversation item. Today we do not support UPDATE, i.e. you need to create a new one.
POST /rest/v2/conversations/<conv ID>/messages HTTP/1.1
Host: local.circuit.com
Authorization: Bearer <access token>
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
content=New+Text+Message&attachments=ZmIyMT...
You have to pass the generated attachment ID. After the execution of this requests the file is attached to the conversation.
If you skip the second step the file will not be linked to any conversation, is only accessible by the user who initiates the upload and will be deleted within the next 24 - 48h automatically.
Hope this helps, let me know if you have additional questions.

Too many authorization bearers in MFP 8.0

I've followed the steps provided in https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/authentication-and-security/protecting-external-resources/ to protect an external resource and https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/application-development/resource-request/javascript/ to call via Cordova.
I'm making 2 request to the same REST method, which is protected with the scope "aovLogin".
It seems that every call is generating a new bearer token, which needs 4 extra calls to MFP.
Also, the first time a method is called, it makes several extra calls (it always goes http 401, then 403 then 200, making extra calls to MFP in the middle). If i have a very granular API, it's making a lot of extra calls.
I've seen that the server API has a cache for the bearers and the scope is configured for being valid for 10 minutes.
Why is the client sending so many authorization requests?
POST /com.costaisa.app.api/api/mfprest/delegation/detail/private HTTP/1.1
HTTP/1.1 401 Unauthorized
----------
POST /mfp/api/preauth/v1/preauthorize HTTP/1.1
{"scope":"","client_id":"3deccec7-3f18-4ee2-8464-de90a7c64685"}
HTTP/1.1 400 Bad Request
{"errorCode":"INVALID_CLIENT_ID","errorMsg":"Invalid client ID."}
------
POST /mfp/api/registration/v1/self HTTP/1.1
{"signedRegistrationData":{"header":"XXXXX","payload":"XXXXX","signature":"XXXXX"}}
HTTP/1.1 201 Created
-----
POST /mfp/api/preauth/v1/preauthorize HTTP/1.1
{"scope":"","client_id":"84c45e4a-b75d-4125-ab9a-98f390d5bd3a"}
HTTP/1.1 200 OK
{"successes":{"clockSynchronization":{"serverTimeStamp":1480322130967}}}
--------
GET /mfp/api/az/v1/authorization?response_type=code&scope=&client_id=84c45e4a-b75d-4125-ab9a-98f390d5bd3a&redirect_uri=http://mfpredirecturi&isAjaxRequest=true&x=0.1757133661526875 HTTP/1.1
HTTP/1.1 302 Found
------
POST /mfp/api/az/v1/token HTTP/1.1
XXXXX
HTTP/1.1 200 OK
{"access_token":"XXXXX","token_type":"Bearer","expires_in":3599,"scope":""}
---
POST /com.costaisa.app.api/api/mfprest/delegation/detail/private HTTP/1.1
Authorization: Bearer XXXXX
{"idDelegation":"0801"}
HTTP/1.1 403 Forbidden
---
POST /mfp/api/preauth/v1/preauthorize HTTP/1.1
{"scope":"aovLogin","client_id":"84c45e4a-b75d-4125-ab9a-98f390d5bd3a"}
HTTP/1.1 401 Unauthorized
{"successes":{"clockSynchronization":{"serverTimeStamp":1480322131320}},"challenges":{"aovLogin":{"remainingAttempts":5,"errorMsg":null}}}
---
POST /mfp/api/preauth/v1/preauthorize HTTP/1.1
{"challengeResponse":{"aovLogin":{"username":"XXXXX","tokenSEA":"XXXXX"}},"scope":"aovLogin","client_id":"84c45e4a-b75d-4125-ab9a-98f390d5bd3a"}
HTTP/1.1 200 OK
{"successes":{"aovLogin":{"user":{"id":"XXXXX","displayName":"XXXXX","authenticatedAt":1480322139874,"authenticatedBy":"aovLogin","attributes":{"tokenSEA":"XXXXX"}}},"clockSynchronization":{"serverTimeStamp":1480322139874}}}
--------
GET /mfp/api/az/v1/authorization?response_type=code&scope=aovLogin&client_id=84c45e4a-b75d-4125-ab9a-98f390d5bd3a&redirect_uri=http://mfpredirecturi&isAjaxRequest=true&x=0.5223292209780417 HTTP/1.1
HTTP/1.1 302 Found
---
POST /mfp/api/az/v1/token HTTP/1.1
XXXXX
HTTP/1.1 200 OK
{"access_token":"XXXXX","token_type":"Bearer","expires_in":599,"scope":"aovLogin"}
---
POST /com.costaisa.app.api/api/mfprest/delegation/detail/private HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6Ijg0YzQ1ZTRhLWI3NWQtNDEyNS1hYjlhLTk4ZjM5MGQ1YmQzYSIsIm4iOiJBTTBEZDd4QWR2NkgteWdMN3I4cUNMZEUtM0kya2s0NXpnWnREZF9xczhmdm5ZZmRpcVRTVjRfMnQ2T0dHOENWNUNlNDFQTXBJd21MNDEwWDlJWm52aHhvWWlGY01TYU9lSXFvZS1ySkEwdVp1dzJySGhYWjNXVkNlS2V6UlZjQ09Zc1FOLW1RSzBtZno1XzNvLWV2MFVZd1hrU093QkJsMUVocUl3VkR3T2llZzJKTUdsMEVYc1BaZmtOWkktSFU0b01paS1Uck5MelJXa01tTHZtMDloTDV6b3NVTkExNXZlQ0twaDJXcG1TbTJTNjFuRGhIN2dMRW95bURuVEVqUFk1QW9oMmluSS0zNlJHWVZNVVViTzQ2Q3JOVVl1SW9iT2lYbEx6QklodUlDcGZWZHhUX3g3c3RLWDVDOUJmTVRCNEdrT0hQNWNVdjdOejFkRGhJUHU4PSJ9fQ.eyJpc3MiOiJjb20uaWJtLm1mcCIsInN1YiI6Ijg0YzQ1ZTRhLWI3NWQtNDEyNS1hYjlhLTk4ZjM5MGQ1YmQzYSIsImF1ZCI6ImNvbS5pYm0ubWZwIiwiZXhwIjoxNDgwMzIyNzM5ODc0LCJzY29wZSI6ImFvdkxvZ2luIn0.jGJAhZaV6NFHZKj-LKBmJ6Gqb7ZrZX20xDKEPkNtORZ1tanLo8MSklY2HogK-wKs7APIuWESLSsskrwR9p0EnrmHgUYZf3BPY9HDUSBojUN9-vd_I9kavcg34Hes1KTvYG4Wi-9XbZQ2T1-SbHhn-mqsToeLIGBGkzsugwQG9tIKG3Qr0BixDIfuhxux4Gdo30HCyn9SB5ZaY5wdxaD2_kJjnJih_SsAuuXRNAXEO_PgExnZ6Mr1qyqyOfwc3k9jmgRpuEQigYYRYOP-Tvs_i59IVYOdpsQ70gi-Ky09orx5Jy3hVJv-J45Dx7FHdR3ZPTn7pYW7IRmRo4CZ2COoCg
HTTP/1.1 200 OK
.....
--- CALL AGAIN, new bearer is generated
POST /mfp/api/az/v1/introspection HTTP/1.1
POST /mfp/api/preauth/v1/preauthorize HTTP/1.1
GET /mfp/api/az/v1/authorization?XXX HTTP/1.1
POST /mfp/api/az/v1/token HTTP/1.1
POST /com.costaisa.app.api/api/mfprest/delegation/detail/private HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImp3ayI6eyJrdHkiOiJSU0EiLCJlIjoiQVFBQiIsImtpZCI6IjM1NDcyYWNhLWVlNmItNGNhZi04OGQ2LWQxY2ExNjQ0NzM4NyIsIm4iOiJBTTBEZDd4QWR2NkgteWdMN3I4cUNMZEUtM0kya2s0NXpnWnREZF9xczhmdm5ZZmRpcVRTVjRfMnQ2T0dHOENWNUNlNDFQTXBJd21MNDEwWDlJWm52aHhvWWlGY01TYU9lSXFvZS1ySkEwdVp1dzJySGhYWjNXVkNlS2V6UlZjQ09Zc1FOLW1RSzBtZno1XzNvLWV2MFVZd1hrU093QkJsMUVocUl3VkR3T2llZzJKTUdsMEVYc1BaZmtOWkktSFU0b01paS1Uck5MelJXa01tTHZtMDloTDV6b3NVTkExNXZlQ0twaDJXcG1TbTJTNjFuRGhIN2dMRW95bURuVEVqUFk1QW9oMmluSS0zNlJHWVZNVVViTzQ2Q3JOVVl1SW9iT2lYbEx6QklodUlDcGZWZHhUX3g3c3RLWDVDOUJmTVRCNEdrT0hQNWNVdjdOejFkRGhJUHU4PSJ9fQ.eyJpc3MiOiJjb20uaWJtLm1mcCIsInN1YiI6IjM1NDcyYWNhLWVlNmItNGNhZi04OGQ2LWQxY2ExNjQ0NzM4NyIsImF1ZCI6ImNvbS5pYm0ubWZwIiwiZXhwIjoxNDgwMzM5OTU0NjE2LCJzY29wZSI6ImFvdkxvZ2luIn0.JSm3nrW6BD5i66GossHYM4-6GqQfC-ZSH5P-X4M9mws2jBNvCkFKgv_XbRAb3km-0NMZz3FHsrY_0h0dx7fpJYiR9CIjaY-PFw75zdKbyEpzbhAX7OjZtYOtZblKEYLkT8mH-0mLc6VE_YBPFd2q55HMmECCLirAAdWwzMGgEzL02OKTd1GVuJyjqjlxeOJypFglaHezuByd6eGVMFJvnfDX3h_o6k8sWcv-g7UFa8jtcMNZpbzFOYG9Q2nGQ-oYIt17QyF4CVKPMN4anMwRRQ_2cjuvg-1ZuU450hxBX3u09wBxJ21mQklgg72t7fdLKgT7EIPmQlPP3wrX9qzy7A
HTTP/1.1 200 OK
Update:
The HTTP 401 and 403 calls to the external resource and serveral calls to MFP can be avoided if the scope is send in WLResourceRequest
It generates a new token calling an external resource using an absolute URL but also calling a standard protected adapter using a relative URL
Sample calling a protected adapter:
var resourceRequest = new WLResourceRequest(
"/adapters/AOS42_AOV_API/resource/protectedResource",
WLResourceRequest.GET,
{'scope' : 'aovLogin'} // it avoids 401 and 403 responses
);
resourceRequest.send().then(
function (response) {
alert("response ok protectedResource " + response.responseText);
},
function (response) {
alert("response ko protectedResource " + response.responseText);
}
);
Sample calling an external resource:
var resourceRequest = new WLResourceRequest(
"https://someurl.com/someApp/protectedResource",
WLResourceRequest.GET,
{'scope' : 'aovLogin'} // it avoids 401 and 403 responses
);
Update 2:
We've made a change: Instead of calling to a protected external resource, receiving HTTP 401 and then sending the challenge, now we call to WLAuthorizationManager.login before.
In Android, it continues calling MFP 3 times before each call, but now the server returns the same Bearer Token.
The same Cordova Application calling the same Rest API protected by MFP and using the same security adapter in MFP works perfectly fine in iOS.
Once the bearer is obtained, we see only calls to the external API.
This bug has been resolved in a just-released iFix for MobileFirst Foundation 8.0. The build number is 8.0.0.0-IF20170125-0919. Please login to IBM Fix Central to download the iFix.
The associated APAR is:
PI74988 MULTIPLE AUTHORIZATION CALLS ARE MADE FOR EACH REST CALL IN ANDROID APPLICATION
Since you're using Cordova, I believe updating the cordova-plugin-mfp plug-in to #8.0.2017012210 should suffice.

Office 365 REST Calendar API for creating events failing with HTTP - 403 when authenticated using OAuth bearer token

My azure hosted web API uses the O365 Calendar and Mail REST APIs for creating events and mails on behalf of the users. All necessary permissions have been enabled for the corresponding Azure AD application. My question - Accessing the mail API using the Bearer OAuth token as part of the header succeeds but when I use the same token for the events API, it fails with a 403.
The Documentation I have been following for my implementation is the official msdn one and the update - https://social.msdn.microsoft.com/Forums/exchange/en-US/6fc135ae-f8f9-4b4d-b50b-f00a2bd79a30/office-365-rest-api-mail-calendar-contacts-update?forum=exchangesvrdevelopment
Fiddler trace (Raw view of request) -
POST https://outlook.office365.com/ews/OData/Me/Events HTTP/1.1
Accept: application/json
client-request-id: 00000000-0000-0000-0000-000000000000
Authorization: Bearer <OAuth token>
Content-Type: application/json; charset=utf-8
Host: outlook.office365.com
Content-Length: 287
Expect: 100-continue
{"Attendees":[{"EmailAddress":{"Address":"sample#sample.com","Name":null},"Type":"Required"}],"Body":{"Content":"Hello World","ContentType":"HTML"},"End":"2014-10-22T19:00:00Z","Location":{"DisplayName":"Conf Room M"},"Start":"2014-10-22T18:00:00Z","Subject":"Testing"}
Text view of response -
{"error":{"code":"ErrorAccessDenied","message":"Access is denied. Check credentials and try again."}}
Fiddler trace of the Mail API request that works fine -
POST https://outlook.office365.com/ews/OData/Me/sendmail HTTP/1.1
Accept: application/json
client-request-id: 00000000-0000-0000-0000-000000000000
Authorization: Bearer <OAuth Token>
Content-Type: application/json; charset=utf-8
Host: outlook.office365.com
Content-Length: 171
Expect: 100-continue
Connection: Keep-Alive
{"Message":{"Body":{"Content":"Test","ContentType":"HTML"},"Subject":"test","ToRecipients":[{"EmailAddress":{"Address":"sample#sample.com","Name":null}}]}}
Considering that you are getting a 403 (Forbidden) error for one API, I'd suggest you review the resources enabled for the application. Can you make sure you have Write permissions for the Calendar API? I know you mentioned that you've done this before, I'm just checking in case of the small chance you missed those Write perms.
Sorry for having kept this question hanging.
The issue was with the ClientSecret (either had stale permissions on it or was wrong in the first place). Generating a new one via the management portal fixed this issue.

twitter api issue

I'm integrating "Sign in with twitter account" function at my site.
So, I'm sending request to https ://twitter.com/oauth/request_token, getting token, making redirect to https ://twitter.com/oauth/authenticate?oauth_token=%oauth_token%
Then I recieving call back with oauth_token and oauth_verifier
This goes fine.
But than I need to call https ://api.twitter.com/1/account/verify_credentials.json to get authorizated client details
I'm sending:
GET https ://api.twitter.com/1/account/verify_credentials.json
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: q=0.8,en-us;q=0.5,en;q=0.3
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1
X-Auth-Service-Provider: https ://api.twitter.com/1/account/verify_credentials.json
X-Verify-Credentials-Authorization: OAuth realm="http://api.twitter.com/", oauth_signature="acYFjEgUrTcyb4FMBoJF8MlwZGw%3D", oauth_timestamp="1286899670", oauth_consumer_key="%CONSUMER_KEY%", oauth_nonce="268310006", oauth_token="%oauth_token%", oauth_version="1.0", oauth_signature_method="HMAC-SHA1"
%oauth_token% - token got when twitter redirects me back the cleint
%CONSUMER_KEY% - my twitter account's consumer key
And getting back
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, max-age=300
Connection: close
Date: Tue, 12 Oct 2010 16:07:45 GMT
Server: hi
Vary: Accept-Encoding
WWW-Authenticate: Basic realm="Twitter API"
{"error":"Could not authenticate you.","request":"/1/account/verify_credentials.json"}
Can anyone plz advice me what's wrong here?
Thanks!
After you receive the callback you have to make request to POST oauth/access_token to exchange the temporary request_token for a permanent access_token associated with the user. Once you receive the access_token you can perform the GET account/verify_credentials request.
Here is a good flow chart explaining how the full OAuth process works.
Flow Chart
It sounds like you're two thirds of the way through the authentication. Now you need to exchange your authorised request token for a permanent access token.
You are using header to pass parameters (X-Verify-Credentials-Authorization), instead you should be using GET method. If you are using php Zend framework's OAuth component, then it should look like
$client->setMethod(Zend_Http_Client::GET);