When a user tries to connect via this method and it fails. How do I redirect_to? Thanks in Advance.
class ApplicationController < ActionController::Base
protect_from_forgery
USER_NAME, PASSWORD = "admin", "admin"
helper_method :authenticate
private
def authenticate
begin
authenticate_or_request_with_http_basic do |user_name, password|
user_name == USER_NAME && password == PASSWORD
end
rescue
"HTTP Basic: Access denied"
else
redirect_to root_path
end
end
end
Rails - authenticate_or_request_with_http_basic custom "access denied" message
In the past, we've made authenticate a before_filter which will just perform the authenticate_or_request_with_http_basic, and then have our redirects/renders happen in their respective actions.
I just re-read your question & code sample. What exactly are you looking to have happen? A redirect on fail of the authentication?
Edit: I've never done this, but it seems like trying to follow the docs might be your best bet, in particular, the "more advanced basic example."
I ultimately don't know enough about the inner workings of basic auth, but it strikes me as it could also boil down to an Apache/(insert your awesome web server here) configuration. Someone will definitely correct me on that if I'm wrong.
Related
I would like to protect a site with a very simple password only validation when user first visits site. I currently use http authentication, but that requires a username & password. I can hardcode password in back end. Basics of site: local sports league where we keep our stats and info about league. Simply trying to keep "riff-raff" out :)
I am a ruby on rails newbie, and am using this site as a way to learn. Any help out there would be appreciated!
You could do something cookie-based.
In your ApplicationController, you'd implement a method for determining if the cookie is present that states that the visitor has entered your password – if the cookie isn't present, then you'll redirect to your password page:
class ApplicationController < ActionController::Base
def require_password_verification
unless cookies[:visitor_password_verified]
return redirect_to <whatever your passwords#new path is>
end
end
end
The controller for your password page would look something like this:
class PasswordController < ApplicationController
def new
# Nothing needed here because all your #new view needs is a password field
end
def create
unless params[:password].present?
return redirect_back(fallback_location: root_path, alert: 'Password is required.')
end
if params[:password] == Rails.configuration.visitor_password
cookies[:visitor_password_verified] = true
redirect_to(root_path, notice: 'Password verified.')
else
cookies.delete(:visitor_password_verified)
redirect_back(fallback_location: root_path, alert: 'You've entered the wrong password.')
end
end
end
Your password would be stored in the application.rb file, like so:
config.visitor_password = '12345'
Normally, you would never store a password in this way because it's not secure at all but considering your use case, it's probably fine, since having a single password for everybody is already not secure. 😃 However, if you did want to step up the security a notch, I would recommend storing your password in an environment variable, and then you could set the password like so:
config.visitor_password = ENV['VISITOR_PASSWORD']
That way, at least your password isn't hard-coded and accessible to anybody who looks at your, assumedly public, repo.
And then you can require the "password has been entered" cookie for whatever views you want like so:
class LeagueStatsController < ApplicationController
before_action :require_password_verification
def index
# Whatever
end
end
If somebody hits your league_stats#index page, then it's going to check to make sure the visitor_password_verified cookie is present and true first. If it is, then they'll get through to the view. If it's not, they'll be redirected to your passwords#new page.
I am developing a rails application, that allows optional HTTP basic authentication.
Authorization should be allowed, but not mandatory.
To do this, I am trying to use a before_action inside the application controller, that will try to find a user matching the given credentials and either write that user or nil into a global variable.
I tried this, but the block for authenticate_with_http_basic doesn't seem to be called at all (The console doesn't show the username and password, that I supplied, however logging outside of the block works):
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :authenticate
def authenticate
authenticate_with_http_basic do |username, password|
logger.info "Login:"+username+" "+password
#auth_user = User.authenticate(username, password)
end
end
end
And I tried this:
def authenticate
if user = authenticate_with_http_basic { |username, password| User.authenticate(username, password) }
#auth_user = user
end
end
I also tried this, which throws an error undefined method 'split' for nil:NilClass. When looking at the documentation, I see that split is being called on part of the request. Am I doing something wrong with just assuming the request variable should be accessible from a before_action inside the application controller?
def authenticate
username, password = ActionController::HttpAuthentication::Basic::user_name_and_password(request);
logger.info "Login:"+username+" "+password
#auth_user = User.authenticate(username, password)
end
I just need a simple function that gives me username and password as string variables. What am I doing wrong? Is there another way to accomplish that seemingly simple functionality?
Update
The things I tried seem to work. My only mistake was to use a regular webbrowser to debug my API. Most web browsers don't send authorization to the server, before they get a www-authenticate header back, even if the user explicitly included it in the URL.
As long as it is just used as an API or accessed through other ways, this should not be a limitation. However, this kind of optional authorization, that does not present an authorization dialog doesn't work with regular browsers (at least not as a HTTP authorization). It is not a problem with Rails, just the way browsers are built.
you might just be using the wrong method. this is one of the examples from ApiDock:
class AdminController < ApplicationController
before_filter :authenticate
def authenticate
authenticate_or_request_with_http_basic('Administration') do |username, password|
username == 'admin' && password == 'password'
end
end
end
see this question for more details: In Ruby on Rails, what does authenticate_with_http_basic do?
UPDATE
i don't see any problems without requesting basic auth. it works as expected:
class HomeController < ApplicationController
before_action :authenticate
private
def authenticate
authenticate_with_http_basic do |username, password|
logger.info "try basic-auth without requesting it: username=#{username} password=#{password}"
end
end
end
calling an action with credentials:
curl -I "http://uschi:muschi#hamburg.onruby.dev:5000/"
gives the following logs:
[hamburg.onruby.dev] [127.0.0.1] [044cb7ea-56a9-4f] Started HEAD "/" for 127.0.0.1 at 2013-10-21 17:40:54 +0200
[hamburg.onruby.dev] [127.0.0.1] [044cb7ea-56a9-4f] Processing by HomeController#index as */*
[hamburg.onruby.dev] [127.0.0.1] [044cb7ea-56a9-4f] try basic-auth without requesting it: username=uschi password=muschi
I would like to use a web server based on Rails.
But I have no idea about how to check a user's identification.
For example, a user named Guest could only perform actions like GET and UPDATE on certain tables, while another user named Admin could perform all possible actions such as POST.
I am new to this area, but I heard there are some technicals like SQL injection could threaten the security of the web server.
So, could you tell me how to check the authentication and how to encrypt password entered by the user?
What you seem to be wanting is authentication and authorization.
For authentication:
https://github.com/plataformatec/devise
https://github.com/vpereira/authlogic
https://github.com/thoughtbot/clearance
For authorization:
https://github.com/be9/acl9
https://github.com/ryanb/cancan
This is strictly speaking out of my personal experience. I have tried all of the suggested authentication and authorization gems mentioned above, but I always came to the conclusion that its not more or less work to just write it yourself, especially when your requirements a very simple. Consider this:
class ApplicationController < ActionController::Base
before_filter :authentication
def authentication
redirect_to '/authentication_form' unless session[:logged_in]
end
def authentication_form
... render the form
end
def login
if params[:username] == 'adam' && params[:password] == 'eva'
session[:logged_in] = true
redirect_to '/restricted_area'
else
render :action => 'authentication_form'
end
end
end
class RestrictedController < ApplicationController
def index
... this action is now restricted
end
end
This is not complete, of course but it demonstrates how easy authentication can be with rails. Instead of checking users and passwords through controller code, you could query the database like this:
if User.find_by_name_and_password(params[:username], params[:password])
session[:logged_in] = true
...
For authorization you would have to save the users identity within the session hash which allows you to restrict access from within every action (provided the controller is a derived from ApplicationController)
I hope, this helps.
I want a subdomain like... admin.example.com
but I want it to require a user and password. Like... the kind that uses teh browser's interface, rather than a database backed authentication system.
what are some good methods of doing this?
It's fairly simple:
# products_controller.rb
before_filter :authenticate
protected
def authenticate
authenticate_or_request_with_http_basic do |username, password|
username == "foo" && password == "bar"
end
end
See: http://railscasts.com/episodes/82-http-basic-authentication
Write a small rack application. Both checking if its the correct subdomain and enforcing basic auth can be done easily.
I am just starting to learn Ruby on Rails and have a newbie question that I have so far been unable to find the answer for. I have a small app that uses HTTP basic authentication and I have design elements in my view that I only want to display if the request is authenticated. How can I access this information?
You can use the session hash which store data during your session( http://www.tutorialspoint.com/ruby-on-rails/rails-session-cookies.htm) I will recomend using the following tutorial with Http Basic Auth for generating the form: railscasts.com/episodes/21-super-simple-authentication
heres some code you could use
application_controller
helper_method :admin?
def authenticate
authenticate_or_request_with_http_basic do |user_name, password|
session[:user] = "admin" if user_name == 'admin' && password == 'password'
end
end
private
def admin?
session[:user] == "admin"
end