rails 4 - ldap authentication and user objects without database - ruby-on-rails

I have an app where users log in and the LDAP server is used to authenticate them. That part I have down, but the hiccup comes when dealing with the users and multiple sessions.
When a user is authenticated I create a new user object from a user model that inherits from ActiveModel, saves their name and email from the LDAP entry. This is done in sessions_controller with user as an instance variable. i.e. #user = User.new
However when current_user in application_controller checks for the user object, it's value is nil.
I'm guessing this is a scoping issue where the application controller can't see the instance variable in session controller's value.
Without using a database, how could I handle saving this minimal info about a user and have it persist through out their session? Before when using a class variable ##user and setting it in application_controller other users were only able to log in one at a time...Thanks for any help in advance!

Assuming your User object is small, you can store it in the session.
class SessionController < ApplicationController
def authenticate
# Handle LDAP-auth and we now have a user
# ldap_authenticated? should be true
# ldap_user contains relevant info from LDAP
session[:user] = User.new(email: ldap_user.email) if ldap_authenticated?
end
end
module ApplicationHelper
# Use this to access the current user everywhere in the app
def current_user
session[:user]
end
end

Related

Rails: How to invalidate all user sessions in all browsers on logout from one browser using Devise?

I am using Devise gem for login/logout of the users. When a user logs in in two browsers, and then logs out from one of them, the other browser is still active. I want the user to be logged out in all browsers when they log out from one. How can I do that?
Add a session_token column to your devise model (e.g. User) and override Devise #authenticatable_salt method to contain your session token:
class User < ApplicationRecord
def authenticatable_salt
return super unless session_token
"#{super}#{session_token}"
end
def invalidate_all_sessions!
update_attribute(:session_token, SecureRandom.hex)
end
end
You can now invalidate the session cookie by resetting the session_token of a user, when he/she logs out:
class Users::SessionsController < Devise::SessionsController
def destroy
current_user.invalidate_all_sessions!
super
end
end

Create password and authentication for existing users

I have rails app with:
Admin table with Devise authentication
User table with email and name without authentication (but session to remember them)
User can browse anywhere but now on certain pages I would like to enhance it and add authentication - allow user to create password and only with password it will be accessible but I am quite lost what is the best way to do it with the current setting?
I allow users to add their details like name and email and I am creating a cookie to remember them without any authentication or password:
UsersController
def create
user = User.find_or_create_by(email: params[:user][:email])
cookies.permanent.signed[:user_id] = user.id
session[:user_id] = user.id # for users/edit temporary
render json: user
end
Let's say I have this following method in User:
before_filter :authenticate_user!, only: :your_order
def your_order
end
If User will visit this page and didn't set up password before, how can I prompt him to create one and how can I require for him to login after with Devise? I am thinking of more solutions but none of them are perfect.
As per the specifications given the below mentioned criteria might help you.
def your_order #before_filter
if user.password.present?
# authenticate using valid_password? method of devise
else
#redirect user to say set_password
end
end
def set_password
#set the user password in this method and after successful completion redirect to login page where before filter your_order will be called
end

How do I check if my user is an admin in rails even after new http requests?

My user model has the attributes password, password_confirmation, username, email, and admin.
I'm wondering how exactly do I check whether the currently logged in user is an admin. How would I go about the methods? I've tried if user.admin? on my views, but it seems that doesn't work.
I'm new to rails so any suggestions would be helpful!
There is a "session" hash which persists through the whole session.
Once a user has logged in, you would store the current user's id in the session hash, like so
session[:user_id] = user.id
Now, if you want the current user to be accessible from your controllers and in your views, you can go to apps/controllers/application_controller and make some useful methods...
class ApplicationController < ActionController::Base
protect_from_forgery
helper_method :current_user, :signed_in?, :is_admin?
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def signed_in?
!!current_user
end
def is_admin?
signed_in? ? current_user.admin : false
end
end
Now in your views you can use "is_admin?" to check if the current user is an admin, use
"signed_in?" to check if a user is signed in, and "current_user" to access the user object if it exists (if no user is logged in, "current_user" will be nil)
Cheers
I suggest you to consult with this Devise guide. It shows how to create a basic user model with help of Devise and how to perform admin checks. And yes, by giving you this link, I strongly encourage you to use Devise gem for users and all that stuff ;)

Devise, merge guest and user session

Is there a way to hook into signin process (using devise), to merge "guest" session data before signing in, and some other data (Mysql) after signin in?
For example I need to merge user's cart data from session, when he goes to ordering step and logs in, and already has items in DB
Found some solutions here, but I don't want to create guest users in DB, just need to merge sessions
It would be a bit hacky, but you could do it in the after_sign_in_path_for controller method.
class ApplicationController
def after_sign_in_path_for(user)
merge_cart_from session[:cart] # or whatever
root_path
end
end

detecting if user is logged in at different domain

I'm developing a rails app that creates a widget that you can put on your website. When the widget is displayed (on a website with a different host) to a user who is logged in my app, I would like to display him some additional admin options.
What would be the best and easiest way to figure out if the user is logged in the app?
I was thinking of storing the IP when user logs in, and then compare the IP from the request that is sent to the widget controller.
I followed the Omniauth Railscast Episode and have been using session variables and a SessionsController to create and destroy sessions when the user logs in and out.
class SessionsController < ApplicationController
def create
# create user if new user, or find user account if returning user.
session[:user_id] = user.id
redirect_to root_url # or wherever
end
def destroy
session[:user_id] = nil
redirect_to root_url # or wherever
end
end
Then in the Application Controller,
class ApplicationController < ActionController::Base
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
You can then easily determine if a user is logged in or not via if current_user, or equivalently, if session[:user_id] is nil.
IP could be deceptive. Try cookies.
Edit: not only in an actively deceptive manner (i.e. spoofing/Tor) but rather if two people are on separate sites from the same public IP, then you have a false correlation.

Resources