I am using Postgresql as my database and rails 3 as my middleware for a multi-tenant application.
I would like to set an environment variable containing currently logged in client id for every connection that gets created via establish_connection method.
Is there anyway I can intercept initialization process through any callbacks of establish_connection to set this environment variable?
I would lean towards separating data at the app level by something like an authority_level field. You could then have a "verify_permission(current_user)" method run as a before_filter.
We typically do this and have a "kick_user_out" method that automatically forces a logout and emailed admin alert with non-sensitive params for the purpose of alerting admins when a privilege escalation occurs. You get enough of those and the account gets locked as well.
Related
I have an application that has an actual map of objects that any visitor can view as long as they have the correct access code. I don't require the user to login because I don't want to make them create an account as it is unnecessary. I want to allow the users to mark the objects on the map with a check and save the edits within the session. So if the user refreshed the page or they close the application and reopen it an hour or so later, I would like to save their marks based off their session id. But I am confused on how to set this up without requiring them to login because I am unsure how the sessions would work.
Any help would be greatly appreciated!
Sessions in Rails work the exact same way regardless if you have a proper authentication system or not.
When a first time visitor visits your application the sessions middleware creates a session identifier. This is a cryptographic hash that is kept by the server and also passed to the user in a cookie.
This lets you identify users across requests.
This session identifier is also linked to a session storage. By default this is ActionDispatch::Session::CookieStore which lets you store session data in a encrypted cookie held by the client. This is where you would normally store a user id. Since its a cookie the amount of storage space is very limited. If you want to store more data in the session you can use a different store such as Memcached, Redis or ActiveRecord.
But what you may want to consider is creating (guest) user records implicitly without the normal sign up procedure. I would just use Warden and have a bare bones user model and a cron tab that cleans out unneeded data periodically.
This gives you a database oriented application model where you can use associations and build it like a standard rails application instead of the untestable mess that results when someone goes bonkers with sessions.
I would implement Cookies (with their permission of course). You can store basic data in it, or even create a sort of ID for them so when they return you can restore their settings
I am developing a web application using rails and devise for the authentication. There are two types of users, one who are able to have multiple concurrent sessions (super) and the others who can only have a simultaneous session (normal). In order to implement this behaviour, I have added a new field on the User model to store the authentication_token (generated in the SessionsController#create). Also, I added a new filter to the ApplicationController which check if the stored token in the session is equal to the saved on the User model when it is a normal user. When it is not the same authentication token, we logout the normal user.
Now I am developing a new ionic mobile application which needs to login to the same rails application. However, in this case all user types can have multiple concurrent sessions. In order to do this, we would like to continue using devise (although we have also considered to use doorkeeper with password flow).
I am not sure about the best approach to get this. The main problem is to detect if we are accesing the API with the rails or ionic application. One approach is to add a parameter but I don't like to use a parameter in all requests. Another approach it is to use browser gem, but we can access the web from a browser in the mobile.
When we uses the rails application, we can use the same behaviour described above. Otherwise, I think it is not necessary to do anything because devise permits concurrent sessions by default.
Another posibility it is to use a new model to store the authentication token and its type (rails or ionic). If we are using the rails application, then we query the rails authentication token and override it (or create if it does not exist). On the opposite, we add the new authentication_token as a new instance related with the user model. With this behaviour we can manually control the expiration of the tokens and store more information (IP, browser...).
I am not sure about the best approach to achieve this behaviour. Thanks in advance.
Setup
I have a Rails application where users register for an account, and a subdomain is created for them. They can then proceed to the subdomain and log in with their credentials. The workflow looks something like this:
User visits base domain fills out a form that with email/username/password and subdomain fields
From the submitted info, the server creates an account in the global/public database. Server then creates a database that will be specific to that particular subdomain/account, and stores the user record in it.
User is redirected to their subdomain, and asked to log in.
(note: to implement the separate "databases", I'm using postgres schemas, but that should be irrelevant.)
The question
My question involves step 3. I would like to redirect the user to their subdomain and log them in automatically instead of asking them to log in. However, I do not want to share a single session across all of the subdomains.
I would like to somehow securely transmit auto login request.
Possible Solution
I have considered using a single-use, random token that I would store in a cookie and in the users table. After the user successfully creates an account, he would be redirected to the subdomain. At that point the token would be consumed/destroyed and the user would be automatically logged in.
I would also need to have a short window for the token to be used before expiring.
Thoughts? Thanks!
I had the same issue, the possible solution you suggest does not work because the session is not shared between subdomains.
I solved it the following way (same idea you propossed, different implementation):
Create a new model (I called it LoginKey) that contains the user_id and a random SHA1 key.
When the user is authenticated at the parent domain (for example: mydomain.com/users/sign_in), a new LoginKey is created and the user is redirected to the corresponding subdomain to an action that I called login_with_key (for example: user_subdomain.mydomain.com/users/login_with_key?key=f6bb001ca50709efb22ba9b897d928086cb5d755322a3278f69be4d4daf54bbb)
Automatically log the user in with the key provided:
key = LoginKey.find_by_login_key(params[:key])
sign_in(key.user) unless key.nil?
Destroy the key:
key.destroy
I didn't like this solution 100%, I tried out a lot of different approaches that do not require a db record to be created, but always faced security concerns, and I think this one is safe.
I have hosted a rails application, an online examination system. The users need to get registered to get access to the system. So each user will be provided with a unique combination of credentials. Let us assume my user-name/password is demo/demo123. I want my app to block another person logging in to the system even if he knows my credentials. Any solution for such scenario.
Thanks for any help :)-
Using Cookie would be a better solution. When the user gets registered create a Cookie value specific to the User and System and in encrypted format (for security reason) and save it in the database corresponding to that user. Check for this Cookie token while logging in. When the user clears the cookie, s(he) can request the Administrator to clear out the DB cookie for creating a new one.
Using IP will not be a better solution since in a network, there can be dynamic IP's allocated to the PC's.
You could record the user's IP address in the database when they first log in, and only allow logging in using the same credentials but from a new IP address after some waiting period of, say, 1 hour, or until the current examination is complete. That should prevent more than one user being logged in to the same user account within a short time period.
The user's IP address can be accessed in a Rails controller using request.remote_ip.
You could use the lock gem to add a password to the entire application.
First, add to your Gemfile.
gem 'lock'
Then
bundle install
Next, create your password
rails g lock:create_password_file yourpasswordhere
Finally, add lock your application controller, or whatever you'd like (see documentation).
ApplicationController < ActionController::Base
lock
end
I have to develop multisite application with single sign on across domains (something like google account with multiple google services like gmail,docs,google+):
To use childen sites user must to sign up on parent site.
Each site have its own logic except user sign in, points and
invoices.
From child application I must be able to sign in to global user
account, spend user points and generate invoice for some service.
Sign up form, listing of invoices and panel for managing points are
avaiable only from parent site/application.
What is the best strategy for implementing this on Rails 3.1? Scalability, performance and security are important.
Single or multiple rails applications?
Single or multiple databases?
Global services in main application or as a separate applications/engines?
How to implement single sign in? Single session id in DB or something like facebook oauth?
How to implement spending points and generating invoices as a result of request from child site?
You should be able to implement this using OmniAuth with multiple (and independent) Rails applications. These will be of interest:
https://github.com/joshsoftware/sso-devise-omniauth-client
https://github.com/joshsoftware/sso-devise-omniauth-provider
Blog post on the subject: http://blog.joshsoftware.com/2010/12/16/multiple-applications-with-devise-omniauth-and-single-sign-on/
So lets say you create the Model User in the main application and migrate it. Then what you need to do is accessing this Datbase from the other Applications. That is no problem . First you need to add the Database Connection definition of the Main Application to the config/database.yml of the child application like this:
parent_connection:
adapter: your_adapter_here
host: your_host_here
username: username
password: password
database: main_application_production
Then you create a Model called User but not with the scaffolder or sth. like this. Just create the file manually like this:
class User < ActiveRecord::Base
establish_connection :parent_connection # This uses the specified connection
end
At the default case the connection selected is the one that matches the name of the environment. You only need to specify variations. So now you can access the User class like in the main application.