Curl not working with CSRF token in REST POST - rest

REST: POST fails with CSRF enabled, though it works in POSTMAN.
I have added several headers like -H Set Cookie: JSESSIONID=xxxx along with -H X-CSRF-TOKEN: bbbb, -b cookies.txt after generating it. I would like to know what exactly has to be added to make the request work ?

Related

Keycloak: Login Disabled User Gives HTTP 400 (Bad Request)

I'm using version 3.4.3 of Keycloak. When I deactivate a user using PUT and setting the enabled flag to false, he cannot login anymore. This is exactly what I want. However, instead of a HTTP status code 403 (Access denied) or 401 (Unauthorized) that I'd expect to get from a login attempt of a deactivated user, I get a 400 (Bad Request) instead. When I reactivate the user, using PUT and setting the enabled flag back to true, he can login again.
Here's my curl script:
token=`cat .file_containing_admins_token`
curl -v -X PUT -H "Content-Type: application/json" -H "Authorization: Bearer $token" --data "{\"enabled\": false}" "http://localhost:8080/auth/admin/realms/[my-realm]/users/[user-id-to-block]"
The documentation is rather terse on status codes.
There's also a second, more specific API endpoint PUT /{realm}/users/{id}/disable-credential-types. But there I am missing to re-enable the credential, which is a requirement for my use case.

Cannot call the PayPal Sync API due to Authorization Failure

I'm trying to use the relatively new PayPal Sync API to download my PayPal transactions. I'm following the Sync API guide. I started by logging into the PayPal Developer Dashboard My Apps & Credentials page, scrolling to the REST API apps section, creating an app, clicking on it, and enabling Transaction Search for both the Sandbox and Live accounts.
I then used the Sandbox account's Client ID and Secret to generate an Access Token. I confirmed that the Client ID and Secret are correct and active. My cURL command is below (note that I'm using cURL on Windows 10):
curl -v https://api.sandbox.paypal.com/v1/oauth2/token ^
-H "Accept: application/json" ^
-H "Accept-Language: en_US" ^
-u "<my-client-id>:<my-secret>" ^
-d "grant_type=client_credentials"
I received a response similar to the following (I added the formatting):
{
"scope":"https://uri.paypal.com/services/reporting/search/read
https://api.paypal.com/v1/payments/.*
https://uri.paypal.com/services/applications/webhooks
openid",
"nonce":"2018-04-04T02:20:02Z...",
"access_token":"<my-access-token>",
"token_type":"Bearer",
"app_id":"<my-app-id>",
"expires_in":32400
}
I then took the Access Token and copied it into the sample command on the Sync API guide page. Here is the command I ran:
curl -v -X GET https://api.sandbox.paypal.com/v1/reporting/transactions?transaction_id=5TY05013RG002845M&fields=all&page_size=100&page=1 ^
-H "Content-Type: application/json" ^
-H "Authorization: Bearer <my-access-token>"
I received the following error response:
< HTTP/1.1 401 Unauthorized
...
< Content-Length: 244
< Connection: close
< Content-Type: application/json
<
{
"name":"AUTHENTICATION_FAILURE",
"message":"Authentication failed due to invalid authentication credentials or a missing Authorization header.",
"links":[{
"href":"https://developer.paypal.com/docs/api/overview/#error",
"rel":"information_link"
}]
}
I tried many things to correct this error, including:
Adding a "Accept: application/json" and "Accept-Language: en_US" header to the command.
Creating a new Secret and generating a new Access Token.
Creating a new App with a new Client ID & Secret and generating a new Access Token.
Disabling Transaction Search, re-enabling it, and sending the command again.
Trying in the Live account.
Each of these attempts produced the same result. I noted that in the scope section of the access token response that it doesn't include a path similar to the stated path for the Sync API (/v1/reporting/transactions). However, that's just an observation, and I'm not sure if that is relevant.
I read through the entire Sync API guides and documentation about five times, and I searched Google and StackOverflow pretty thoroughly. I'm seeing evidence that some people are getting past the initial connection to Sync API, so I'm fairly certain this API works.
Can someone help me understand what I'm missing? Could it just be that I need to wait a day or two for their systems to catch up? PayPal's Developer documentation is not very user-friendly, and their Developer Dashboard is extremely glitchy.
I had this same issue. Putting double quotes around the URL solved it for me. The other API endpoints worked (authentication, authorizations/xyz) because they didn't have any special URL characters in them. In the transaction search, the query string delimiters were being parsed by Bash.
Your curl lines above become:
curl -v -X GET "https://api.sandbox.paypal.com/v1/reporting/transactions?transaction_id=5TY05013RG002845M&fields=all&page_size=100&page=1" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <my-access-token>"
Hope that helps someone.
It appears that this error may be caused by either cURL or the way I'm using it. On a hunch, I used Hurl.it to execute this sample request, and the request was successful (HTTP 200). I then tried another request where I searched for all transactions in a given date range, and that was also successful. I'm going to mark the question answered.

Uber Rush API Sandbox

Trying to test Uber Rush API (from localhost and from linux server).
Calling Token works - I get the token
trying to implement sanbox example:
curl -X "PUT /v1/sandbox/deliveries/{delivery_id}" \
-H "Authorization: Bearer <OAUTH TOKEN>" \
-d "{\"status\":\"en_route_to_pickup\"}"
with url https://sandbox-api.uber.com/
and I tried the same request with file_get_contents (in PHP)
So, I always get error "405 Method Not Allowed"
{"message":"Method not supported for this endpoint.","code":"method_not_allowed"}
What I need to do to get access to method from this sandbox example https://developer.uber.com/docs/rush/sandbox?
Corrent syntax
curl -X "PUT" -H "Authorization: Bearer <TOKEN>" -H "Content-Type: application/json" -d "{\"status\":\"en_route_to_pickup\"}" https://sandbox-api.uber.com/v1/sandbox/deliveries/DELIVERY_ID
EDIT: Updated to reflect both issues in your question...
You have a mismatch in your requests and an incorrect syntax for curl.
First off your CURL request is incorrectly specified. It should be:
curl -X "PUT" -H "Authorization: Bearer <OAUTH TOKEN>" -d "{\"status\":\"en_route_to_pickup\"}" https://sandbox-api.uber.com/v1/sandbox/deliveries/{delivery_id}
In addition, your curl command is trying to issue a PUT request to the uber sandbox PUT API. However, your PHP code is not setting the context correctly and so is probably issuing a GET request. I suspect that the server is therefore rejecting the request as a GET as not allowed to do this sort of operation.
To fix it, see Bad request using file_get_contents for PUT request in PHP. This should give you an example of how to pass in the necessary context to issue a PUT request using file_get_contents().

Basic HTTP and Bearer Token Authentication

I am currently developing a REST-API which is HTTP-Basic protected for the development environment. As the real authentication is done via a token, I'm still trying to figure out, how to send two authorization headers.
I have tried this one:
curl -i http://dev.myapp.com/api/users \
-H "Authorization: Basic Ym9zY236Ym9zY28=" \
-H "Authorization: Bearer mytoken123"
I could for example disable the HTTP-Authentication for my IP but as I usually work in different environments with dynamic IPs, this is not a good solution. So am I missing something?
Try this one to push basic authentication at url:
curl -i http://username:password#dev.myapp.com/api/users -H "Authorization: Bearer mytoken123"
^^^^^^^^^^^^^^^^^^
If above one doesn't work, then you have nothing to do with it. So try the following alternates.
You can pass the token under another name. Because you are handling the authorization from your Application. So you can easily use this flexibility for this special purpose.
curl -i http://dev.myapp.com/api/users \
-H "Authorization: Basic Ym9zY236Ym9zY28=" \
-H "Application-Authorization: mytoken123"
Notice I have changed the header into Application-Authorization. So from your application catch the token under that header and process what you need to do.
Another thing you can do is, to pass the token through the POST parameters and grab the parameter's value from the Server side. For example passing token with curl post parameter:
-d "auth-token=mytoken123"
Standard (https://www.rfc-editor.org/rfc/rfc6750) says you can use:
Form-Encoded Body Parameter: Authorization: Bearer mytoken123
URI Query Parameter: access_token=mytoken123
So it's possible to pass many Bearer Token with URI, but doing this is discouraged (see section 5 in the standard).
If you are using a reverse proxy such as nginx in between, you could define a custom token, such as X-API-Token.
In nginx you would rewrite it for the upstream proxy (your rest api) to be just auth:
proxy_set_header Authorization $http_x_api_token;
... while nginx can use the original Authorization header to check HTTP AUth.
With nginx you can send both tokens like this (even though it's against the standard):
Authorization: Basic basic-token,Bearer bearer-token
This works as long as the basic token is first - nginx successfully forwards it to the application server.
And then you need to make sure your application can properly extract the Bearer from the above string.
I had a similar problem - authenticate device and user at device. I used a Cookie header alongside an Authorization: Bearer... header. One header authenticated the device, the other authenticated the user. I used a Cookie header because these are commonly used for authentication.
curl --anyauth
Tells curl to figure out authentication method by itself, and use the
most secure one the remote site claims to support. This is done by
first doing a request and checking the response- headers, thus
possibly inducing an extra network round-trip. This is used
instead of setting a specific authentication method, which you can
do with --basic, --digest, --ntlm, and
--negotiate.
There is another solution for testing APIs on development server.
Set HTTP Basic Authentication only for web routes
Leave all API routes free from authentication
Web server configuration for nginx and Laravel would be like this:
location /api {
try_files $uri $uri/ /index.php?$query_string;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
auth_basic "Enter password";
auth_basic_user_file /path/to/.htpasswd;
}
Authorization: Bearer will do the job of defending the development server against web crawlers and other unwanted visitors.
You can use Body with x-www-form-url-encoded to send with multiple headers.
curl --location --request POST 'http://dev.myapp.com/api/users' \
--header 'Authorization: Basic Ym9zY236Ym9zY28=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'access_token=mytoken123'

OpenId via Curl

How can I do OpenId based authentication using Curl?
At first place can I do it?
Regards,
Allahbaksh
I suppose you are talking about the curl command line, not the library. I have not tried, but according to what I know of OpenID and curl, it should be possible. However, not fully automated. You'll have to "parse" the content of the identity provider and of the content provider login pages if you want to be realy restful and generic. If you know where you're going and don't mind to couple your service and client (no hateoas), you can first authenticate with the identity provider, e.g.:
curl -iSsL --user-agent 'Mozilla/5.0' --cookie cookies --cookie-jar cookies \
--data login=$mylogin \
--data passwd=$mypasswd \
https://identprovider.example.com/login
and then post your OpenID to the content provider:
curl -iSsL --user-agent 'Mozilla/5.0' --cookie cookies --cookie-jar cookies \
--data openid="$myopenidurl" \
http://contentprovider.example.com/login
This suppose that the content provider is already authorised to use the identity provider.
Then get your content:
curl -iSsL --user-agent 'Mozilla/5.0' --cookie cookies --cookie-jar cookies \
http://contentprovider.example.com/interesting/content
Note that this approach is not restful, since I hard encoded the POST uris and fields in the code. To decouple the client and the server, the uris and field names must be extracted from responses. In a bash script, you can use sed for example.
I think is should work, but if not, then you'll have to realy follow the redirects and extract URIs and forms, since some params can be passed in the redirect URIs or in hidden form fields.