As I understand, to update any object with couchdb. I have to send the whole object back since it is actually "inserting" a new revision for the same id. This is all neat and works quite well.
But then I have a problem, I'm not so sure how should I handle that. I have an object that can't be sent to my user completely. I have to hide certain informations such as password hash.
The data is sent to the client, the revision is sent too. Now when I try to update my object I have one problem. Since some data is missing, the update will erase the attributes that are missing from my user.
That said, the easiest way I have is to get the object from couchdb, check if id and rev matches. If it does match, merge the object with the missing attributes. It will work pretty well and I can support deleting attributes too.
Then using this technique, I could add my objects to a cache that will reduce the time to query frequent objects from the database. If the object can be updated, then clear the cache for that id. If the object is newer, then I'll have to handle the error or merge the object.
Is there any better "good way" to handle this problem?
edit
After thinking about it during the night, I think I found a much much better solution. Instead of having my username and password inside my profile. I'll separate the identification object from the use profile.
In other words, I'll have to split up the object as much as possible to keep things isolated... On the plus side, I can add multiple authentication for one profile without messing with the profile itself. I can return profiles and anything necessary without returning any secret object.
It will complicate a bit the logic of insertion but it should be quite easy...
Get 1 id from couchdb using the uuid api "_uuids"
Insert password authentications (username, password, profile_id) using that uuid
If succeed, insert profile using the uuid that we got at 1
If anything wrong happen, rollback and tell the users what's wrong.
Also the nice thing about this method is that I can add access_token for oauth2 using the profile id and the logic will be almost the same as password, the auth type will differ but any auth type should work almost the same.
Yeah, extracting the secret stuff from the profile documents sounds like the way to go.
Related
In order to use some AJAX calls, we use often some input type="hidden". But these values can be easily changed. So, is it a builtin rails feature than permit to send date to AJAX, withouth being usable by user, or than can't be changed by user ?
In my current rails apps, i'm using filters for discard all malicious actions on my controllers. I am not building a public API, so i don't really need more powerful checks.
But for examples, i have an apotomo widget displaying some data, using some input hidden. But if you change it, you can access to another data set. In my case, it's not really an issue, cause all these users have the right to access these data sets anyway.
But is it some manner to give datas to ajax call, in a secure way ? Or the only security, is about rights management ?
All input that comes from the user is insecure as you do not have control over it! Users even do not need a webbrowser but can use some other program (like curl or wget) to send manipulated data.
As you state, using a whitelist (not a blacklist as you can never be sure of all bad, but of all good!) is a good way to start.
To make sure the hidden fields have not been changed you can use some kind of checksum that is calculated on server side using a fixed secret. This secret must never be exposed to your visitors!
hash = md5(field_1 + field_2 + field_3 + my_secret)
When these four hidden fields (field_1..3, hash) arrive in your form you can recalculate the hash and compare it with the params[:hash] in order to be sure the field_1 to field_3 have not been changed.
I have two tables, users and tokens.
Each user have a activated field and each token have the {id, token, user_id, created} fields.
The way the app should work is:
On the creation, the app will -
make sure that the activated field is empty (to avoid manipulations to the submitted data).
a token will be created in the tokens table.
On update, the app will -
NOT create a new token.
NOT allow an update of any kind to the activated field.
check if a new email has been submitted, and if so: will create a new token and set the activated field to false.
I know how to activate the account through the controller and how to setup the router for that.
What I need is mainly the model configuration.
For example:
I think that the token creation should be done in the afterSave method, so - how do I determine if the method is called by an update or by a create operation?
Thanks for any help
yossi you can also specify the fields that should be saved from the form though - a whitelist of fields it is ok to save in you $this->save() call. That way you can stop a hacker passing an ID in the request, and you should just set it in the controller yourself then with $this->Token->id = whatever you have, I would personally use saveField ('activated) in conjunction with this (just saves a single field!). Fat models is best if you can but get it working first then refactor it if you have got stuck. Better than wasting lots of time writing perfect first time.
You question is unclear. If you have a default value for a field, then why not set it in the database rather than doing something in aftersave? If you need to do something that should be done only in certain circumstances, then write a custom method in your model to perform the tasks you want either on creation or update.
Edit
So, if your record has an id, then you know it exists in the database. So, the simple thing to do is (in any method) check to see if the model has an id field and that it is not empty. If it's empty, then you know that you are creating a record and you can do x task. If it isn't, then do y task.
if(isset($modelData['ModelName']['id']) && !empty($modelData['ModelName']['id'])){
//This is an update
} else {
//This is a new record
}
Using CakePHP2.0 Beta I managed to write a custom login handler for my existing database schema. All's well, except that upon logging in I printed out the session variables stored and what Cake's Auth component did is store the entire record from the "Member" table (where my usernames+hashes come from) in session. It is storing an array with data fields that are totally irrelevant to the session. For instance it stores the date the member was created, their address, etc. All pretty useless information for me as I basically only need their ID and maybe username, name, email address.
The offending lines for me are found in: /lib/Cake/Controller/Component/AuthComponent.php line 512. It states,
$this->Session->write(self::$sessionKey, $user);
So my custom authenticate component returns $user and it throws this whole thing into the session. Now, I don't want to go about editing in the core libraries because this project is definitely going to be upgraded when 2.0 comes out. Is there any way to store less information in sessions? I want to keep this whole thing more lightweight.
Possible solution: Change my custom authentication component to only return the fields I need into the $user variable. Are there any concerns about what data I should/shouldn't be returning?
I've solved the problem using my "possible solution". In /app/Controller/Component/auth/MyController.php, I changed the "ClassRegistry::init($userModel)->find" method to have a parameter for 'fields' where I specify only the fields I need. Works like a charm.
A question based on a comment made here:
storing user detail ... session vs cache !
Summary: I mentioned a technique I've used where I populate a model and use hidden fields to keep and pass back that information; Viewstate on the cheap. Simon Halsey said that the information should be encrypted or hashed so it is not tampered with. I'm thinking the added complexity of hashing it is just a form of YAGNI.
I can see that for sensitive information, definitely, but is this a good rule of thumb in general? What am I missing?
I actually have an attribute to do this (something similar) and speak about this exact thing in a security presentation. Yes - you should hash a copy of the value... encrypting it is up to you. if you encrypt it you get no model binding but is more open to attack, although a hash check helps. I'll post the code shortly for it and update this post. Who would ever think Viewstate helped with security : )
but to answer your question - you can encrypt it, but you need a way to at least validate it on the server side, so I hash a value and hash the posted value and then compare hashes in the attribute. encrypting can help - but then you need to implement either your own model binder or manually handle those values
The rule of thumb would be generally for any values that could be maliciously overwritten to attack your data - then you want some protection/validation on those fields. you could compare server side against what you know is a valid option for them (a form of whitelisting) but then you have the same form of rules duplicated on loading the data and on saving the data and that gets a bit messy at times, unless its as simple as limiting a user's get/update to a single userId.
What I mean is.. if you are updating say a user's record. Generally the main thing that matters for security is that the userId is not changed by the user to update a record that isn't theirs. The logic on get/save is easy "where o.UserId == userId"
However in complex role based security the logic becomes trickier and is not as clean to limit record updates like this. In those cases you can really take advantage of encrypted/hashed fields. I always hash the specific fields uses for update. Sure - they can be forged with other valid hashed fields from a previous request, but the scope of potential damage is significantly more limited this way.
I am working on a guess-a-number game with Ruby that will be online. I know I need to pass the SESSION somehow to keep the number that they are guessing, but I have tried a ton of methods with no luck. My code is here.
Any thoughts on what I can do get this code working? I have declared each of my sections.
A session is, usually, a combination of a cookie (session cookie), or some session id tacked onto the url, which has some unique identification of the current "session" and a way to save the data on the server and retrieve it when given the id from the cookie.
So I would set a cookie based on for example ip + Time.now.to_i and then save that ID and the values I want set into a database or a text file on the hard drive. Note that there is probably a lot better ways to create a unique ID but aim for the simple stuff first. :)
I also recommend that you look into CGI::Session which you require with require 'cgi/session'.