Twitter Oauth possible cause for 400 Bad Request response using a simple REST client - rest

I've generated Access Tokens in the Settings/..../ Keys and Access Tokens page and now have a
Consumer Key
Consumer Secret Key
Owner ID (even though this was probably already generated)
Access Token
Access Token Secret
and am using a rest client to test being able to pull the latest 3 statuses using this api end point
https://api.twitter.com/1.1/statuses/user_timeline.json?user_id=userIdHere&count=3
as well as the following headers
Accept: /
Connection: close
User-Agent: OAuth gem v0.4.4
Content-Type: application/x-www-form-urlencoded
Content-Length: 76
Host: api.twitter.com
Authorization: OAuth
oauth_consumer_key=
oauth_signature=
oauth_signature_method=
oauth_timestamp=
oauth_token=
oauth_version=
obviously the 'userIdHere' in the end point address (above) is substituted with my username (i know i can also use my user_id, but that's beside the point) as well as the 'Authorization' values being substituted for real values. That's where my question lies...
What is the mapping for each of the 'oauth...' authorization parameters to their associated Twitter generated and provided Token or key(s) (which were mention near the top of the post)?
I keep getting a '400 Bad Request' response and feel that it is the authorization that is failing in that the permutations of key placements is incorrect. I do not know which value goes to which 'oauth...' value
finally, the structure of the 'Authorization' parameter header is as follows (as per instruction here from the Twitter EXAMPLE) as one line string value
OAuth oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog", oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg", oauth_signature="tnnArxj06cWHq44gCs1OSKk%2FjLY%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1318622958", oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb", oauth_version="1.0"
)
I am just trying to use a GET to get the last 3 statuses and have not been able to. Also, i plan to switch the values to Environmental Variables, but that doesn't matter yet..
UPDATE
using Postman now, and it's better at mapping, but now am getting
{
"errors": [
{
"code": 32,
"message": "Could not authenticate you."
}
]
}

For the Postman part make sure that you leave Timestamp and nonce empty and hit "update request" before you hit send. That will generate timestamp and nonce - otherwise you will get authorization failures every time. I just tried it with my twitter API credentials and it works.
For Oauth gem code, I find it strange that you have a Content-Type and a Content-Length header for a GET request. Looks like the 400 Bad request could be because you are attempting to do a POST to an endpoint that only supports GET. Indeed when I try to do a POST to that endpoint it tells me.
{
"errors": [
{
"code": 86,
"message": "This method requires a GET or HEAD."
}
]
}
So the 400 is actually good news - it means that authorization works, you are just calling the API in the wrong way.

Related

"Missing Authentication Token" Error when calling DVLA MOT history API with Postman

Note - I am very much new to all this. Apologies if anything is unclear.
My overriding aim is to pull out MOT history data for a large batch of vehicles from the DVLA API. I understand that this can be done using Postman, which I am using (on a 64-bit Windows laptop if at all relevant).
The DVLA provide the following instructions
====================================================
Getting started
All API interfaces are implemented as restful APIs and accessed over https.
To access API you will need an API key that uniquely identifies the source of the request. DVSA will give you an API key if it approves your application.
You should keep your API key secure, as DVSA manages throttling and quotas at an API key level.
Each request must have the following mandatory fields in the header:
Accept: application/json+v6
x-api-key:
Content-type field confirms that the response type is in JSON format, and the x-api-key field serves your API key to identify the source of the request.
Technical resources
Access the API at https://beta.check-mot.service.gov.uk/
This root URL will change when the service moves from beta to live.
These 4 endpoints equate to the 4 methods of using the API:
/trade/vehicles/mot-tests?registration={registration}
‘Registration’ is the vehicle registration number.
===================================================
In order to test that this is possible, I am entering the following single request into the bar in Postman, selecting "POST" and hitting "SEND"
https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?Content-type=application/json&x-api-key=ABCDEFGH&registration=MYREG
n.b. no inverted commas or other punctuation surrounds the actual values for ABCDEFH or MYREG
Expected result: Some sort of JSON with MOT history for this vehicle
Actual result: {"message": "Missing Authentication Token"}{"message": "Missing Authentication Token"}
I am unclear on:
- whether I should be using POST
what the +v6 after the application is necessary (other documentation leaves it out)
Why "Accept" and "Content-type" appear to be used interchangeably in the documentation
Whether the ordering of the parameters matters
Whether this can be equally tested by simply pasting the url into a browser
Thanks for any help
Reading through the Documentation found here:
https://dvsa.github.io/mot-history-api-documentation/
It mentions that those fields should be added as Headers:
Each request must have the following mandatory fields in
the header:
- Accept: application/json+v6
- x-api-key: <your api key>
There are example cURL requests on the site to help you with creating the request.
If you use Postman's Import feature within the app (found in the top right), you can add this cURL request in the Paste Raw Text tab.
curl -H "Accept: application/json+v6" -H "x-api-key: <your_api_key>" https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests\?registration=ZZ99ABC
This will give you an example request of what it should look like. From here, you will be able to add in your own API Token and send the request.
If you are using Postman, you can use the Authorization tab right under the request to give the required mandatory header fields. Select Header from Add to drop down. You can also add additional headers information using the next tab named Headers. (for example, the accept-headers).
Edit:
Authorization:
Headers Tab
Normally, you should be getting the authorization token when you register to the site in question(x-api-key here).You need to figure out the value of that token from the initial call's response headers. According to the document which Danny shared, you will be getting x-api-key from them once they approve your request.
Edit:
Alternatively, you can use import feature as Danny suggested in his answer. At the end of the day, you need to add the values as headers instead of query parameters.
For anyone using Python with the MOT history api and getting the same error message, try GET:
import requests
url = f'https://beta.check-mot.service.gov.uk/trade/vehicles/mot-tests?registration={plate_number}'
payload = {}
headers = {
'Accept': 'application/json+v6',
'x-api-key': 'your-api-key'}
response = requests.get(url, headers=headers, data=payload)
data = response.json()
model = data[0]['model'] # get the vehicle model for example
print(model)

Generate API signature in request header from parameters in the request body

I'm using OWASP ZAP to test our API. We have a couple of POST endpoints which use an API Token and a shared secret for authentication and validating the request.
Some parameters of the request body are concatenated and hashed using the shared secret. This value is inserted into the request header.
How can I programatically generate this signature using OWASP ZAP?
Request Header
Content-Type: "application/json"
Accept: "application/json"
API-Key: {API_KEY}
Signature: {hash(field_one + field_two + field_three + SHARED_SECRET)}
Request Body
{
"field_one": "abc",
"field_two": "123",
"field_three": "xyz"
}
The SHARED_SECRET is the password that is stored locally by the client and used to hash the three fields from the request.
It is stored on the server along with the API-Key so that requests can be identified and validated.
Use an HTTP Sender Script. Create it in the ZAP UI so that you can test it as you're writing it. First make sure you are just detecting the requests you want to change, then extract the field values you need and finally generate the hash. Keep testing at each stage to make sure its doing what you need. And if you need specific help theres always the zaproxy-scripts group.

First REST API POST request succeeds but subsequent calls fail with 400 Bad Request

I am making a POST request to a REST API. This POST call succeeds on the first attempt with a HTTP status 200 and I get the correct result. However, when I make the next and subsequent calls, I get a HTTP 400 Bad Request Error. Why is it Bad Request when the previous call succeeded ?
When searching Bing, I found out that this could be related to submitting the same request. If I change some parameter in my payload, the call succeeds.
Any thoughts on what could be causing this? Am I missing something in request headers?
This is my POST Call.
POST http://myServer/v1.0/something/queries HTTP/1.1
Host: myServer
Authorization: Bearer some big token
Content-Type: application/json
Content-Length: 72
{
"field1": {
"Id": "12345"
},
"count": 1
}
In a lot of APIs, POST data is checked to confirm it is not a duplicate. This is important for some types of business logic such as ensuring there is only one user with some email address for example. In your request, I imagine it may be the "Id" field that is causing the HTTP 400 Bad Request since there is already an object with that "Id" in the system.

Which HTTP code should be return from REST API?

im currently working on a website which has Spring at backend and Angularjs at front side and we had discussed about back end responses to handle frontend's message dialogs and i have a question to ask:
Lets say i have an API :
GET : /getstatistics
Request params : fromTime,toTime ( in timestamp format)
And if client make a request with invalid params like a string, which response code should be returned from server ? HTTP 400 bad request and response body with a message " fromTime and toTime should be in timestamp format" or HTTP 200 with same message?
I saw some Google's APIs for example Oauth, they're returning code 200 for a request with invalid access_token but ,in our project my opinion it should be HTTP 400 because Javascript has success and error callbacks, is it better for it just pop a red color dialog with message inside rather than a HTTP 200 code then still need to check the content of the message?
Any advides and opinions are appreciated.
Thanks!
You should be returning a 400 error for bad request. Check out this reference.
The server cannot or will not process the request due to something
that is perceived to be a client error (e.g., malformed request
syntax, invalid request message framing, or deceptive request
routing).
Please have a look at RFC7231#section-6
A client MUST understand the class of any status code, as indicated by
the first digit
and,
4xx (Client Error): The request contains bad syntax or cannot be
fulfilled
Bad syntax can be something like you've mentioned in your question (making a request with invalid parameters, like a string).
I keep these two references handy whenever I'm designing RESTful APIs, might be helpful for you too:
https://httpstatuses.com/
http://www.restapitutorial.com/httpstatuscodes.html
Yes you are right, the http code should be 400 in your case. Your discussion here normally should be whether you need to return 400 or 422. For this you can check the accepted response for this SO question 400 vs 422 response to POST of data
I think it has something to do with how the parameters are used. If you use the resource, then a 404 should return. If the data is simply not valid then we decide to set a 409 Status to the request. It can't full fill it at 100% because of missing/invalid parameter.
HTTP Status Code "409 Conflict" was for us a good try because it's
definition require to include enough information for the user to
recognize the source of the conflict.
Reference: w3.org/Protocols/
Edit:
In any case, the status code 200 is incorrect here because there is an error. In response, you can then return specific information like this:
{
"errors": [
{
"userMessage": "Sorry, the parameter xxx is not valid",
"internalMessage": "Invalid Time",
"code": 34,
"more info": "http://localhost/"
}
]
}

insufficient_scope errors with /me/activities feed

I am failing at retrieving my activities feed (/me/activities) from Soundcloud & thought someone might be able to point out what I'm doing incorrectly.
I can access the /connect endpoint, but only if I specify a scope value of non-expiring. Using a value of * returns the error invalid_scope with an error_description of:
The requested scope is invalid, unknown or malformed.
I can exchange the resulting code for a token at the /oauth2/token endpoint, but only when setting grant_type to client_credentials.
I've attempted to request /me/activities with both GET and POST, providing oauth_token (and trying with and without a limit argument) and am being met with a 403 response * the following response header error:
OAuth realm="SoundCloud", error="insufficient_scope"
Requesting a grant_type of authorization_code when requesting at /oauth2/token fixed the issue.