Passing username and password in HTTP GET query parameters - rest

I'm building a RESTful API for my application and I would like to make it as clean and transparent as possible.
I need to create an authentication endpoint and it makes most sense to me to build it so that users can authenticate in a following way:
GET https://example.com/
auth?identity=<username_or_email>&password=<password>
As I said, passing the user auth data using HTTP GET method in query parameters just seems very clean to me.
But I would like you to ask about how secure it actually is. Considering it will be encrypted through SSL/TLS, do you think it's a good idea to transfer user credentials like this?

As Display Name said, both variants are basically plain text (even using base64 encoding). So you must use TLS or another protection like HMAC
But from other side, Query string is less secure in terms of how Server/Client works with URLs in general. You can read about this here or here. Briefly you should be worry about the following
URLs are stored in web server logs
URLs are stored in the browser history
URLs are passed in Referrer headers

Well I basically pass base64 string to the server.
My username and password are converted in base64 and then passed in Authorization Header
Authorization : "Basic --Value"
I find this the cleanest way of passing username and password to the server.
On the other end , server had a module called passport.Passport provides different type of Authorization and Authentication like Basic,bearer,token or even your own custom.
For the above purpose i use Basic Module.

From a security point of view it does not matter if you pass credentials as query parameters or in the Authentication headers. Both are basically plain text. So you must use TLS.
From a REST point of view, your URL looks like RPC: You call a method auth that accepts two parameters identity and password. What is the REST resource this URL represents? What happens if you make a second GET request with identical parameters? What is the response?

Related

Authentication Practices with Node Express

I built a simple authentication system for my backend API with Express using Cookie-Parser and/or sending the Token to the front end.
It works like this: the user makes a post request to the login route with the username and password, and if it matches, he gets back both a .json response with the token and a cookie set with the token.
I thought it would be nice for the frontend development and authorization purposes to have the current user available in every successive request after the login. So, I set a middleware that searches if there is a token, tries to find a user in database with the corresponding ID, and set the user info (without the password) as a parameter in the request object (req.user).
What I wanted to know is:
Is it a bad practice to put the user info in the request? Does it lead to security problems? Or maybe the database query in every request could overload the server if the app scales to much?
This is my first backend API, I'm trying out different ways of doing things, but I'm not aware of the best practices in the field. Any help is very much appreciated!
That is why there is encryption and in this context it is an ssl ticket. If you add login details to the request you NEED to make sure that the http response is encrypted. Once it is encrypted it is ok to do what you are doing. If it is not, an eaves dropper can snatch up that data from sniffing on your network.

Can a HTTP GET request on REST web service be safe?

I'm currently working on a new REST Web Service, developed in Django REST Framework, and while defining URLs I had a doubt about it's security. Following the standards that defined GET method for list data from a database, I doesn't understand if this can be a safe method to bring data.
Imagine this situation:
I access an URL /patients defined to return a list of patients. This list is not public and can only be requested by authorized users. Since not all users can see all patients, I create an hash code that works as key, allowing to list patients for that specific user. If no hash code provide, the method returns an 403 forbiden.
It work something like this: /patients/HASHCODE
Since my hash code is request in the URL and not inside of the body of HTTP message, like it would be if done by POST method, this looks unsafe me. I know that SSL can hide some information of requests, but not about a GET request. And of course this hash should not be visible for no one.
Can I say this is a safe method to access my API? If not, how should I implement this?
First of all, you must use HTTPS, as it ensures that both body and headers will be encrypted. Pick a certificate issued by a certification authority and stay away from self-signed certificates.
If what you call hash means an access token, then it belongs to the Authorization header with the Bearer authentication scheme (refer to this answer for details). Alternatively, you may want to use a cookie with both HttpOnly and Secure flags set.
I also advise you to look into some sort of authorization mechanism for your application: according to the user roles or authorities, retrieve the data they can access or refuse the request. It's very likely your web framework already provides you some sort for authorization mechanism. Let me also highlight that you should't write your own security-related stuff (unless you really know what your are doing).
Any sort of sensitive information (such as credentials, access tokens, you name it) must never ever be sent in the URL: The requested URL may be logged by servers and proxies; If the URL is requested by a browser, the URL goes to the browser history. You surely want to avoid that.
GET is meant for data retrieval while POST is kinda a catch all verb, that is, the representation sent in the payload will be processed according to the resource's own specific semantics). If you need to send sensitive information to the server, I would advise you to use POST, sending any sensitive data in payload which will be encrypted over HTTPS.

oauth2 redirect uri. Passing data back to the client

I understand that the reason for the redirect uri is to pass the credentials back to the client, which is fine.
I want to allow programmers to use my client_id to write their own implementation, the problem is that my client_id has associated to it a set amount of redirect_uris, thus if the programmer is making their own implementation they cannot redirect to their own page.
I should thus have a single redirect uri which passes the token back to the client, but how can I achieve this?
Sharing client_ids between different apps is not security best practice. You should be looking in to something like Dynamic Client Registration where each client dynamically registers itself together with its redirect URI to the Authorization Server: https://www.rfc-editor.org/rfc/rfc7592

How to send a password in a GET request to access a REST resource

I have a REST service that is already secured with basic authentication using the Authorization header. This is used to access the service in general and is required for any request. i.e. "User1", "password1".
I have a "file" resource which can have an additional password associated with it (i.e a password protected Word document, PDF, etc), "docpassword". What is the best way to send sensitive information like this? I'm especially interested in how to send the password for a GET request, but I'd like to have a universal solution that will also work for POST requests.
Maybe a custom header?
The HTTP protocol defines the standard Authorization header for sending authentication data (credentials) to the server. This header is defined in the RFC 7235 (which makes the old RFC 2616 obsolete and updates the RFC 2617):
4.2. Authorization
The Authorization header field allows a user agent to authenticate
itself with an origin server -- usually, but not necessarily, after
receiving a 401 (Unauthorized) response. Its value consists of
credentials containing the authentication information of the user
agent for the realm of the resource being requested.
Authorization = credentials
[...]
Please note that the name of this HTTP header is unfortunate because it carries authentication data instead of authorization. Anyways, this is the standard headers for sending credentials in the HTTP protocol.
Once you are already using the HTTP Basic Authentication Scheme to authenticate the users in your application, I believe you are already using the standard Authorization header.
I usually do not recommend custom headers, especially when the standard headers can be used instead, but your scenario seems not so common: You need to perform two authentications on the same request.
So, maybe a custom header such as X-Auth-Document or Document-Authentication with the document's password will be fine for GET requests. If you decide not using GET and decide using POST to access this resource, you can consider sending the document's password in the request paylod.
Anyways, don't forget using HTTPS: is highly advisable once you are sending sensitive data, such as credentials, over the wire. And HTTPS will protect you against the man-in-the-middle attack.
HTTP already has an authentication method, see for example this RFC: https://www.rfc-editor.org/rfc/rfc2617
Edit after clarification of question: There is nothing preventing the server to make additional challenges, even based on single resource basis. I must admit I did not implement such a thing yet, but each authorization can have its own realm. You could specify different realms, even down to document level if you really want to. The server then can potentially make multiple challenges in each realm (first login, then document). Remember, you can cache successful authentications, either on the client (for a realm, like a browser does), or giving out cookies with a cached token.
This would have the advantage of avoiding a custom header, and be completely HTTP/REST conform. There may be some performance disadvantage, but it could be mitigated with some targeted caching.
Of course you can go with custom header if you want to, but normally REST would imply that the client goes in with no prior knowledge other than mime-types and the HTTP protocol. A custom header implies out-of-band prior knowledge.

How to pass additional data to restful API Basic authentication

I am developing my first restful API for a project.
I understand and have gotten the basic authentication to work properly, using the format Basic username:password where username:password is Base64 encoded.
Currently, we pass a user's email address in the 'username' field and their password in the 'password' field.
The problem is that the email address is not unique in the application. It is unique per Organisation within the application.
So in order to log the user in successfully, we need to pass another value to the API which indicates what the organisation is (the idea would be to pass along a key that would be used to look up the organisation)
My issue is that the basic authentication process only allows you to pass two values (username,password), whereas I need to pass three. Is there a way to pass more data to the basic authentication process? Or do I have to use some other type of authentication to achieve this?
My idea was to modify the basic authentication so that it takes three values, for example: username:password:orgkey
I don't know if that is allowed or goes against the protocol for basic authentication though?
Although this question really is language independent, for the record I am using Coldfusion and the Taffy plugin.
Any guidance would be appreciated.
Thanks
Basic authentication is not a good protocol for securing web APIs as I tried to explain in my answers here and here.
It's okay to support it for things like test automation etc, but I would not use it in production. You will have a hard time keeping the password secret as neither JavaScript nor mobile clients can be trusted to keep secrets.
It's not clear to me why email addresses are not unique across organizations. Are you not sending the part after the at-sign ('#')?
You cannot introduce another field in the basic authentication credentials field. According to RFC7235, the credentials field can only contain:
credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
I would look into a security token based authentication scheme like using JWT tokens.