I have an ExtJS6 app as frontend and rails at backend. Using devise for authentication. sessions#destroy looks like
def destroy
cookies.delete :auth_token
reset_session
sign_out(:user)
render json: { success: true, message: 'Successfully logged out' }
end
it does logs user out (seemingly) but refreshing page logs previous user in
It seems like cookies are not getting reset
Take a look at these two issues:
https://github.com/lynndylanhurley/devise_token_auth/issues/486
https://github.com/lynndylanhurley/devise_token_auth/issues/375
They explain why deleting your session may not be persisting. You'll need to override your sessions controller. Full explanation there.
Related
I have a method that creates a new user session and will redirect back to the previous screen after successful login. It has introduced a security issue where someone can type in a url navigate to a page they shouldn't have access to. The app will direct them to login, but after logging with valid credentials (just not the proper level of clearance) it will redirect them to the page they had manually typed into the url. How can I verify that redirect_back isn't sending a user to a page they shouldn't have access to?
Here is the session create method:
def create
#user = authenticate(params)
sign_in(#user) do |status|
if status.success?
redirect_back root_path
else
flash.now.alert = status.failure_message
render :new, status: :unauthorized
end
end
end
Is there a way to see what address it will be sending them back to because I could just do something like
if back_url.includes? "admin"
redirect_to root_path
end
You can’t rely on URL obscurity for security of your application. Your admin routes or controllers should be protected so they can only be accessed by signed in admins.
You can do this with a route constraint in your routes file (my preference) or a before action that is consistently applied across all of your admin controllers that returns a 403 if the current user is not an admin.
I made Devise authentication to log out via GET, but couldn't make it log out using this Angular.js code:
$scope.logout = ->
$http.get('/users/sign_out').success ->
#If it does not redirect from 'editor' to 'login' then you haven't actually logged out
$location.path('editor')
Devise's logout behaviour seems to be random - sometimes it logs out, sometimes not.
And if I enter /users/sign_out into browser's address bar, it logs out always.
Ok, I switched the Devise authentication's log out to POST request to get rid of caching problems and used following Angular.js code:
$scope.logout = ->
$http.post('/users/sign_out').success ->
$location.path('editor')
The first time it logged out fine, as always, but then I couldn't make it to log out.
I decided to make my own method to see what happens:
match '/logout' => 'api#logout', :via => :post
class ApiController < ApplicationController
before_filter :authenticate_user!
def logout
sign_out
if current_user
puts 'Has not signed out!'
else
puts 'Has signed out!'
end
head :ok
end
end
and detected that after sign_out the current_user is always nil, but then the Angular application by some miracle manages to access other methods of ApiController, and current_user isn't nil there!
I do not understand that. Ok, let us suppose that there may follow some other HTTP request, right after (or at the same time as) logout request, passing the authentication cookie and Devise re-logins, but shouldn't the session ID passed in cookie be expired immediately after call of sign_out method?!
sorry I never responded earlier, hope this helps
My Sesisons Controller
$scope.signOutUser = function () {
$http.delete('/api/users/sign_out', {
auth_token: Session.currentUser // just a cookie storing my token from devise token authentication.
}).success( function(result) {
$cookieStore.remove('_pf_session');
$cookieStore.remove('_pf_name');
$cookieStore.remove('_pf_email');
location.reload(true); // I need to refresh the page to update cookies
}).error( function(result) {
console.log(result);
});
}
My Devise Sessions Controller I overrode
class SessionsController < Devise::SessionsController
before_filter :authenticate_user!, only: :destroy
def destroy
token = params[:auth_token]
#user = User.find_by_authentication_token(token)
#user.reset_authentication_token!
sign_out(#user)
render status: :ok, json: {message: "You have successfully logged out"}
end
end
As you can see, I'm not using Rails cookies and thus my answer may not pertain. If I did I would probably add a line like session[:user] = nil in my destroy action.
Here is what I have for redirecting to a default url(myapp_url). But I want to change redirect to go the request url was entered by the user after authentication.
How do I do that? I tried couple of options from searching here, like :back. But no go.
User enters an url, if not authenticated then gets redirected to the login page, then after login user shall be redirected to the original request url.
def create
user = User.Authenticate(params[:user_id], params[:password])
if user
session[:user_id] = user.id
redirect_to myapp_url, :notice => "Logged in!"
else
flash.now.alert = "Invalid email or password"
render "new"
end
end
You can read the chapter about "Friendly forwarding" in the "Ruby on Rails Tutorial" by Michael Hartl to see how you can easily implement it.
Basically you have 3 helper methods:
store_location to store the user desired location in the session
redirect_back_or(url) redirect the user to the location stored in the session or, if not set, to the location contained in the url method param
and clear_return_to used "internally" by the redirect_back_or method to clear this piece of information once used
And then you use these methods:
A) when you see a guest user try to access a page that needs authentication use store_location before redirect him to the login page.
B) when a user is logged in, you use redirect_back_or(url) to redirect him to the right location (if present of course)
This is an overview of how this work, you get the idea but I suggest to read that chapter for the implementation (few) details.
You need to save path in session before redirection on authentication, and after successful auth redirect to this path.
I have a popup that will only allow to view/save some information if the user is authenticated.
I am using devise.
In the controller before_filter it checks if user is signed in and if not, show a sign in page.
This sign in page is ripped down version of the site's sign in page, so that it fits nicely to the popup.
On the authenticate action I call authenticate_user!. Everything works fine when the user enters valid credentials. But when the credential is invalid, devise automatically redirects to site's sign in page (which as I stated is different and not fit for a popup)
I tried appending a rescue to the call, but to no avail.
Anyone could suggest a better/right way to do this please? :)
def authenticate
authenticate_user! rescue redirect_to "/popup/sign_in"
if user_signed_in?
respond_to do |format|
format.html {
flash[:notice] = I18n.t("logged_in_succesfully")
redirect_back_or_default(accounts_path)
}
else
flash[:error] = I18n.t("devise.failure.invalid")
render "/popup/sign_in"
end
end
I've implemented authlogic in a rails site, and I'm trying to get openid to work correctly. So far, you can login just fine as long as you have an existing account, but not so much if you don't. I'd like to be able to automagically create a new account if the identity_url is not already in the database.
The problem is that I also need to store some additional info. if the user is logging in for the first time with their openid, I'd like to ask them to fill in basic info (name, email), BEFORE the account is created.
I've played around with a few methods, but nothing seems to be working.
Thanks in advance for any input!
acts_as_authentic do |c|
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
end
Will allow you to require an email. I'm unsure of how to require other fields, but maybe check that axschema.org page. There is no need for the user to fill anything out other than their OpenID provider URL.
Combining login and registration could be done with something like this (untested create method from UserSessions controller, like from the authlogic tutorial stuff)
def create
if User.find_by_openid_provider(params[:user_session]).nil? # or something like that
#user = User.new(params[:user_session])
if #user.save
redirect_to whatever_path
else
# handle error
end
else
#user_session = UserSession.new(params[:user_session])
if #user_session.save
add_message 'Login successful!'
redirect_to whatever_path
else
render :action => :new
end
end
end
Maybe try putting the additional information into a temp table of some kind, and keep track of the session the user is in. Once they have authenticated, connect the previously entered information with the OpenID information to create the real user.