Trying to implement a passwordless authentication using Redis and random tokens - django

I want to implement a passwordless email based authentication (like in medium.com!), now I want to verify if this logic flow is secure or not:
User submits his email
Server generates a random token, sets to Redis a new value where the KEY is the token, the VALUE is the email or the corresponding user id, also make the key expires within an hour or some soon future value (within tens of minutes or hours), send a link including the token to the user email (i.e. example.com/login/token/{TOKEN})
User visits his inbox and press on that link
Server checks for {TOKEN} key, if it exists, authenticate the user and redirect to homepage, if not redirect to some error page.
Is this approach secure, is there something hidden I can't figure out yet?
Also Note that this method authenticate the user with only GET methods.
I use Django/Python, so if there is some package doing that, what is it?
Also is it relevant and secure for new user registrations/password-change/other user checks? Is there impact in case of DDoS attacks like making my server spam random emails, consuming the server using having a big Redis memory consumption in short time?
For token generation, I will use some value generated by random.SystemRandom().choice('abcdefghijklmnopqrstuvwxyz0123456789')
long enough to be hard to guess ( 60-80 characters) and it is valid for a short time like I mentioned.

Yes, I have used it in production quite successfully at my company. However, the use case is a bit different, as we use it for inter-service authentication once user has logged in using the password.
Spamming of random email addresses using your service is quite a real possibility in this scheme and you would have to put in checks like Captcha etc. to ensure this does not happen.
For actual implementation refer to this link:
Is there a way to configure Django Rest Framework to store token information in Redis rather than the Database?

Related

Tronweb authentication

I want to build a webapp that uses the wallet address as account, but yet I want to store the user in my db to allow specifying a nickname.
The problem I'm dealing with is that I want to call different apis, where the user needs to be authenticated / authorized in order to gain access .
Since the authentication happens 100% client side in my case (through the tronlink extension and TronWeb), I don't see another way as to add supplementary authentication for my webapp specifically.
If the user logs in to my app with a different password (not using the private key of the wallet), it seems like bad user experience as the user needs to authenticate twice (through Tronweb AND my webapp with a password).
How do you solve this problem?
It seems that the way to handle this is to foresee a separate login flow for the web app after all.
Even when the user already has logged in into Tronlink, it needs to obtain a token to authenticate rest calls.
The way it would appear to work is by generating a random nonce and storing this nonce along with the public key in the User table.
The login flow then consists of signing the nonce in the front-end, and verifying the signature in the backend after which the token will be generated and returned.

Preventing multiple simultaneous logins with Cognito

We have React Native app that uses Cognito for authentication. We would like to prevent the same user ID from logging in simultaneously from multiple devices.
We were hopefully that we could use a Cognito pre-authentication trigger for this. Unfortunately it seems that we can't just call globalSignOut for the user since that wouldn't invalidate tokens that have already been issued and are currently active (see https://github.com/amazon-archives/amazon-cognito-identity-js/issues/21#issuecomment-331472144).
The other idea was to reject the login if the user is logged in elsewhere. But we can't see a reliable way to tell whether the user is already logged in. We can see if there are valid tokens issued for that user but not if they are currently associated with an active session.
We also thought of maintaining our own DB of active sessions but there is no sign-out trigger so we wouldn't know when to remove a session from the DB.
You can use a token authentication system,
Issue a brand new token for each login, and check for available tokens.
if any token is available for the user that means He/She is logged in some other device, for this case you can prompt user that You are logged in other device.. are you sure you want to log out from that device ? and after clicking yes, you can clear all tokens for that user. And issue a brand new token.
AUTO LOGOUT : this token should be passed all over the back-end i.e. in headers of each and every API call token should be there... and should be checked before doing anything in back-end. if token is not available then throw 401. In your app if any API throws 401 then it means user is UNAUTHORIZED and should be logged out.
or
your app should be listening to one socket that responds to log out when it receives a message of same. so whenever your user logs in, a logout message will be passed across sockets and appropriate device with some token id or unique id will get that message and will log out a particular user from all other devices.
or
have a notification receiver which will be used to log out whenever necessary same as socket.
Reading the link you provided the API token / session system seems being faulty by design since long time already.
So without an own token-system inside cognito you won't have reliable results probably, at least in the current state of the system (as the repository is archived it won't be developed further by the owner).
What I propose is an own field in the database-table for users where each login is honored with an own token. A second own field in the same table with a timestamp, where the last access is saved.
If last access is older than a predefined time of 30, 60 or 120 minutes any user gets logged out.
If the last access is younger than the time-limit then the login-mask has to provide a random access token which is compared with that in the database:
- if the access-token in the database is too old for an active session, or just no access-token is stored, then access can be granted which means login is successful.
- the comparison of the current time with the time-stamp saved in the database is for cases where users never have been logged out by purpose but just by being disconnected or passive. I think this case will happen regularly, so it's no exception.
- logging out by click on a button should destroy the access-token in the database, so that the user can immediately login from any device, even from another one then before.
- if there exists a valid access-token in the database then no new access will be granted and the user should get shown a message that he has to sign out first at another login.
- The access-token could be stored together with a third own field for the session-id to make it more reliable and safe. On logout that session-token-field can be cleared too. The session-token can be copied from the global session if required to be saved in the user-record.
- Any checks are only done on login, tokens never have to be included on every page.
- On active logout the token(s) have to be destroyed to allow a direct login again, else the users had to wait till the max. age of the time-limit is reached to login again - at least on another device then before.
As the login itself is currently done independent from the check that has to be implemented, it would be possible to leave the new access-token completely away but use only the session-id as that differs on any device and browser. But perhaps there exists a situation where one of session-id and access-token can change but the other one not - I don't think so but perhaps I missed something in my considerations.
If you provide the access-token on every page like proposed by #Jadeep Galani or in a cookie - beside the corresponding check - you also can offer a button to sign out from all devices. This would enable the users to change login any time even without logging out at the last used device. Without access-token on every page or in a cookie this general logout-function solution is not possible as else access is only checked on login but not on all pages.
A general question is if it's still worth it to rely on the buggy cognito for login or just replace it completely by an own solution. You even could implement the desired authentication in your site in form of a wrapper-class and the concrete login-system could be replaced without changing that implementation.
You can use the UUID of the device to identify whether it is the same user. Add a UUID to each request header to record it in the DB, and then you can do what you want.

How to protect web application from cookie stealing attack?

My web application's authentication mechanism currently is quite simple.
When a user logs in, the website sends back a session cookie which is stored (using localStorage) on the user's browser.
However, this cookie can too easily be stolen and used to replay the session from another machine. I notice that other sites, like Gmail for example, have much stronger mechanisms in place to ensure that just copying a cookie won't allow you access to that session.
What are these mechanisms and are there ways for small companies or single developers to use them as well?
We ran into a similar issue. How do you store client-side data securely?
We ended up going with HttpOnly cookie that contains a UUID and an additional copy of that UUID (stored in localStorage). Every request, the user has to send both the UUID and the cookie back to the server, and the server will verify that the UUID match. I think this is how OWASP's double submit cookie works.
Essentially, the attacker needs to access the cookie and localStorage.
Here are a few ideas:
Always use https - and https only cookies.
Save the cookie in a storage system (nosql/cache system/db) and set it a TTL(expiry).
Never save the cookie as received into the storage but add salt and hash it before you save or check it just like you would with a password.
Always clean up expired sessions from the store.
Save issuing IP and IP2Location area. So you can check if the IP changes.
Exclusive session, one user one session.
Session collision detected (another ip) kick user and for next login request 2 way authentication, for instance send an SMS to a registered phone number so he can enter it in the login.
Under no circumstances load untrusted libraries. Better yet host all the libraries you use on your own server/cdn.
Check to not have injection vulnerabilities. Things like profiles or generally things that post back to the user what he entered in one way or another must be heavily sanitized, as they are a prime vector of compromise. Same goes for data sent to the server via anything: cookies,get,post,headers everything you may or may not use from the client must be sanitized.
Should I mention SQLInjections?
Double session either using a url session or storing an encrypted session id in the local store are nice and all but they ultimately are useless as both are accessible for a malicious code that is already included in your site like say a library loaded from a domain that that has been highjacked in one way or another(dns poison, complomised server, proxies, interceptors etc...). The effort is valiant but ultimately futile.
There are a few other options that further increase the difficulty of fetching and effectively using a session. For instance You could reissue session id's very frequently say reissue a session id if it is older then 1 minute even if you keep the user logged in he gets a new session id so a possible attacker has just 1 minute to do something with a highjacked session id.
Even if you apply all of these there is no guarantee that your session won't be highjacked one way or the other, you just make it incredibly hard to do so to the point of being impractical, but make no mistake making it 100% secure will be impossible.
There are loads of other security features you need to consider at server level like execution isolation, data isolation etc. This is a very large discussion. Security is not something you apply to a system it must be how the system is built from ground up!
Make sure you're absolutely not vulnerable to XSS attacks. Everything below is useless if you are!
Apparently, you mix two things: LocalStorage and Cookies.
They are absolutely two different storage mechanisms:
Cookies are a string of data, that is sent with every single request sent to your server. Cookies are sent as HTTP headers and can be read using JavaScript if HttpOnly is not set.
LocalStorage, on the other hand, is a key/value storage mechanism that is offered by the browser. The data is stored there, locally on the browser, and it's not sent anywhere. The only way to access this is using JavaScript.
Now I will assume you use a token (maybe JWT?) to authenticate users.
If you store your token in LocalStorage, then just make sure when you send it along to your server, send it as an HTTP header, and you'll be all done, you won't be vulnerable to anything virtually. This kind of storage/authentication technique is very good for Single-page applications (VueJS, ReactJS, etc.)
However, if you use cookies to store the token, then there comes the problem: while token can not be stolen by other websites, it can be used by them. This is called Cross-Site Request Forgery. (CSRF)
This kind of an attack basically works by adding something like:
<img src="https://yourdomain.com/account/delete">
When your browser loads their page, it'll attempt to load the image, and it'll send the authentication cookie along, too, and eventually, it'll delete the user's account.
Now there is an awesome CSRF prevention cheat sheet that lists possible ways to get around that kind of attacks.
One really good way is to use Synchronizer token method. It basically works by generating a token server-side, and then adding it as a hidden field to a form you're trying to secure. Then when the form is submitted, you simply verify that token before applying changes. This technique works well for websites that use templating engines with simple forms. (not AJAX)
The HttpOnly flag adds more security to cookies, too.
You can use 2 Step Authentication via phone number or email. Steam is also a good example. Every time you log in from a new computer, either you'll have to mark it as a "Safe Computer" or verify using Phone Number/Email.

Advice how to implement a simple user login and authenication

We are in the process of building a simple Android application together with a simple back-end web server to allow the user to get some information form the server.
We need to login the user, to make sure he is authorized to view the data, but apart form that I do not think we have particular security concerns.
I need some advice on how we can implement the server to keep things as simple as possible.
For example, we could use something like this to make sure the user is authorized to see the data:
http://ourwebservice/user/password/viewsuchandsuchdata
Is that a good way of doing things?
Do you have any suggestions or comments?
There are many ways to secure web-services.
The simplest is possible "Basic Auth" (http://en.wikipedia.org/wiki/Basic_access_authentication). On every request, you send the user credentials in the "Authorization" HTTP header concatenated with ":" and base 64 encoded. To keep it safe, you need to make sure the connection to your web-server is using SSL (HTTPS), otherwise the user password could be intercepted.
Another "newer" solution is OAuth2, and in your case the "Resource Owner Credentials" flow. Instead of passing the user credentials on every request, you use them once to "exchange" them for a short-lived access token issued by your server. Then on any request to the web-service you pass that access token in lieu of authentication. The server must then verify that the token is valid and find out for which user it was issued. For more info see this article: http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified.
There are potentially many more "custom" ways of doing authentication...
Going the OAuth2 flow is probably more difficult but there are lots of open-source libraries out there to help you build a OAuth2 provider (http://oauth.net/2/). The advantage is that you don't have to store the user password on the device, which is safer (the less you touch passwords, the better).

How can I implement user authentication for ColdFusion Web Services called from a mobile application?

I am developing several Web Services that will be accessed by a mobile application. I have several requirements:
Each user will need to sign in with their own User ID and Password (the same User ID and Password they use to sign into the website).
Every Web Service request will need to be authenticated to ensure that the request is coming from the mobile app(s).
Every Web Service request will need to authenticate the user, since there is user-specific fucntionality built in, and access will need to be blocked if the user's account is disabled.
Let's assume that OAuth is not an option.
In order to ensure that Web Service requests are coming only from the mobile app(s), I am planning to use HTTP Basic Authentication in IIS (the mobile app(s) will need to have a User Account setup in Windows Server and the mobile app will need to store the User Name & Password and pass these in the header).
Next is the User Authentication for each Web Service request. Would it be suitable to encrypt the User ID, Password, and some shared secret key (a "pepper", of sort) with AES-256, pass that encrypted string as a parameter with each request (over HTTPS, of course), and then decrypt and parse it on the server to authenticate? This is the existing plan, but something just doesnt seem right about it - like it's not "secure enough".
What else can I do to properly authenticate users for Web Service requests?
I recently went through this problem and asked opinions from a group of senior people about how they solve the problem. Opinions were varied, but one consistent feeling is that your level of security depends on the use case of your application. Are you doing online banking or storing medical records? Then your security needs may be quite high. Social networking? Maybe not so much.
Basic Authentication is generally fine when encrypted over SSL, ColdFusion works well with it. If you use Basic Auth, make sure to encrypt your traffic with 1024-bit keys or better. Don't authenticate every request with username/password - that's unnecessary. Authenticate the first request, set a session token, and rely on the session token for your identification of users.
Set a polling mechanism from the client to the server to keep the session alive - set the session timeout to 30 minutes and the polling frequency at 25 minutes, for example. Otherwise you may need to re-authenticate expired sessions. Again, how you approach this part of the solution depends on your paranoia level, which depends on what kind of data/app you are dealing with.
Cookies, and therefore sessions, should work fine in iOS apps. If you use sessions to verify identity after authentication, make sure your session cookies are memory-only (set at the server level).
Check the SSL implementation of your server against the Qualysis SSL Test:
https://www.ssllabs.com/ssltest/
The report will give you a surprising amount of detail about the strength of your SSL implementation.
Lastly, consider implementing two-factor authentication to combat password theft.
If you ignore the SSL advice and plan on encrypting your password and communicating over an insecure channel, look at the Kerberos protocol for a well-known example of how to authenticate securely:
http://en.wikipedia.org/wiki/Kerberos_%28protocol%29
Yes, you can use Basic Authentication but that means the client will need to store the username/password in plain text, and also send them over in plain text. Sending part is sort of fine if it's under HTTPS, but storing username/password in plain text may not be a good idea, unless you're using some secure key store.
Let's assume you have decided that Basic Authentication is the way to go, and you want to make use of the official CF way of supporting that, then you can use CFLOGIN.name & CFLOGIN.password. You may also check out Ask Ben: Manually Enforcing Basic HTTP Authorization In ColdFusion. In the remote cfc side, always validate the username/password, or return some sort of token and asks the client to use that token going forward. The token can be cfid+cftoken if you like, or even roll your own that never expires. If you use cfid+cftoken, and send them over as cookie or in body along with your web service call, I believe you can resume the session if you so choose.