Basic HTTP and Bearer Token Authentication - rest

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'

Related

How to authenticate with TestRail API?

I'd like to use the TestRail API, but I am having authentication issues. I setup a Postman to play with the API and query it like:
https://my.testrail.io/index.php?/api/v2/get_users
I saw another SO question that used the Authorization header with basic authentication so I added that:
Authorization: Basic myemail#whatever.com:apikey
When I tried running this I got:
{
"error": "Authentication failed: invalid or missing user/password or session cookie."
}
I've also tried replacing the API key with my password, but that didn't work either. The cURL command generated by Postman is:
curl --location --request GET 'https://my.testrail.io/index.php?/api/v2/get_users' \
--header 'Authorization: Basic <EMAIL>:<APIKEY>' \
--header 'Cookie: tr_session=<GUID>'
I can go to https://my.testrail.io/index.php?/api/v2/get_users in my browser after logging in to TestRail and that does work.
You need to either add your email/key via "Authorization" tab in Postman or you need to encode them by yourself and put into "Authorization" header (Postman can do it for you when you use "Authorization" tab)

Getting Users and groups from Keycloak

I have a web application secured by Keycloak. Now I want to read all the security groups and users from keycloak in my application. Is it possible?
Keycloak has a very good documentation around the APIs.
I believe you are looking to get all the groups and users from the Keycloak. It could be as straightforward as calling any REST APIs.
You can follow this link to get all the groups from the Keycloak.
And this link to get the users based on the given search criteria.
But I would be wary of the performance implication it might have calling these APIs. Make sure to use pagination and appropriate filters for getting users.
Also, if you want, you can write a custom extension in Keycloak to serve your purpose. You can follow this link for it.
I could get the access token using the client secret key using the curl command from command line.
$curl -X POST -d "client_id=my_client" -d "username=username" -d "client_secret=c957b0ba-c421-4021-8433-764aa2fwes72" -d "grant_type=client_credentials" HOST/auth/realms/my_realm/protocol/openid-connect/token
I could also get the list of users after getting the access token
$curl -X GET HOST/auth/admin/realms/my_realm/users -H "Authorization: Bearer access-token" -H 'cache-control: no-cache'
Now, I'm thinking how can I do this from my web application.

Curl not working with CSRF token in REST POST

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 ?

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().

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.