I want to mandate that all users accept terms of service, much like is described here:
Ruby on Rails / Devise - Bypassing custom validation option in model when resetting password
However there are 2 requirements that make the above approach not fit.
1) Users are not self registered, rather they are created by a system administrator. The administrator obviously can't accept terms and conditions on the users behalf. The user should be prompted to accept terms and conditions on their first login.
2) If the terms and conditions change after the fact. Users need to re-accept the new terms on subsequent logins.
These seem like pretty standard workflows. Does devise provide any way to accomplish this?
If not, I am thinking this check will need to be implemented in a before_filter on my application controller. (Feels dirty mixing authentication with the application logic...)
Will I have to resort to this or can anyone suggest a better way?
Thanks
this is not something devise would handle and devise should not handle this because a TOS does not pertain to authentication.
What you could do is something like implement a state machine but that may be more complex than what you need.
The simple way would be to add a accepted_tos boolean field to your user model and tie that into a before_filter then you would set the accepted_tos to false everytime the TOS is updated.
Couldn't you theoretically just disable moving further in your app using JQuery?
Disable your form "continue" or "log in" button until they have checked a box or hit a continue button, then enable your log in button once they have.
If you need to store that information just make a column in your database on the user which gets posted too when they check the box or hit the continue button, or you could even utilize the number of log in counts as a way of knowing.
If user.logs > 0 then the user has already accepted the terms.
If user.logs == 0 then the user needs to accept the terms before they log in.
I guess according to your question it seems like tying everything into Devise sounds overly complex.
Hope this helps.
Related
I'm writing an app that make some calls to my API that have restrictions. If users were to figure out what these url routes were and the proper parameters and how to specify them, then they could exploit it right?
For example if casting a vote on something and I only want users to be able to cast one vote, a user knowing the route:
get '/castvote/' => 'votemanager#castvote'
could be problematic, could it not? Is it easy to figure out these API routes?
Does anyone know any ways to remove the possibility of this happening?
There is no way to hide AJAX calls - if nothing else, one just needs to open Developer Tools - Network panel, and simply see what was sent. Everything on clientside is an open book, if you just know how to read it.
Instead, do validation on serverside: in your example, record the votes and users that cast them; if a vote was already recorded by that user, don't let them do it again.
Your API should have authorization built into it. Only authorized users having specific access scopes should be allowed to consume your API. Checkout Doorkeeper and cancancan gems provided by the rails community.
As others have said, adding access_tokens/username/password authorisation is a good place to start. Also, if your application should only allow one vote per user, then this should be validated by your application logic on the server
This is a broader problem. There's no way to stop users from figuring out how voting works and trying to game it but there are different techniques used to make it harder. I list some solutions from least to most effective here:
Using a nonce or proof of work, in case of Rails this is implemented through authenticity token for non-GET requests. This will require user to at least load the page before voting, therefore limiting scripted replay attacks
Recording IP address or other identifiable information (i.e. browser fingerprinting). This will limit number of votes from a single device
Requiring signup. This is what other answers suggest
Requiring third-party login (i.e. Facebook, Twitter)
Require payment to cast a vote (like in tv talent shows)
None of those methods is perfect and you can quickly come up with ways to trick any of them.
The real question is what your threat model and how hard you want it to make for users to cast fake votes. From my practical experience requiring third-party login will ensure most votes are valid in typical use cases.
Relatively new rails programmer here, so bear with me.
I have an app where registered users can create polls but anyone can answer the polls.
I am using Devise for my authentication. I want non-authenticated users to be able to answer the polls but I want to prevent double-voting.
I assume this should be done with persistent (not session) cookies, but I'm not sure. So when the user enters the site, I create a user in devise and I store some random value in both the User model and in the cookie, and I check that the user has not answered the question previously when he/she attempts to load my "answer" page?
Can someone give me some advice on whether this is the right approach and/or point me towards a resource to help me get started?
I have found relatively little information out there on how to manage persistent cookies in Rails.
You can't reliably prevent people from voting multiple times without logging in. It's not possible. I guess people could also create multiple user accounts to vote so there is no fool proof way.
Cookies are often cleared automatically by certain popular cleaners and unless you are only going to allow people to vote on a product they have purchased I think you are kind fighting a lost battle.
Stack Overflow limits voting capability by making sure a certain level has been achieved before being allowed to vote but I guess that's not really applicable to your scenario.
This is not so much about sessions and cookies and more about setting up your database to record a vote including the voter id.
In the view that allows users to vote I would suggest that you switch between a voted icon and a vote now link depending on whether or not the currently logged in user has voted.
To determine if the user has voted then include the user id of the currently logged in user in a question_vote xref table.
For the belt and braces approach to prevent abuse of the html in the browser add the check to the validations of the question_vote record.
I would do this by adding a can_vote? method to the user model that accepts a question id as a parameter then you can use the question_id plus the user id to find a matching record in the question_vote table if a reordx is found return false otherwise return true
I'm trying to implement a delayed-signup (aka delayed authentication aka gradual engagement) website flow using Devise + Rails.
By gradual engagement, I mean
"Don't make the user sign in until she
absolutely has to, but let her play
around and be remembered on the site"
I'm looking for a simple way to do this using devise. I feel like this is something many others have had to do, but I haven't found documentation on it.
The following approach sounds ok in my head, so I'm going to start with it:
Create users that are only "rememberable"
When certain pages are accessed, require that these users have more
data on them, like a username and
password, via something like
"before_filter :authenticate_user!" in
the appropriate controllers.
Does this approach make sense? Is there a better one? Do you have an implementation of a gradual engagement approach to signup/registration forms using Devise + Rails that you're willing to share?
I think the point of the article you gave us is to say:
only ask for sign up if necessary.
What does this mean?
Let's take an example. You're an e-commerce web site.
When does the customer has to sign up "at last"? During checkout. Never before. So you don't have to store, or remember anything about the user. Devise is never, never used here.
How do you manage the shopping cart of an unsigned in/up user? I'd say database, with session Id as primary key. Or You could store all the items ids in cookie, for later use.
In your code, if you have an action called checkout, just set in your controller a before_filter authenticate_user!, :only => [:checkout]
But maybe you have some constraints, like being able to keep your user's nickname without signing him up for example?
One alternate option is to do email-only signup, then send an email with a special link to finish registration later / bring them back to their account. There's an actively maintained tutorial on devise email-only signup at:
https://github.com/plataformatec/devise/wiki/How-To:-Email-only-sign-up
I've used this tutorial for a site I did a while back where we only asked for their email address to sign up, then later sent emails for them to complete registration / add a password.
You can keep all unsigned user's data in cookies, and transfer them to database once the user logs in, if you need to.
What would be the best way to go about giving users the ability to share a private link that enables anyone who clicks it to view a certain page/document/item that have privacy restrictions in place?
In my case:
A User creates events which are limited to certain groups of relationships in the database (namely: friends, friends of friends, etc.) I have a :before_filter in the event controller that checks the eligibility of the current logged in user to make sure that that user has permission to see the event. If they don't they get booted to the root page with an error message.
However, I want a special scenario to exist where a user can create an event with those same privacy settings and IN ADDITION, be able to share a special link with his or her friends via e-mail, facebook, etc. Those users do NOT need an account (but will need to make one in order to sign up for the event). This is important because there is also a :before_filter in the application_controller which makes sure a user is logged in.
I'm thinking there is something I could do with routing here... Right now I just have the simple /events/72 setup. Should each event have two different links: a normal one, and a "special code" version which enables them to bypass those two :before_filter?
What are people's thoughts?
I agree with David Lyod's answer (separating this concern in a different controller).
But for creating the hash I strongly recommend you salting the hash with some secret phrase.
require "digest"
Digest::SHA512.hexdigest("#{created_at}#{user_id}.mysupersonicsecretSALT")
Doing this it is not possible, without the knowlegde of the secret phrase, to calculate the hashes and test them against your system until it hits an existing one.
If you're handling sensitive data you should not be lazy.
Cheers,
Lukas
I would have a separate controller that uses a hash value to reference the event.
Something simple like the created_at + user_id hashed to create a unique reference.
You could also simply skip the check on a certain action but I would much prefer the first solution .
I'm required to provide functions for both users and administrators to edit account and profile details in a web application. An example of a URL for the public side of these profiles is:
http://example.com/user/joe
I'm still torn between two ways to design these URLs. I've thought of either this:
http://example.com/user/joe/edit
Or something non-specific and separate to the profiles:
http://example.com/account
The benefit of the first one is that it allows administrators to do their job through the same functions. This avoids building a whole different backend specifically for administrators. I suppose the negative here is that I'd have to be careful with authorization and make sure nobody can edit what they are not supposed to edit.
The second is a more standard way of doing things, it'd turn out to be simpler and easier to secure, though it means a separate interface for administrative users.
What is SO's opinions on this? Are there any more pros/cons for either way? Which method would you recommend to use?
I would have a different view for the administrator with such a security sensitive area. It makes things much more explicit having a separate view. It is likely even an administrator would only be able to edit certain user information and thus have a different view to the user editing themselves.
It makes the authorization much clearer even if the two views shared a common edit form
If you are using an MVC approach, then my suggestion would be:
http://example.com/user/edit/1234
or
http://example.com/user/edit/joe
Where user is the controller, edit the controller method and 1234 or joe the user id or username respectively.
But as Gumbo commented, administrators should not be allowed to edit user information. They should have some mecanism to disable the account in case of a profile has offensive content or false info. Forcing the user to update it to get the account active again.
The way we do it is the admin and the user share the same view. Items which are admin-only are protected from editing or viewing by the user.
The reason for the single view is:
It reduces the number of 'moving parts' - when a new field is added to the user screen, it only needs to be added once,
It is easier to move items to/from the user's purview. If all of a sudden, management decides to allow a user to manage their "FizzBar" then we only need make the change in one place, and
It is easier to segregate the roles and the functions at the controller level.
I think that you should go with the second approach. It's more secure and flexible, and shouldn't be harder to code than profile editing the profile inline.