RailsCasts Pro episodes are now free!

Learn more or hide this

Recent Comments

Avatar

Ryan,

thanks for the cast. I'm wondering why you used a flash message to alert the user of login failure, instead of using an error on the user model.

thanks,
Ian

Avatar

@Piotr Kurek

you could do something like this in the application controller.

  protected
  
  def logged_in?
    unless session[:user_id]
      flash[:notice] = "You need to log in first."
      redirect_to some_path
      return false
    else
      return true
    end
  end

and then add a:

before_filter :logged_in?

to the controllers you want to protect.

PS: Nice screencast, congrats on 250th episode and +1 to a screencat on "account verification via email, password resetting, and a "remember me" option and others!"

Avatar

Well, if you store all three data (eg. hash, salt, and cost), you can update users' password on the fly to increase cost of older encrypted passwords... at successful login:

class User
  DEFAULT_COST = 15

  def self.authenticate(email, password)
    user = where(:email => email).first
    if user
      pw = BCrypt::Password.new(user.password_hash)
      if pw == password
        if pw.cost < DEFAULT_COST
          user.password = password
          user.save
        end
        user
      else
        nil
      end
    else
      nil
    end
  end
  ...
end

Avatar

Question u changed the login so you can use username can you do something like config.authentication_keys = [ :username, :email ]
so that you could enter username or email into the box?

Avatar

As an additional note, by using BCrypt::Password you also store the cost of the BCrypt hash in the string. This allows you to easily upgrade the cost as computing power advances. New users will get the newer cost, old users will keep the older cost (until they update their password). You could also give admins a higher cost hash, whilst keeping the same authenticate function.

Avatar

I would recommend using the interface bcrypt-ruby provides, instead of storing salts on your own. It stores the whole password + hash and host in a 60 character string. See the gist for rewritten encrypt and authenticate functions.

https://gist.github.com/799333

Avatar

http://pastie.org/1501829

I added this to my application controller but it doesnt redirect if I'm not logged in

Avatar

@Brian J. Cardiff #48
Try add ":subdomain => false" in you'r routes.rb for lines in which you want to use default subdomain.

Avatar

Great. This reassures me that my authentication layer is done correctly. Thanks for the tip with using "password.present?" I was just using "password" before.

Cheers

Avatar

Hi Ryan,

This example is not working in Rails3. At least for me.

The problem is that response is ActionDispatch object (code 200OK) the first time a route is accessed, and an empty array[] (code 304) for all requests.

Can you update this for Rails3 and explain this change a little further?

Respect!

Avatar

Great videos!

I have a question on Devise. In this video, it seems that we created our base use model from what devise wanted.

I have another model, skills, that i want to do a many to many through association with the user model.

i have two concerns:

1) i'm using a third party user model (devise) and don't want to edit it significantly for fear that it may lock me into big changes later on.

2) i want to create a set of checkboxes like in your habtm videos, but i'm not sure if i should use the devise based model or create it through the skills controller. i'm editing a user's skills so i'm a little confused on how to do it. any thoughts?

thanks!

Avatar

@Rorsvort

Thanks for the Gist. This was the only solution I could find that solved all the problems with the cropper.rb.

Avatar

Hi Ryan-

Question for you that I couldn't find anywhere else. What if we are using "member" instead of "user"? Is there a way to configure that? I am, getting an error when my ability.rb and devise are configured around "member"

Thanks

Tommy

Avatar

Yeah, don't forget to restart the server. Caused me anxiety at first.

Avatar

Although there is some benefit in using bcrypt vs the traditional sha1 (actually the only one I can see is a much more cpu power required to generate each hash/password), I would still stick to sha1 when rolling out my own authentication solution. At least that's what I did in my simply_authenticate Rails plugin:

https://github.com/pjg/simply_authenticate/

(btw. there is some utf8 related problem with getting my username from github).

Avatar

Hey Ryan, Thanks for your work!
One question, how do you manage validation off-line?
If the model is a little more complex that one column. it could be a nightmare no?

Avatar

Great screencast, but half of my views are rendered in pdf, I don't know why? I set config.middleware.use PDFKit::Middleware, {}, :only => %r[^/invoices/show] in application.rb

Please help.

Avatar

Ryan, is there any need to flush passwords after save? I usually do something like this in my model:

after_save :flush_passwords
private
def flush_passwords
  @password = @password_confirmation = nil
end

Needless or important?

Avatar

As it happens, I was wrapping up simple username/password authentication into a gem when this RailsCast came out:

https://github.com/airblade/quo_vadis

Avatar

Hi Ryan,

Just checking this cool gem. One question though... In case of a CanCan::AccessDenied, how can I redirect to the previous page instead of root?

I tried:

https://gist.github.com/794752

That doesn't work.

Thanks

Avatar

Hi Ryan,

I'm a bit off topic here, but where can I get the Textmate snippets you continuously use?

Thanks

Avatar

@Ryan BCrypt actually handles the salting for you automatically, so there is no need to store the sale separately.

Also, DHH is adding has_secure_password to rails which does all the password stuff for you using BCrypt. See:
https://github.com/rails/rails/commit/bd9dc4ff23ab1e185df6ccf35d6058c0a3d234ce

Avatar

Thanks for the great screencast (all of them)!
I agree with the others about having a
followup screencast on authentication.
In particular it would be nice to see
how to replace Authlogic's feature of
using "?user_credentials=xxxxx" for
API requests.

Avatar

@Ricky You can add a before_filter to your controller and have a method which may redirect a user if they're not logged in. That's how a lot of authentication solutions work.

Avatar

I'm a rails noob so pardon me if this is obvious, but the one thing I see missing here is how you mark a page as needing to be authenticated.

Avatar

I exactly do the same for my apps...this cast was an assurance that I am doing right.

Avatar

I agree with other users, It'd be great to see a second part to this episode that covers account verification via email, password resetting, and a "remember me" option and others!

Avatar

Another great episode! Thanks Ryan, this makes much more sense for simple auth than requiring an engine.

Avatar

Excellent timing! I just started working on an application that needed a simple/homemade authentication system. Keep up the great work! I probably wouldn't be a ruby on rails programmer without Railscasts!

Avatar

How print all events without year create? For example: i have many events in one day but another years, how to display it?

Avatar

AFAIK, bcrypt hash has unique salt in it, which means that we don't need password_salt field.

Check out http://pastie.org/private/eqhgo4trb3owrsefupmxgg

Avatar

An excellent 250th episode, congrats.

Got to say, while I've used devise without too many problems I do feel like you Jimmy, that something this important shouldn't be reliant on a third party library. Especially since authentication libraries seem to go in and out of favour all the time!

Avatar

Also congrats on #250.

I would really like to see your take on unit testing this piece of functionality.

Avatar

I'm agree with Jimmy.. Hope to see a second episode with the other features!!

Avatar

Quite nice, indeed! I also prefer doing authentication myself. I ended up using devise though, as it takes care of a lot of details, like validation and has a lot of useful modules - also for OmniAuth.

Avatar

Considering how Authlogic has gone the way of the dodo, I wish I had just done this in the first place with my apps. The fewer external dependencies you have, especially for something this important, the better off you are in the long run.

It'd be great to see a second part to this episode that covers a few less essential but common features like account verification via email, password resetting, and a "remember me" option.

Congrats on episode #250! Keep it up. :D

Avatar

Great cast! Really helpful to see what's going on under the hood.

Avatar

@Amr, yes, CanCan will work with any authentication solution. It just relies on a current_user method, which even then you can customize.

@alex, thanks. I expect to.

Avatar

Congratulations on making #250!

Now keep it up for another 250. :)

Avatar

Thats what am talking about! I'm thinking of dropping Devise and any other auth engine from my projects and make my own auth system!

And CanCan will work normally as expected, right?

Thanks Ryan!

Avatar

@136, I am getting error with formatted_categories_path

Avatar

Ryan, thanks for the Railscast. As always, very helpful. Two quick questions:

#1) Will uid:string provide enough space for Facebook user ids?

#2) Would it be correct to say that string was chosen in order support a wide range of different id specifications, against a more efficient (but provider-limited) int or bigint?

Avatar

Oh my god this episode is splendid.
Previously I've been thinking, wow diving into the source code of rails would only be guru's things to do. But now by following your direction I finally appreciated and learnt the way to look inside source codes. Thank you Ryan.

Avatar

It seems Paperclip doesn't save file name on sumbit, when there are some errors raised in form. Can it be handled somehow?

Thank you

Avatar

great job as usual, ryan but please, stop doing casts for rails 3.

- not many use it yet
- it's not stable (things break here and there) and we dont want to waste development time on something that's 3/4 baked.
- please continue to support rails 2.3.5+

thank you, ryan! :)

Avatar

I am also interested in your opinion on a suitable mechanism to implement a model focused pub/sub system for simple events.

I am currently using Observers and custom events (ActiveModel::Observing#notify_observers) but the simplicity of this approach and the RegExp matching capability seems to be a better approach to me.
Since I am only interested in my custom events the Observers are pretty much overkill and the presented method would work quite well. Do you see any other major drawbacks than scattering the code (because I need to extract some core business logic into external places)

Avatar

Thanks for the screencast, Ryan.

Holding this logic in an initializer seems odd. I'm going to assume you could place that block almost anywhere else.

I have seen a presentation on Domain Driven Design with Rails by Pat Maddox where he plays around with the notion of generating and consuming events as a means to decouple concerns. Makes me wonder if you might do it with these. I know you advise against this, but am wondering how that would feel.

Of course, with the above, you have to consider how it would be tested.

Avatar

Warning: link_to method is NOT safe because its not properly encoding all characters into percent-encoding (skipping slash)

In your video if you click on the link with "...</strong>" text your application woulnt probably work because the slash in this string would brake your routing rules.

Actually this is not an XSS safety but an attacker could provide a string that would break the app from working (broken links).

I have no idea why link_to encodes only few characters and not all according to the specs.

Avatar

Cool! Many many thanks.
Do you think that notifications could be suitable for pub/sub like jcoglan faye for nodejs and rack does?