I want to make a simple REST web app, where the user interact with the objects through links in an email. The links have a token that can be used to authenticate a user without a username and password, like the ones that are usually used to reset a password.
What are the best practices for such a login-less, token-based authentication system?
I am by no means a security expert.. but some of the points which come to mind are -
Lifetime - The token should expire after a set period of time. Indefinite access using the token certainly doesn't make sense.
Replay attacks - The mechanism should prevent replay attacks.. which means the token should be valid for not only a set period of time, but also fixed number of calls.. Ideally exactly 1. If this number is not exactly 1, then it opens another can of worms..
Unless, its a feature :( For example, by design, the user is expected to share link with others, and anyone with the link should be able to access the resource in question.
Authorization - Granularity of the access granted by the token. Is it black and white.. or is the token also associated with a fixed set of rights. For example - token X was issued for Read-Only access, vs token Y was issued, for same resource with R/W access.
Administration - User / Admin should be able to see and verify any currently active and issued tokens, and associated information (permissions granted / affected resource etc), and explicitly revoke them, if necessary.
Secure Communication - You should consider security of the medium through which the url with token will be sent to the user. i.e. in your scenario, do the users receive emails over secure channel (TLS / SSL)? Should the email itself be protected with DRM?
Man in the Middle / Leaks - Similarly, even though you are providing the url in email, and the user is not logging on using user name and password over SSL, the resource should still be accessed using the url with token over SSL. This will prevent any capturing of the tokens from url, by a man in the middle. You would also need to be very careful about when the users browser may use this url in places you didn't expect..
I can vaguely recall reading about a popular site being affected by their urls being used as Refer Url, when displaying ads on their website.. which means, the advertisers site would probably get the url with the token as Refer.
Generation - Choice of algorithm to generate the token - May seem pretty obvious, but the token should be extremely obscure and near impossible to guess or brute force. The tokens should never be reused and the algorithm should avoid collisions.
Server Side Security - The tokens should probably be treated with same security as you would secure users id and password. If your user database gets hacked, hackers should not get the users passwords and other sensitive information.. Similarly, if your user / resource / token database gets hacked, despite the expiration on the tokens, hackers should not be able to access the resources as users for x hours.
Point is, when the tokens are stored on server side, they should themselves be secured / encrypted.
On the same lines.. just like its bad practice to log information like passwords in log file (specially plain text), You'd also have to consider any place these urls may get logged (plain text) on your server.. For example web server logs. If only super admins should have access to user's database, then they should also be the only ones to be able to see these token.. Not your web server admin and not any hackers parsing the log file after the hack.
Auditing - If there will be a need for auditing, you'd need some mechanism in place to prove that while the user didn't log on to the system, they are indeed the ones who performed the action / operation in question. Would you want to track the ip address and other information along with the request which would help such auditing?
Consent - Do your users even consent to the use of such alternate means of authentication and authorization? Should this be an optional / opt in feature?
EDIT: I found a link to the referrer url problem I was recalling. Although it was in context of user information.
I agree to 10 points of Vikas however from security perspective I have to tell you few points that you must be careful.
I will try to keep as simple as possible. And here I simplify the technical stuff to your special case.
Firstly tokens are used to prevent Cross Site Request Forgery attacks (XSRF). Keep that in your mind. If there is a web platfrom without unique tokens on the forms then any attacker can force the user to make malicious requests.
If you simply try to authenticate the user with a token, this is pretty wrong. Because there must be no simple authentication process and you can not rely on token.
Here is how the login system works in official security documentations, im writing as I remember:
Identification: you have to identify the user firstly, that is generally done with username. YOu will know that there is a user exist in your system.
Authentication: Let's say you have already identified that user A want to login. So you mast authenticate the user A with something that you know and user A know. We call it password simply :) You cannot by pass this step with plain text methods. Passwords are generally encrypted in your db and also through all communication with secure certicates, check ssl.
Authorization: okay you made the authentication somehow, the user has a right to get Authorization. Let's say if the admin type user is logged in, he has differen rigts and if the normal user is logged in then she has regular rights.
Session control: finally you have to control the session with a secure way. Here generally in web applciations people use access tokens for all requests to be sure that the authorized user is aware of the request. As a platform owner you are responsible to secure everything until the session ends. If you don't satisfy the users with your security, then probably your platf is not going to survive longer.
Tokens have different lifetime to expire and different access rights.
Now let's look at what facebok like companies do with mobile aplications. For the mobile app they generate a unique access token which is alway alive. One shortcoming here is, if any attacker steal the mobile token generally she can do anything in the account anytime :) Anyway here our point is how they verify the users with those tokens; firstly the token is unique for that device. (Actually not exactly unique or not dependent on hardware, because if you clearly steal the necessary files from the device then you can use it on another phone). So with this unique access token which is generated with users password at their initial login on mobile app, they can login always automatically with that. And this method is a little similar to what you want to do. However pay attention that they don't authenticate the users with links or email code.
Verification is not an authentication, don't forget that. By sending e-mail you can verify the users if the emailed code is unique and valid for only 30 sec or 1 minute. I hope you got the point.
Here I suggest you to check single sign on across multiple domains, which is really interesting.
Single Sign On across multiple domains
Let's say you are logged in to google.com and then you visit the youtube.com Opps the youtube is already logged in? Yea, cool right, but exist for long time. They can authenticate users accross domains which use different cookies with a little and secure trick. You will read on the link.
If your service is not really confidential and if you want to make your users happy with easy login system. Here is two of my solutions which I love :)
1-) Ask users their email address: just directly send 4-6 digit code as e-mail. Ask user the enter/click on that. There will be no password at all, only unique code on each login.
2-) Let's say you need to verify the user with a stronger way than email. Then mobile phone :) Here trick is; you will not send the verification code to user, but they will send what you tell them to you.
Ask to user to send a SMS with a unique CODE to XXXXXX your number :) Connect your mobile operator with your web service and check whether the code is sent to you by the user :)
There is always a trade-off between security and simplicity, and also with complexity. You have to find the balance.
Don't try to make it simple if your security is going away.
Don't try to make it complex if it'll seem more secure.
Hope those informationn help you.
Related
In case of using password-backed authentication, if user forgets the password, the provider always trusts the user's email security.
So why the whole fuss? Why not use email for sending the secret login keys to registered users? Isn't that what sites do when user forgets the password?
What is the reason for still using passwords for authentication?
What are the major problems with passwordless auth that passworded auth lacks?
One difference is if you log on via forgotten password, you usually have to change the password to something else, so it cannot be undetected - an attacker will likely be discovered. If it's just a login link in email, this is not the case, the attacker can log in, and likely nobody will notice. There can be controls to mitigate this of course, but it quickly becomes a UX question.
Another UX aspect is having to go to your email all the time if there is only a login link. A lot of people use password managers, which make entering very secure and unique passwords really easy. If it's a login link, you have to open your email, disrupting your flow in the application. It's arguably inconvenient.
Also a login link sent in an email will contain a token in the url. That will be remembered by the browser, logged in intermediate proxies, logged to the web server logs and so on. Secrets should not be sent in the url. However, if it's a one-time token valid for a (very) limited time, this risk is very much mitigated.
Having said all these, there are commercial applications that opted for passwordless login via an emailed link. If implemented correctly (a strong enough one-time token with enough entropy, generated with a proper crypto random generator and so on), passwordless login via an emailed link can be secure enough for many applications, and it's mostly a UX question (keeping in mind the security considerations above).
I am currently developing a RESTful API server, and I am choosing between using ID and password or using a token to authenticate a user.
Let me, explain my situation first. I need to include static authentication information to my library to communicate between a client and my server or provide it to a partnership company to communicate between their server and my server. And when I was researching other services which are in a similar situation as us, they are using token now (for example, Bugfender is using a token to specify a user).
However, what I think is that using ID and PW and using the token are the same or using ID and PW is better because there are two factors to compare it is correct or incorrect.
Is there any reason why other services are using a token?
Which one is better as a security perspective or is there a better way to do this?
I think, if you are going go use on your client fixed username/password, or some fixed token, then the level of the security is the same.
Username and password is not considered as multi-factor authentication. Multi factor means that you are authenticating someone by more than one of the factors:
What you know. This can be the combination of username and password, or some special token.
What you have. Might be some hardware that generates an additional one time password - Google authenticator app on your telephone, or SMS with OTP received with some time expiration.
What you are. This is for example your fingerprint or retina of the eye.
Where you are. This can be the IP address of the origin if it is applicable for your setup.
How you behave. What is your normal way of using the service.
etc.
Maybe not needed to mention that both - the token and the username/password combination have to be carried in an encrypted requests (I believe you are using HTTPS). Otherwise the client's identity can be stolen.
How are you going to provide the credentials to your client library? I thnk this is the most tricky part. If those credentials are saved as a configuration (or worse hard coded) on their server, is that storage secure enough? Who is going to have access to it. Can you avoid it?
What would happen if your partner company realize that the username/password is compromised? Can they change it easily themselves? Or how fast you can revoke the permissions of stolen credentials?
My advice is also to keep audit logs on your server, recording the activity of the client requests. Remember also the GDPR if you work with Europe servers, check for similar regulations in your country based on what you are going to audit log.
In case the credentials (ID and password) and the token are being transferred the same way (say: by a header in a REST request) over a TLS secured channel, the only difference lies in the entropy of the password VS entropy of the token. Since it is something for you to decide in both cases, there is no real difference from the security perspective.
NOTE: I don't count the ID as a secret, as it usually is something far easier to guess than a secret should be.
I'd go for a solution that is easier to implement and manage.
IMHO this would be HTTP basic authentication, as you usually get full support from your framework/web server with little danger of making security mistakes in authentication logic. You know, friends don't let friends write their own auth. ;)
Do web browsers have a unique ID that can be passed on to Perl scripts? (Like a unique serial - like products that you buy in the shop have for example)
For instance: If I install a web browser, can this web browser provide a unique identifying ID to a PHP or Perl script?
The reason I'm looking for something unique is to do the following:
I have a user database with user names and passwords.
The user names / passwords are encrypted and set as cookies to the web browsers of users so that users can log in and out into my web application. (Each web page loaded when logged-in looks at the cookies and grants access if the cookie user/pass is correct)
If a hacker manages to steal the encrypted user name and password cookie from a user he will be able to log in with that stolen encrypted details.
If the browsers of users all had unique IDs to pass on then I could record those IDs and match them each time a user uses his encrypted user/pass cookie. This way if the unique ID does not match (what has been recorded previously) then the user is logged out and asked to manually log in again.
In the event where the encrypted user/pass is stolen the hacker won't be able to get in with it because unique browser ID's won't match. The user/pass cookie is encrypted and the hacker cannot see the user name or password. When the unique browser recorded ID's don't match the web application will ask the user to login manually and the hacker won't be able to login manually because the user/pass he stole is encrypted.
Using IP addresses is a possible solution but a poor solution because many if not most ISP's assign dynamic IPs to the internet connections of their clients.
Using time is also not a good solution because I would like the users to stay logged in on the same computer for weeks at a time (if they chose so) to make it convenient.
Anybody have any solutions to the above scenario?
I've been searching for a way to get something unique from browsers but this does not seem possible. Is it possible or not?
Browsers do not have a unique ID, but a good level of fingerprinting is possible. The EFF has measured that, in the best case, information sent by browsers (including the user agent string and other HTTP headers) represent 18.1 bits of entropy, which means if you take two browsers at random, you have 1 chance in 218.1 (≈280,000) that they will have the same "fingerprints". They have set up a website where you can estimate the degree entropy of the information sent by your browser.
Some websites use this. My bank, for instance, stores information about the three browsers I use most often to connect to their website, and ask me additional verification questions whenever I'm not using one of those.
On the other hand, all this information is entirely spoofable: if someone is able to carry a man-in-the-middle attack and steal a cookie, they are able to steal also all the headers sent by the browser, and can reuse them to authenticate themselves on your website. The same would be true if browsers actually had unique IDs.
Your alternative, besides using a connection encrypted with SSL (https) which requires you to either pay for a signed certificate or create a self-signed one that will display a security warning to your visitors, is to adopt better practice against session highjacking.
For one thing, it is not standard to keep the username and password, even if encrypted, in the cookie. What you should do is, once a user has logged into your website, assign them a random, single use session ID which you will store in your database along with an expiration time (which you may extend every time the user interacts with your website), and this to them in a cookie.
If you want an even higher degree of protection, one option is to change the session ID every time the user sends an HTTP request. You could also store a list of IP addresses each user uses to connect to your website, or IP address masks (e.g. X.Y.*.*) if it changes too often, and have them authenticate themselves if they are connecting from an unusual place. If you do this, it is a good practice to ask them "Will you be connecting again from this place?"
No, browsers don't have a unique ID. There is no such thing. If there were such a thing, it would be an online advertising company's dream!
That said, if you're serving up your site via HTTPS, you can issue your clients with client-side X.509 certificates. These would be cryptographically signed by your organization, so fairly unforgeable. (Though obviously if somebody had access to your client's computer they could make a copy of it - the same would be true of any browser ID number though!) Once the certificate is installed, every time the browser makes an HTTPS request to your website, your website can ask for its certificate, and this can be used to verify the user's identify.
You can store some unique values (e.g.: user id) in the user browser using "Html Local Storage" permanently with no expiration date, and store the same values with info about the user agent in the db.
Then you pass the user agent info with the data in the local storage and match it with the ones in the database...
// store
localStorage.setItem("myValue", "123-abcd");
// retrieve
var myValue = localStorage.getItem("myValue");
I'm not sure how much secure is this approach to identify users, but the Html Local Storage supposed to be accessible for only pages from one origin (same domain and protocol).
There is also "HTML Session Storage" to store data in the users browser for only one session.
Even we can use localstorage, sessionstorage and also cookies as well to implement this.. but wen these data s visble to user, so better to keep this encrypted
I am building a messaging application using BackboneJS which naturally persists using a REST interface.
The issue I'm having is that I don't know how to restrict what data a user can pull back from the API. For instance a call to /messages would, at the moment, return messages for ALL users. I would like that resource to only return messages belonging to the current user.
Searching online seems to indicate that oAuth2 is the best way to solve this issue but all the tutorials talk about been redirected to another place to confirm access and retrieve an access token.
Given that my users will have already logged into the message application and that the REST API is actually part of the same application I don't like the idea of asking the users to confirm that my own app can access my own API.
Is there a better way?
oAuth2 is probably your best bet -- you definitely don't want to roll your own security. However, the flavor of oAuth2 you are thinking of is probably not what you want.
oAuth2 has four different flavors, known as authorization grant types:
Authorization code: This is the type you are thinking about. It is often called three-legged oAuth, because there are three actors in the token granting process (app, resource owner, and user). The app asks the user whether it is ok for the resource owner to give specific type(s) of access to the resource. It is a rather complex process that allows the validation of user credentials without allowing the app access to them. This is not necessary in your case, since you are both the app and resource owner.
Client credentials: This is a method for authorizing a client application with the server. It does not use user credentials at all. If you completely trust your client application (all client applications) to correctly protect user data and not expose other user's data to the user using the app, or you are providing only non-user data via the API (for example, map data or catalog data), you might be able to use this fairly simple type of oAuth2. However, if you want to be vigilant in protecting user data (and not allow apps to get to the data without the user providing credentials), you might not use this one.
Resource owner password credentials: The username and password of the user is passed via https to your backend server, which authenticates and authorizes access by providing an access token. The access token can then be passed with each call, and it remains valid for accessing the backend until a configurable time period has elapsed. This means that someone intercepting the token could only use it successfully for a limited amount of time (some number of minutes, generally). The interceptor would not know the username and password of the user. In addition, you can supply the app with a refresh token, which can be used to get a new access token once it has expired (until the refresh token expires -- usually with a significantly longer expiration date). Since the credentials are not passed across the wire often (and must only be passed encrypted), this is often the best solution for protecting user credentials and not requiring the user to pass them in often (good user experience). Implementation is much simpler than for the authorization code grant type.
Implicit: This is the least secure method -- no credentials are validated server side at all. This is usually used for client side scripting languages where credentials cannot be stored safely. If you are worried about security at all, avoid this type if possible.
So, check out OAuth 2.0, and look for the resource owner password credentials grant type.
The apps that I build frequently have 'social media service' requirements; e.g.
Twitter
bit.ly
Facebook
For most of these services, I need to have an API key of some sort. I'm trying to work out the best way of including these API keys in the application binary. The desired level of security depends on the possible attacks that can be conducted by malicious attackers.
Twitter
I have an xAuth-enabled key and secret. Both need to be used by the iPhone app.
Fallout from attack
Malicious users could post twitter status updates masquerading as coming from my app. There is no twitter account to hijack and start posting status updates on.
bit.ly
I have a username, password and API key.
To login to the website and access analytics, the username and password are required.
To create links via the API, only the username and API key are required by my iPhone apps. The password will not be in the app in any form.
Fallout from attack
Malicious users could create links on my bit.ly account. They would need to do a separate attack to brute-force or otherwise gain the password to login to the account.
For both of those services, the potential for harm doesn't seem too great. But for other services, it could be much worse.
I can just define the API credentials as strings in the header or in-line in the code, but then it's vulnerable to someone using strings on the application to see what's in it.
I could then start doing silly concatenation / xor-ing in the code to recreate the API key in memory, and the attacker would have to do a bit more work to recover any keys in the binary. My concern with that is that I'm not a cryptographer and would create an embarrassingly weak form of obfuscation there.
What better suggestions do people have?
The attacker can just sniff your traffic and extract the secret from there. So any obfuscation is easily circumvented.
Even SSL won't help much, since you can intercept the networking API which receives the unencrypted data.
The secure way to solve this is create your own server, keep the secret stuff server side, and use your own server from your app, and the server then relays to the other webservice. This way the attacker never has access to the secret.
A good suggestion is not to worry about it. There are plenty of apps that store their API keys in plain text. The point is you need a lot of different bits of information to construct an access token.
As long as you're not storing username+password combos in plain text on the file system or transmitting them over the network without SSL/HTTPS etc then you're fine.