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.
Related
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?
Our application has different roles for each user and only certain users are allowed to query the data. We have to validate user id and password for each request.
I have a simple REST get where the user passes employee id and we return employee data. What is the best way to pass userid and password? Is using userid and password in URL (i.e. #PathParam) bad idea?
Right now I have it as follows, this will return the employee data for emp id 111 by user u1
https:../MyRestWebService/services/getEmp/u1/encpassword/111
Only https port will be open in the firewall i.e. all requests are always over https and password is always encoded string (we publish how to encode)
thanks
Whether or not this is a good idea always depends on exactly how you are using it. Passing the password itself will probably raise eyebrows at least, and it could be a serious problem.
Generally, the two approaches are require a login prior to issuing further calls, which mimics what a human user would use the system but requires logic to handle logging in and out on the client side. The second is to use API tokens, which is potentially less secure, but more convenient for automated clients. Note, there's no fundamental reason you can't do both.
Take a look at how github handles API authentication; they actually do both. You can do an OpenAuth authentication to create an authenticated session, which takes the form of a temporary access token used in subsequent requests. You can also create a permanent access token and associate it to the account.
https://developer.github.com/v3/oauth/
https://developer.github.com/v3/auth/#basic-authentication (see x-oauth-basic variation)
You can also use a framework or built in support for sessions (depending on your server stack) to track authenticated sessions implicitly.
Yes, putting username and password in the URI is a bad idea. For starters, it means you can't share the URI without exposing your username and password. Is there some compelling reason you aren't using HTTP Basic Authentication? This seems like the exact case it's designed for.
GET https://.../employees/111
is a much more correct URI.
We are in the process of planning an iOS application in which users will need to be authenticated and authorized before they can interact with data provided by a Symfony2 web service.
Authorization will be implemented with ACLs, it's the authentication I'm not sure about.
From what I found in my research, there are a few ways to achieve the authentication part, but since there won't be any third parties accessing the data it sounds like basic HTTP authentication paired with a SSL certificate is the way to go. Is this correct?
Additionally, is a simple username and password secure enough, or is it better to add some sort of API key for identification?
If a key is needed and considering our users will be part of a group, should a key be bound to every user individually or to the group as a whole?
Finally, and slightly off topic, Symfony2 has FOSRestBundle, is there a defacto REST library for iOS?
For securing REST applications in symfony the FOSOAuthServerBundle is very useful. With it you can implement easy OAuth authentication for your app. OAuth is de facto standard for securing REST web services.
As https/ssl is pretty secure you can go for basic http authentication and/or the api key solution.
Wether to use a key and/or username/password is your personal choice.
If somehow requests can be catched in cleartext either one is compromised.
Keys in addition to username/password auth can have the advantage of seperating i.e. user contingents.
Basic http authentication is mostly used, therefore the chance of your client having already available methods to integrate it from his side are high.
You should always give out unique keys or username/passwords to every user in order to be able to log who did exactly what.
I'm not that much into iOS, sorry.
I'm building a picture diary on web application google app engine using python. Users can sign up and post pictures to their diary.
Also, I'm trying to conform as much as I can to the REST architecture of doing things.
The authentication scheme is based like this for the web application:
1. Post username/password from the frontend
2. Backend sets up a cookie if authentication is successful
3. The rest of the AJAX calls made are authenticated using this cookie.
Is there any way to conform to REST without using cookies ?
Now, I'm also building an android application where users can sign in and post/view their picture diary. I need to expose the data from web application's datastore so I'll be building a webservice to fetch data from the datastore.
The authentication scheme for the android client:
OPTION a
1. Post username/password over https to the web service
2. Web service returns a unique authorization token (store the token in the username/pwd table on the datastore)
3. Request subsequent services by adding this token to the Request Header of the request
4. Server maps the token to the username/pwd table and returns data if token is found
5. Authorization token expires after a certain period of time
OPTION b
1. Set up a secret key on the client and server side
2. Use "username:hash of password and secret key" in the authorization header of every request
3. server generates the password by extracting the password from the hash value using the same hash algorithm ; if successful returns data
btw, I didn't wanna use basic authorization because of its security vulnerabilities.
Which is better ?
Are there other significantly better ways to accomplish what I'm trying to do ? Security is quite a concern for me btw.
I'd appreciate if anyone has any insight into this issue. thanks.
I've been doing some research myself as to what would be the best solution. I think the 2-legged oauth might work in my case as Leonm suggested.
In this case the server has to provide the client with a consumer key/secret which in my case is hardcoded in the app.
The steps now would be:
1. Generate a signature using the oauth_parameters(consumer_key, signature_method, timestamp), request url, request parameters, and the SECRET.
2. Include the signature, oauth parameters when making a request.
3. Server verifies the request by generating the signature again except in this case it uses the SECRET that corresponds to the key
I think this way I am pretty much confirming to the REST principles. The server is statless as I far I understand now.
What are the pros/cons on doing things this way?
If "security is a concern" then I would say that you'd be a lot better off using open standards and a library to achieve what you want. The main reason for this is that if you do it yourself, you're very likely to forget something; these standards have had a lot of eyes looking at them, looking for holes.
Your options include (in increasing level of complexity)
Basic authentication and HTTPS
Everything is encrypted, which makes it impossible to compress or look into, it increases the overhead somewhat, using more horsepower on the server, and more perhaps battery power on the client. Simple to implement, since it's well supported by libraries.
Digest authentication
Unencrypted messages pass the wire, but the authentication is securely managed in the Authorization headers. See the wikipedia entry for more information.
OAuth
See how Google is providing OAuth for installed applications. I believe it isn't what you're looking for, since you're not asking to share data between applications, just authenticating users.
Roll your own
If you want to roll your own, I suggest looking at e.g. how Google's (now deprecated ?) ClientLogin used to work.
Clients would GET a protected resource, and get a 401 with instructions to perform a GoogleLogin authentication, including a URI for where to perform the login itself
Clients (knowing how to do this) POST a request in a specific manner to that URI
The server responds with a specific response including a (long) token
The client can now perform GET requests to the protected resource with that token.
Statelessness
You cite REST, which dictates that requests should not specifically depend on prior interaction: "... each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server." (fielding) This means that a server shouldn't store conversational context (like an authentication token) in a table.
One way of fixing this is by using any of the token based approaches (where the server tells the client about a token it should use for future requests) where the token is not a random number, but a message to the server itself. To protect yourself from client tampering, it can be signed, and if you're afraid of clients looking at it, you can encrypt it.
Edit: Although I'm not certain, it seems unlikely that Google has a table of all authentication tokens ever issued; The length of their tokens suggests that the token is some encrypted message proving that whoever holds this token actually provided real credentials in some realm at some time.
OAuth does exactly what you want to do in a standard way.
You could use a combination of HTTPS and HTTP Basic Auth. Both are existing standards and should be secure enough when used together.
I am working on a REST API for a web application that up until now we have developed internally for a couple of companion applications. Now that we are looking at opening up to outside developers we want to add tokens to the API in order to help identify who is making requests and in general to help manage it's use. At this point we are using https and basic authentication for user authentication on the API.
The token scheme we've been discussing would be very simple where each developer would be assigned 1 or more tokens and these tokens would be passed as a parameter with each request.
My question is if you've done something similar before how did you do it (did you do more or less, how did you handle security, etc) and do you have any recommendations?
First, you might want look at http://OAuth.net. Depending on your usecases, it might provide the security you need.
As to the token, it's a BLOB to most protocols, including OAuth. You can put any information you need in it in any format.
Here is what we do,
First we assign each developer a key with associated secret.
The token itself is an encrypted name-value pairs. We put things like username, expiry, session id, roles etc in there. It's encrypted with our own secret so no one else can make it.
For easy of use with web API, we use the URL-safe version of Base64 so the token is always URL-safe.
Hope that helps!
You might also want to think about maybe adding a time based token that would allow you to limit the amount of time a request is valid. this will help with someone trying to do a replay attack.
You would have a handshake call to get/assign a time valid token based off the above developerKey. This token would be stored locally and passed back to the caller.
The developer would then use this key in a request to validate the request and the developer.
For example that key can then be used for 5 mins or for 10 requests or whatever you define. after that point the generated time based token is removed from the valid list and can no longer be used. the developer will then have to ask for a new token.
UUID is very good for any temporary random key you fancy dishing out. Unpredictable and fast to generate, with collisions so unlikely they are effectively unique. Make nice session keys also.