I'm implementing a REST API that also provides functionality for authenticating users. Authentication requires an user to send a POST request with the following data in the body:
{
"userOrEmail": "spook",
"passowrd": "Test1234"
}
If the username and password match, the user gets back a token from the server, while if they don't, the server returns 401 Unauthorized, with the following header:
WWW-Authenticate: Credentials realm="http://localhost:9000/auth/users/credentials"
Is that header acceptable? realm contains the location where the user can try to authenticate again.
It appears to be acceptable, but maybe not optimal except under very specific conditions. From RFC1945:
The realm value (case-sensitive), in combination with the canonical root URL of the server being accessed, defines the protection space. These realms allow the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme and/or authorization database. The realm value is a string, generally assigned by the origin server, which may have additional semantics specific to the authentication scheme.
So, you can, but I might be paranoid about multiple applications using the same authentication and inadvertently cross-authenticating if they were to share the same realm name. Better would be to isolate the realm by application, just to be on the safe side.
No, it's not acceptable.
a) There is no authentication scheme called "credentials".
b) The purpose of the "realm" parameter is different.
Related
As a preface I'd like to claim I have some understanding of how the HTTP-supported authentication is supposed to work according to RFC 7235.
I am specifically interested to know how a client is supposed to know, after authenticating, which URIs on the server it is expected to provide same authorization (through the Authorization header) bearer for? Furthermore, is there any provision by HTTP to assist client in determining which Authorization headers it (the client) may have available (through whatever means it acquires them -- "login" form/dialog etc), would go with which realm(s)?
A realm doesn't seem to be specified in the form of an URI or even a regular expression of an URI, it's a value the interpretation of which appears to be left to the HTTP client application. Of note, a "Protection Space (Realm)" is defined, quoting:
A protection space is defined by the canonical root URI (the scheme and authority components of the effective request URI (see Section 5.5 of RFC7230) of the server being accessed, in combination with the realm value if present.
The above is all well and good, but it doesn't facilitate client mapping realms to URIs that may require authorization.
Say my Web server returns a response with status code 401 and the WWW-Authenticate: Bearer realm="The hangout" header line, for a request with a given URI, let's say /foobar. That makes it obvious that subsequent requests to the particular URI must include Authorization header line corresponding to solved challenge (as the client authenticates the user). No problem there. But what about e.g. requests with URI(s) that have the same pathname - those starting with /foobar/ -- is there an implication here that the same Authorization value is expected for these as well? What about entirely unrelated URI pathnames [on the same server]?
It would seem beneficial for the kind of authorization negotiation HTTP already does, to somehow relate or facilitate said relation of realms to URIs. But maybe I am missing something very obvious. Does HTTP do something along of what I am describing? Does it facilitate it in any way, at least, beyond leaving it entirely to the application? How would one realistically let the client determine which authorization bearer to send for which requests? Must it always get a 401 and a challenge response first, before knowing for sure requests to the particular URI and only said URI, must include related authorization bearer?
HTTP is a stateless protocol that deals with a request-response pair. The protocol does not deal with any information that would describe the concept of a "page", "site", "application", etc. Even though it deals with hypermedia, the protocol itself doesn't go beyond the concrete request. This means that you won't get any information from the protocol itself about any other paths under the same domain that are in the same authentication realm. This is left to the documentation of APIs or websites.
It seems to me that your research is centered on one type of authentication process that we call basic auth, know they are some other ways to authenticate a user and that they might suits your needs better as basic auth is kinda old as you can see on that RFC you linked.
To my understanding, the principle behind basic auth is to have a simple process based on challenges. When your client asks for a resource and that resource is protected by authentication, the server responds with a challenge : 401 Unauthorized with a header WWW-authenticate: Basic realm="some realm". The client then know the resource is restricted and depending on the realm, knows if it can have access (or asks the user for credentials for that realm), and try to access with a basic auth header : Authorization: Basic viFWGrwehryfviehtNRBRGWrwGERThRGE. You then repeat that process every time you need a resource.
HTTP and basic auth don't implement any sort of deeper and more complex system for authentication like you're searching for. It's one of the simplest system as its name implies and has not a lot more to offer. I'd even add that it's one of the riskier way to authenticate a system (even using SSL cert and cert pinning) as the client must send credentials for every single authenticated resource request.
In case you want to search other ways to authenticate requests, here are some :
OAuth (2.0) (most secured and complex)
Bearer (JWT or session tokens)
API keys
After the user requests a protected resource X the server responds
with code 401.
The browser prompts the user to inser user-name and
password and automatically re-send the request to the server with
those authentication information
My question is : is this process repeated over and over for each protected resource ?
Look at RFC 2617. There is stated for basic-athentication :
Upon receipt of an unauthorized request for a URI within the
protection space, the origin server MAY respond with a challenge ...
and also
A client SHOULD assume that all paths at or deeper than the depth of
the last symbolic element in the path field of the Request-URI also
are within the protection space specified by the Basic realm value of
the current challenge. A client MAY preemptively send the
corresponding Authorization header with requests for resources in
that space without receipt of another challenge from the server.
Similarly, when a client sends a request to a proxy, it may reuse a
userid and password in the Proxy-Authorization header field without
receiving another challenge from the proxy server.
So, from the server side this may occur at any request the the server deems unauthenticated. If resource Y does not share the prefix that had been yuthenticated with resource X then the server will re-request authentication.
For avoiding this the authentication scheme e.g. could request authentication for a common prefix of the related resources , such that authentication for prefix of resource X also covers resource Y as a prefix. This will allow the client to send the authentication header and cause the server to detect the call as already being authenticated.
Once the user input the password, the browser will remember it.
each time the client request the resource at the same website, the browser will send the authentication header automatically.
I have a web service REST API on a secure ASP.NET website which requires a login to work. What is the most secure way to request the username/password programatically? (just adding a ?username=me&password=mysecret to the URL doesn't seem all that secure to me (even though this is a HTTPS connection).
There are several ways to achieve what you need:
[WRONG WAY] One could pass the username and password along with the query string. In theory there is nothing wrong with this practice, but such a URL (http://example.com?username=me&password=mysecret) is usually cached by browsers, proxies, etc and thus leverage a potential risk that someone else can access to your protected data by using these stored data.
[GOOD WAY] In order to remove "almost all" risks related to caching abilities of browsers, proxies, etc. and moreover in order to use standard features of the HTTP protocol, you have to deal with the special HTTP Authorization header.
The HTTP Authorization header :
If you are using HTTP S connections, then you can use the Basic Access Authentication method.
The Authorization header is constructed as follows:
Username and password are combined into a string "username:password".
The resulting string literal is then encoded using Base64.
The authorization method and a space i.e. "Basic " is then put before the encoded string.
For example, if the user agent uses 'Aladdin' as the username and 'open sesame' as the password then the header is formed as follows:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
If you are using HTTP connections, then you should use the Digest Access Authentication method. Because it's more complicated and useless with HTTPS connections, I let you read more about it if you want (here maybe).
I am building a web service that exclusively uses JSON for its request and response content (i.e., no form encoded payloads).
Is a web service vulnerable to CSRF attack if the following are true?
Any POST request without a top-level JSON object, e.g., {"foo":"bar"}, will be rejected with a 400. For example, a POST request with the content 42 would be thus rejected.
Any POST request with a content-type other than application/json will be rejected with a 400. For example, a POST request with content-type application/x-www-form-urlencoded would be thus rejected.
All GET requests will be Safe, and thus not modify any server-side data.
Clients are authenticated via a session cookie, which the web service gives them after they provide a correct username/password pair via a POST with JSON data, e.g. {"username":"user#example.com", "password":"my password"}.
Ancillary question: Are PUT and DELETE requests ever vulnerable to CSRF? I ask because it seems that most (all?) browsers disallow these methods in HTML forms.
EDIT: Added item #4.
EDIT: Lots of good comments and answers so far, but no one has offered a specific CSRF attack to which this web service is vulnerable.
Forging arbitrary CSRF requests with arbitrary media types is effectively only possible with XHR, because a form’s method is limited to GET and POST and a form’s POST message body is also limited to the three formats application/x-www-form-urlencoded, multipart/form-data, and text/plain. However, with the form data encoding text/plain it is still possible to forge requests containing valid JSON data.
So the only threat comes from XHR-based CSRF attacks. And those will only be successful if they are from the same origin, so basically from your own site somehow (e. g. XSS). Be careful not to mistake disabling CORS (i.e. not setting Access-Control-Allow-Origin: *) as a protection. CORS simply prevents clients from reading the response. The whole request is still sent and processed by the server.
Yes, it is possible. You can setup an attacker server which will send back a 307 redirect to the target server to the victim machine. You need to use flash to send the POST instead of using Form.
Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=1436241
It also works on Chrome.
It is possible to do CSRF on JSON based Restful services using Ajax. I tested this on an application (using both Chrome and Firefox).
You have to change the contentType to text/plain and the dataType to JSON in order to avaoid a preflight request. Then you can send the request, but in order to send sessiondata, you need to set the withCredentials flag in your ajax request.
I discuss this in more detail here (references are included):
http://wsecblog.blogspot.be/2016/03/csrf-with-json-post-via-ajax.html
I have some doubts concerning point 3. Although it can be considered safe as it does not alter the data on the server side, the data can still be read, and the risk is that they can be stolen.
http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/
Is a web service vulnerable to CSRF attack if the following are true?
Yes. It's still HTTP.
Are PUT and DELETE requests ever vulnerable to CSRF?
Yes
it seems that most (all?) browsers disallow these methods in HTML forms
Do you think that a browser is the only way to make an HTTP request?
I need to authenticate a client when he sends a request to an API. The client has an API-token and I was thinking about using the standard Authorization header for sending the token to the server.
Normally this header is used for Basic and Digest authentication. But I don't know if I'm allowed to customize the value of this header and use a custom authentication scheme, e.g:
Authorization: Token 1af538baa9045a84c0e889f672baf83ff24
Would you recommend this or not? Or is there a better approach for sending the token?
You can create your own custom auth schemas that use the Authorization: header - for example, this is how OAuth works.
As a general rule, if servers or proxies don't understand the values of standard headers, they will leave them alone and ignore them. It is creating your own header keys that can often produce unexpected results - many proxies will strip headers with names they don't recognise.
Having said that, it is possibly a better idea to use cookies to transmit the token, rather than the Authorization: header, for the simple reason that cookies were explicitly designed to carry custom values, whereas the specification for HTTP's built in auth methods does not really say either way - if you want to see exactly what it does say, have a look here.
The other point about this is that many HTTP client libraries have built-in support for Digest and Basic auth but may make life more difficult when trying to set a raw value in the header field, whereas they will all provide easy support for cookies and will allow more or less any value within them.
In the case of CROSS ORIGIN request read this:
I faced this situation and at first I chose to use the Authorization Header and later removed it after facing the following issue.
Authorization Header is considered a custom header. So if a cross-domain request is made with the Autorization Header set, the browser first sends a preflight request. A preflight request is an HTTP request by the OPTIONS method, this request strips all the parameters from the request. Your server needs to respond with Access-Control-Allow-Headers Header having the value of your custom header (Authorization header).
So for each request the client (browser) sends, an additional HTTP request(OPTIONS) was being sent by the browser. This deteriorated the performance of my API.
You should check if adding this degrades your performance. As a workaround I am sending tokens in http parameters, which I know is not the best way of doing it but I couldn't compromise with the performance.
This is a bit dated but there may be others looking for answers to the same question. You should think about what protection spaces make sense for your APIs. For example, you may want to identify and authenticate client application access to your APIs to restrict their use to known, registered client applications. In this case, you can use the Basic authentication scheme with the client identifier as the user-id and client shared secret as the password. You don't need proprietary authentication schemes just clearly identify the one(s) to be used by clients for each protection space. I prefer only one for each protection space but the HTTP standards allow both multiple authentication schemes on each WWW-Authenticate header response and multiple WWW-Authenticate headers in each response; this will be confusing for API clients which options to use. Be consistent and clear then your APIs will be used.
I would recommend not to use HTTP authentication with custom scheme names. If you feel that you have something of generic use, you can define a new scheme, though. See http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p7-auth-latest.html#rfc.section.2.3 for details.
Kindly try below on postman :-
In header section example work for me..
Authorization : JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyIkX18iOnsic3RyaWN0TW9kZSI6dHJ1ZSwiZ2V0dGVycyI6e30sIndhc1BvcHVsYXRlZCI6ZmFsc2UsImFjdGl2ZVBhdGhzIjp7InBhdGhzIjp7InBhc3N3b3JkIjoiaW5pdCIsImVtYWlsIjoiaW5pdCIsIl9fdiI6ImluaXQiLCJfaWQiOiJpbml0In0sInN0YXRlcyI6eyJpZ25vcmUiOnt9LCJkZWZhdWx0Ijp7fSwiaW5pdCI6eyJfX3YiOnRydWUsInBhc3N3b3JkIjp0cnVlLCJlbWFpbCI6dHJ1ZSwiX2lkIjp0cnVlfSwibW9kaWZ5Ijp7fSwicmVxdWlyZSI6e319LCJzdGF0ZU5hbWVzIjpbInJlcXVpcmUiLCJtb2RpZnkiLCJpbml0IiwiZGVmYXVsdCIsImlnbm9yZSJdfSwiZW1pdHRlciI6eyJkb21haW4iOm51bGwsIl9ldmVudHMiOnt9LCJfZXZlbnRzQ291bnQiOjAsIl9tYXhMaXN0ZW5lcnMiOjB9fSwiaXNOZXciOmZhbHNlLCJfZG9jIjp7Il9fdiI6MCwicGFzc3dvcmQiOiIkMmEkMTAkdTAybWNnWHFjWVQvdE41MlkzZ2l3dVROd3ZMWW9ZTlFXejlUcThyaDIwR09IMlhHY3haZWUiLCJlbWFpbCI6Im1hZGFuLmRhbGUxQGdtYWlsLmNvbSIsIl9pZCI6IjU5MjEzYzYyYWM2ODZlMGMyNzI2MjgzMiJ9LCJfcHJlcyI6eyIkX19vcmlnaW5hbF9zYXZlIjpbbnVsbCxudWxsLG51bGxdLCIkX19vcmlnaW5hbF92YWxpZGF0ZSI6W251bGxdLCIkX19vcmlnaW5hbF9yZW1vdmUiOltudWxsXX0sIl9wb3N0cyI6eyIkX19vcmlnaW5hbF9zYXZlIjpbXSwiJF9fb3JpZ2luYWxfdmFsaWRhdGUiOltdLCIkX19vcmlnaW5hbF9yZW1vdmUiOltdfSwiaWF0IjoxNDk1MzUwNzA5LCJleHAiOjE0OTUzNjA3ODl9.BkyB0LjKB4FIsCtnM5FcpcBLvKed_j7rCCxZddwiYnU