I need some advice on a Rails app where I want to have signing up to be private (or not have one at all with users pre-registered in the seeds.rb file). In other words, I do not want random people off of the internet to be able to sign up. I know that I could easily not making a signup form and tweak my app accordingly, but the problem lies with the seeds.rb file containing sensitive information (i.e., passwords). The passwords need to somehow be encrypted. Any advice would help. Thanks.
You have multiple options:
Disable sign up and do it manually using an admin user (thinking about ActiveAdmin gem).
Register that users at DB (without rails' knowledge). I don't know what DB you're using, but imagine you're using postgreSQL (for instance). Go to your DB and manually insert the users on DB using some kind of user interface (command-line or graphic/visual)
Use environment variables at deployment that contain passwords.
Give them a default password and make them change password once they log in.
... there are more options, but you need to be explicit about what you want to achieve. Do you want to start with X users and don't add more? Do you want to start with X users and be able to expand to more users?
Related
I have a webapp build with rails. Nothing complicated so far. Now I would like to restrict some areas for the user. I would like to implement two roles, User and Admin. Clearly the admin can do much more, like use DELETE in some of the controller methods. But there is even more. The user should be able to set some settings. For example he can set his profile to private, so only his friends can see his content. I am not sure how to build all of this with rails.
I did some research and found those two:
https://github.com/elabs/pundit
https://github.com/ledermann/rails-settings
Maybe a combination of those two would get me to the way I want the app to be?
If the app is going to be used used by real users i would go for the devise gem(https://github.com/plataformatec/devise) It allows user to create accounts, retrieve lost passwords etc. By default it allows users to edit their "profile"(rather their personal data), it should be easy to add a checkbox to toggle public/private profiles.
In conjunction with cancancan(https://github.com/CanCanCommunity/cancancan) you can assign roles to users, without having two different classes(Users and Admins for example).
Rails has some very good methods for role based authorization, e.g., cancan
But how can you grant authorization to specific pages, rather than controllers/actions.
For example, take the case of an app that contains a receipt or invoice model. A User can log in and generate an invoice. The User then needs to send his customer a URL to that invoice. The customer should not be able to access invoices of other customers, particularly important as Rails generates sequential and easily guessable path names (e.g., /invoices/1, /invoices/2, etc.).
Ideally the customer should not need to signup to view these pages. One solution might be to generate a random password on Invoice creation, and send this to the customer to unlock that page specific page.
This sounds like an issue that should be reasonably common, but after Googling I have not found much information of use (though I may be using incorrect search terms).
So I would like to know:
Is this something I should be attempting with Rails?
Are there any gems or example apps that I could study?
What are the potential considerations/ pitfalls of this approach?
Hi if the user you wish to have access was registered in the system it would be no issue at all as you could generate a permission record.
How ever your concern with the predictable urls can be easily solved by :
FriendlyID(https://github.com/norman/friendly_id)
or my personal favourite
Vanity permalinks (http://blog.teamtreehouse.com/creating-vanity-urls-in-rails)
Ideally the customer should not need to signup to view these pages. One solution might be to generate a random password on Invoice creation, and send this to the customer to unlock that page specific page.
So anyone with the information should be able to access it. One solution is to obfuscate the url or use a UUID, so don't give out /invoices/1, instead give /invoices/8a20ae59-30d5-41b6-86d3-ac66e3b43e9d. The url is unguessable. Still the url is the only piece of information one needs to access the contents.
If you want two-factor authorization, then the easiest way is to use http basic auth, generate a password from the url and your secret_base, and send it to the user separately. As it's generated, you don't need to store it, you can always check it by generating it again.
I am looking to set up 2 rails apps (with the same tld) which have single sign on and share some user data. If I have railsapp.com I will have the second app set up as otherapp.railsapp.com or railsapp.com/otherapp. I will most likely have railsapp.com handle registration/login etc (open to suggestion if this is not the best solution).
So lets say I sign up and upload an avatar and start accumulating user points on the main-app, I can then browse to the other-app and my profile there has the correct avatar and points total. is there an easy way to achieve this? Do the available SSO solutions create the user in the second app with the same user ID? if not, how are they tied together? (ie how can I query the other app for information I would like to be shared across the 2 - user points and avatar) I was initially looking at sharing a database or at least the user table between the 2 apps, but I can't help thinking there must be an easier solution?
I think the simplest solution is if you set the cookie on the .railsapp.com domain, then it should be sent when you do requests to otherapp.railsapp.com or any other subdomain (just stressing that as it might be a security concern). Remember to mark the cookie as secure!
And a extra bit you might need to make this work, is to store authentication tokens on a database so they can be shared between the two apps.
Disclaimer: I don't have much experience with Rails anymore, so I'm not sure if some of the frameworks like Devise can do something like this out of the box.
Edit
Got curious and ... google had the answer: http://codetheory.in/rails-devise-omniauth-sso/
My Scenario:
Sessions are being stored in the database using ActiveRecord::SessionStore
User is on site at 'http://domain.com '
they go to secure checkout at 'https://domain.secure.com' (our app has lots of domains, but want to send everyone through secure checkout on the same domain to save SSL headaches).
We append session_id and a hash to authenticate and identify the user at 'https://domain.secure.com'
Load that users session data by doing ActiveRecord::SessionStore::Session.find_by_session_id(session_id)
The above all works fine. BUT how can I actually set the same session_id to the user once they are on 'https://domain.secure.com'? I can loop through the data and assign it to the user's session, but Rails automatically gives the user a new session_id on 'https://domain.secure.com'. I want the users session to be stored in the same database row regardless of whether they are on 'http://domain.com' or 'https://domain.secure.com'
Why do I want to do this? For ease of expiring sessions. I can just remove that row from the sessions table.
Otherwise I'm thinking I'll have to add a user_id column to the sessions table and then when i want to expire the session, I delete all rows for that user. But this sounds more complicated to me. I'd rather just have one row in the sessions table.
Any suggestions?
A couple ways to approach this.
One, you could look at a higher level of abstraction for authentication that lets you manage cross server. For example, Devise http://github.com/plataformatec/devise
Second, you can override the whole session controller and write your own session manager. A bit more work, but not that complicated if you ultimately need a bunch of custom functionality. I remember correctly, start with this in your environment:
CGI::Session::ActiveRecordStore.session_class = MySessionClass
and go from there..
Passwords are one-way encrypted and will remain so, but is there a way I can easily export these crypted passwords and use in a different app?
Are you talking about moving them from one database to another? Or allowing a different application access to the same database?
Either way, sure, that's fine as long as the logic in the new app uses exactly the same hashing/encryption algorithm to check the users' entered password with the stored one.