How to set up a temporally password accessed ressouce? - database

Context
Developing a platform with contents and some files. Users can create a resource, and set it:
private: only accessible for him
protected: accessible via a password that can expire
public: no security rules to access
Problem
Considering we have that 2 tables:
We want to protect our element table if visibility = 'protected'. So creator should give a password for resource access, and set an expiration date.
Users can set many passwords with a different expiration date.
How can we store that password, with security, and thinking about the user can share a password, close password access, and get his password access to share resources when he needs them.
We talk here about a conception of the solution, don't care about languages or orm.
Potential solution
Cron job
Create a table joining passwords with entities, and when the user sets a password, launch a cron job that will set an attribute like active to false when the expiration date is reached.
Problem: making our app stateful, if cloud-based and the pod crash, cron job fell in void...
Store it in base64
To allow users to get back already set passwords, we have to get symmetric encryption algorithm to encrypt and decrypt the password, but that exposes resources if the database is compromised..
Also creating a table joining passwords with entities here.
No more ideas for the moment... How would you do ?
The best solution should be stateless and don't store passwords in clear.

I can think of other two solutions
A PubSub mechanism, which you can choose to trigger when to execute. For example, when you create a password today and want it to expire tomorrow. you can create a pubsub task that will trigger in a day. The task will remove that password.
A JWT token, which is a token that encoded the information in there, which includes the expiration date. When you verify that token, you will verify the signature to make sure it is not tampered and also if it is still valid. If you need to store secret inside it, you can use RS256.

Related

What is the right way to maintain user audit in a system designed to use external authentication?

I am using AWS cognito for user authentication in the application that I designed. And where ever there is a need for user audit in the application, I have used the id from cognito as if it is a foreign key from another table(I am using a relational DB).
Even though this works, this approach somehow feels improper. Is there any other proper way to design this?
In my application, the user logs in with his email address (common scenario). Hence, by construction the email address is a unique identifier both in cognito and in my database.
My database creates a user id for each new user, and that is the main identifier I use in my app (note that this identifier has nothing to do with cognito).
Cognito also assigns an id to each user (which it calls "username"), but I never reference that id (nor have I ever felt the need to reference it). I have been in production for several years, and I have never regretted this decision.
Upside of not linking user ids:
full flexibility (e.g. I can decide that I want to create a new user Object in my database for a particular cognito user. I can keep the previous user e.g. as a backup, even though it is not linked to the cognito user).
less work: i don't need to make sure the ids in my system are in line with those in cognito.
Downside of not linking user ids:
maybe it's faster to query cognito using the username field than the email field? maybe that could be an advantage for some use cases?

Is it safe store a username inside a cookie?

I working on security and I 'm storing a session key inside a cookie. I will use it to check if the user is actually connected and if he didn't tried to change some info.
at first I think to just check if the session key is inside the database, but I think it would be more secured to check if the current user has the session key instead of just finding a user that have that key and assume that he must be the one connected.
I know I should use session storage, but since I'm using AngularJS, I don't know how to achieve that, so no need to point out that I should use session instead.
-Would it be safe to put the username inside the cookie?
-Would just using the session key and assume that the user that got the key most be the connected one be a good idea (it would simplify some of my request to the database later on)?
It sounds like essentially what you are trying to achieve by storing the username in a cookie is to make the username a 2nd factor in a 2-factor authentication scheme. The problem is, the username always travels in a cookie alongside the session id and so when one is exposed, the other is too. So no security is gained.
Furthermore, there is no valid security argument to storing username in a client cookie and then trusting that this username is the same one associated with a session. The client can trivially change the value of the cookie before submitting a request. And any attacker that has already managed to have sniffed out the session id from a cookie could probably just have easily read the username cookie too, making a session hijack attack practically the same difficulty. At best, you've achieved no higher security and added unnecessary complexity to your code. At worst, you've betrayed usernames which wouldn't have otherwise have been visible to an attacker. eg. in the case of expired sessions.
OWASP Recommendation:
Session ID Content (or Value)
The session ID content (or value) must be meaningless to prevent information disclosure attacks, where an attacker is able to decode the contents of the ID and extract details of the user, the session, or the inner workings of the web application.
The session ID must simply be an identifier on the client side, and its value must never include sensitive information (or PII). The meaning and business or application logic associated to the session ID must be stored on the server side, and specifically, in session objects or in a session management database or repository. The stored information can include the client IP address, User-Agent, e-mail, username, user ID, role, privilege level, access rights, language preferences, account ID, current state, last login, session timeouts, and other internal session details. If the session objects and properties contain sensitive information, such as credit card numbers, it is required to duly encrypt and protect the session management repository.
It is recommended to create cryptographically strong session IDs through the usage of cryptographic hash functions such as SHA1 (160 bits).
-- https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Content_.28or_Value.29

Evernote users in the application database

What's the best practice or the common way of keeping (or not keeping) Evernote users in your application's database?
Should I create my own membership system and create a connection to Evernote accounts?
Should I store Evernote user data (or only part of it) in my own app and let the user log in only with Evernote?
Summary: you must protect their data but how you protect it is up to you. Use the integer edam_userId to identify data.
I think the API License agreement covers protection in the terms:
you agree that when using the API you will not, directly or indirectly, take or enable another to take any of the following actions:...
1.8.4 circumvent or modify any Keys or other security mechanism employed by Evernote or the API;
If you cache people's data and your server-based app lacks security to prevent people looking at other's data, then I think you're pretty clearly violating that clause. I think it's quite elegantly written!
Couple that with the responsibility clause 1.2
You are fully responsible for all activities that occur using your Keys, regardless of whether such activities are undertaken by you or a third party.
So if you don't protect someone's cached data and another user is able to get at it, you're explicitly liable.
Having cleared up the question of your obligations to (as you'd expect) protect people's data, the question is how do you store it?
Clause 4.3 covers identifiers pretty directly although it's a bit out of date now that we are all forced to use oAuth - there are no passwords ever entered into anything other a web view. However, mobile or desktop client apps must provide a mechanism for the user to log out, which must completely remove the username and password from your application and its persistent storage.
For a web app, you can't even save the username: If your Application runs as an Internet service on a multi-user server, you must not ask for, view, store or cache the sign-in name or password of Evernote user accounts.
The good news is that you can rely on the edam_userId value which comes back to you in the oAuth token credentials response, as discussed here.
When you look at the Data Model, you can see the unique id under the User and going into the User struct, see the reassuring definition The unique numeric identifier for the account, which will not change for the lifetime of the account.
Thinking about the consequences, as you can't get the user id until you have logged into the service, if you want to provide a local login for people you will have to link your local credentials to the user id. That may irk some people if they have to enter a username twice but can't be helped.
You can allow users to log-in via OAuth. Here's a guide on how that process works.
But you'll probably also want to store a minimal amount of user data, at least a unique identifier, in your database so you can do things like create relationships between the user and their notebooks and tags. Refer to the Evernote data model for those relationships. If you're using rails, this will also help you take advantage of rails conventions.

Destructible Passwords in a Silverlight E-Commerce Application

I have a business requirement that calls for an end user to be able to login to an e-commerce system with a one-time use password, purchase a course, and then never be able to login again. At the moment the company that is allowing their employees, my client's students, is going to generate that password for them and send me a list of the passwords they are generating.
I do not like the concept but I have yet to come up with a better one that will work for all parties. If something happens mid-purchase they have to go back to the company to get new login credentials.
The ability to purchase a course cannot be open to the public, it has to be through the e-commerce portal, and for the moment there is only one company participating but there will be more in the future. I am seeing this as a total maintenance nightmare.
My question is has anyone run across this before, if you wouldn't mind sharing tell me how you solved it, or point me in a direction that will give me some insight. I have googled the concept to death and have not come up with any bright ideas.
You can't resolve the "problem during purchase" issue yourself - They need to modify their service so that the password is destroyed when the transaction completes.
No matter what you do with regards to the password, once the user is logged in, the password is disabled on their servers. After that, you have no control.
They should either:
Cancel password on transaction completion
Provide you with an API/Web service to allow you to request a new key.
I have the answer for this one and document it here for my own personal OCD completion purposes. I created a login form that allows for a two part key; username is based on company name plus internal company ID(not a guid), paired with a password that is cryptic key, ex: #SCD6-, plus employee id generated by the company. The rub is I don't know what the employee ID is, and only use it because it should be unique although it doesn't matter if it is not, once the user logs in once completes the only marginally secure process then checks out the login is invalid and can never be used again, unless manually unlocked (in case of a duplicate employeeID at some time in the future, which is unlikely). The username and key is emailed to the employees of the target company, which is generated by the target company.If I do have the employeeID in the system which is 50/50 then I can pre-fill the forms out.
The only thing this lock protects is a process and not secure information so I am not too worried about security and it's only real purpose is to keep John Q, from stumbling onto the process and paying money that my client would need to refund later. If it were a secure data process I would not use this method.

Google App Engine - Dealing with concurrency issues of storing an object

My User object that I want to create and store in the datastore has an email, and a username. How do I make sure when creating my User object that another User object doesn't also have either the same email or the same username?
If I just do a query to see if any other users have already used the username or the email, then there could be a race condition.
UPDATE:
The solution I'm currently considering is to use the MemCache to implement a locking mechanism. I would acquire 2 locks before trying to store the User object in the datastore. First a lock that locks based on email, then another that locks based on username.
Since creating new User objects only happens at user registration time, and it's even rarer that two people try to use either the same username or the same email, I think it's okay to take the performance hit of locking.
I'm thinking of using the MemCache locking code that is here: http://appengine-cookbook.appspot.com/recipe/mutex-using-memcache-api/
What do you guys think?
Try storing your User with their email as the key_name. This can be done in one simple step:
MyUser.get_or_insert(email)
Getting your MyUser by an email is also easy:
MyUser.get_by_key_name(email)
See this similar question: add properties to users google app engine
So that solves the problem of two users with the same email. To do the same for usernames, perform the "get users with this username" query and the "insert a user with this username" in a transaction (this is what get_or_insert() does behind the scenes).
You can catch a TransactionFailedError to find cases when another user "takes" that username during your transaction.
You definitely don't want to use a memcache mutex, since that while loop waiting for the lock to free up can spend a lot of your memcache API call quota.
If you use the JPA impl of datastore, you just have to set the annotation
#Column(unique=true)
Field field
This way the db will reject your insert/update.. i guess it's implemented by gdatastore, it's not a big matter for me to give a "technical error" to the user on such a specific case... but anyway you could catch a constraintviolation exception. I guess JDO also have this.
But actually i don't even know if you'r using Python or Java...
In Java as far as i know you can do a select request in a transaction...
About transactions you should also check what is transaction isolation and how it works on GAE...

Resources