Looking for some true Authentication Authorization recipes or hidden knowledge. Oh soothsayers of Ruby

503 views
Skip to first unread message

tripdragon

unread,
Sep 4, 2010, 8:44:39 PM9/4/10
to sinatrarb

----- Sinatra, the singing voice is rich -------

Hi folks. In my 3 day search on learning Sinatra I have now run into
what seems a black art in Sinatra. Admin Views.

For records and tags for the future searchers of this skill.
Authentication Authorization Administration. The Darkness of security,
or " HOW The FU%K do I secure my clients web site!

I ran into the following active gems on git { sinatra-authentication,
chowder, sinatra-warden, padrino, Sinatra-Authlogic-Template, Monk }
As well as the Sinatra http://www.sinatrarb.com/extensions.html
documents for rack based auth

Currently my bare bones test code for viewing. I will update it
instead of reposting as I gather something that resembles the story
below.
http://tripdragon.tumblr.com/post/1064806746/sinatra-admin-tests




----- Ignorance The Bliss of spending days in Google.....-------

The issue I am having is just my ignorance thus far in the way things
work. Some of the gems above provide a user registration setup, and
then some require kitchen sinks to run. While another gets things off
the ground I think until I check my database to find that the password
is not hashed or salted or whatever type of security tools are used.
Then the new issue arises. How do I shut off the method and or routes
to allow anyone to signup?!


What I and I am sure several others wrestle with learning is easy to
illustrate in a user case story.

The admin publishes the site to the server. Once the app is ready to
start a default Admin user and view is created with a top of the line
secure password system.
In the new admin view only is your normal assortment of admin
goodness. But most of all a new form view for creating new users with
whatever Roles based permissions you want to create or use from a
gem.

Now that sounds like a generator instead just like Padrino does. So
that's to much at this moment. Simplify in order. Create admin user.
Disable signup ability to guest viewers. Create admin password
protected route. Put in route the user signup feature to later create
roles down the line.




----- Secure. Did you lock your keys in the car? Got a Tennis Ball?
-------

What seems confusing currently: Is the method of HTTP authentication
storing the password in the code secure? http://www.sinatrarb.com/faq.html#auth
What is a standard way of creating a proper Admin User Model. Signup
form? Database call in code? Console hacking?
Can a guest viewer of the sight do things in the url or curl to say
the /signup/ route to register a user account?

Sorry if I seem to oblivious to this and that. It's been awhile from
when I coded in pure Ruby. Rails spoiled me in the past and I want to
remedy that with true knowledge of how things work. I'm fine with
using someones well crafted gems in the future but I need to know the
underling mechanics before I just read some quick how to.



Jonathan Stott

unread,
Sep 5, 2010, 11:03:09 AM9/5/10
to sina...@googlegroups.com
Hi

A lot of the questions you're asking are very application specific.
What constitutes secure is ultimately only something you can answer,
and on an application by application basis. That being said, I'll try
to talk through some of the answers and questions you might want to
consider asking.

First, storing username and password in the code is fine. As long as
no-one untrusted has access to the code. And it has scalability
issues if you want more than one admin. And it requires a code edit
and a reboot to change the password. But for all those limitations,
it's as secure as the source code. How secure that is, depends on
things like directory permissions for the deployment, and is way
beyond the scope of sinatra.

But to get beyond this very simple method of authentication, since the
rest of your email suggests you want a richer authentication and
authorisation model. One which supports multiple authenticated users,
with differing permissions through roles. It also seems that the
admin(s) is responsible for signing up new users, rather than the more
usual (for many public facing webapps) 'anyone can sign up'. But all
these are doable, though they might require a certain amount of code
writing by yourself. I'm not aware, off-hand, of a sinatra solution
for role-based authorisation.

So, first, the user model. This should ideally store the password
salted+hashed. Probably using BCrypt (see http://is.gd/eWa11 for some
reasons why this is a good idea). That way, if the application
database (or backup) is compromised, people's passwords arn't spilled
all over for the world to see. As an aside, I believe Padrino by
default stores user passwords in the DB with reversible encryption,
which I don't particularly agree with. I'd much rather get a password
reset email than my original emailed back to me. And it seems a
little unlikely that only a database would get breached, while the
application code stays safe. But, whichever. The ability to email
passwords back, and have admins look at passwords, might be
appropriate for your application.

Next, creating the admin user. This is another one where what is
appropriate is up to you. For some deployments, first account is
admin will work fine. Depending on what other configuration is
possible via the web interface, you might even want to consider
something like an 'install' action, which guides the admin through
setting up their account, and configuring other details about the
site. For others, you might want to create the first user via some
kind of system task, run from the console. I'd suggest against
creating directly from the database console, since if you do you'll
have to manually hash the password, and set whichever other fields are
appropriate.

At that point, it's then mostly up to you to set things up
appropriately with regards to the permissions used to set up accounts.
Many of the prebuilt auth solutions you mentioned have a way of
checking if a/which user is signed in. By checking those credentials
in your 'sign up' action, you can deny guests the right to set up an
account or not, as you please.

I hope my writings on the subject help,
Regards,
Jon

Chris Schneider

unread,
Sep 5, 2010, 2:08:26 PM9/5/10
to sina...@googlegroups.com
I agree with most everything Jonathan wrote, let me try to throw a bit of code behind it. I'm going to use ActiveRecord in the example. Obviously it's not a complete setup. There's no support for creating or editing users, but it's enough to get you moving. Basically the goal is to store the current user in the session, and check against that later.


class MyApp < Sinatra::Base
def login_required!
if session[:user].nil?
redirect '/login'
end
end

# A nice helper to have... returns a User object, or nil
def current_user
if session[:user]
User.find(session[:user])
end
end

get '/admin' do
login_required!
haml :admin
end

# Ask for username/password
get '/login' do
haml :login
end

post '/login' do
user = params[:user]
password = params[:password]

u = User.find(:first, :conditions => {:username => user})
if u.authenticate?(password)
session[:user] = u.id
else
haml :login
end
end

end

class User < ActiveRecord::Base
# fields needed are:
# username
# encrypted_password

def authenticate?(password)
# don't wanna look up how to actually call bcrypt. Also, if you want to be
# super secure, add a per-user salt... like their created_at attribute
self.encrypted_password == bcrypt(password)
end

# Other useful stuff, like changing password:
def password=(password)
self.encrypted_password = bcrypt(password)
end
end

> --
> You received this message because you are subscribed to the Google Groups "sinatrarb" group.
> To post to this group, send email to sina...@googlegroups.com.
> To unsubscribe from this group, send email to sinatrarb+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/sinatrarb?hl=en.
>

Jonathan Stott

unread,
Sep 5, 2010, 2:36:23 PM9/5/10
to sina...@googlegroups.com
Hi

BCrypt actually includes a salt (randomly generated) in the hash which
is stored in the DB. So you don't have to worry about that.

class User < ActiveRecord::Base
# fields needed are:
# username
# encrypted_password

def authenticate?(password)
# bcrypt overrides == for an instance to allow this to work.
BCrypt::Password.new(self.encrypted_password) == password
end

# Other useful stuff, like changing password:
def password=(password)

self.encrypted_password = BCrypt::Password.create(password)
end
end

Just to add the correct BCrypt calls. Thanks for actually putting some code
to the stuff I was talking about :)

Regards
Jon

On 5 September 2010 19:08, Chris Schneider

tripdragon

unread,
Sep 5, 2010, 4:54:15 PM9/5/10
to sinatrarb
Oooooo!!! All of this was the knowledge I had sought. I never want
people to finish things for me. Just share some deep rooted insight to
how things work.
But I will admit it's great when a little bit of code shows up to see
how things actually work.

Thank you Jonathan & Chris I will put this into work shortly and see
if I can break it down into a nice little web page for archiving
searches.

When junior programmers can get to a greater understanding faster we
can get back to the goals and experiments we had envisioned.

davesag

unread,
Sep 9, 2010, 12:44:35 AM9/9/10
to sinatrarb
I come from a Java background but have not been coding for about 4
years for one reason or other. Last week I decided I really needed to
brush up my skills. So I started learning Ruby, and Sinatra, Haml &
Active Record (and yes I also looked at Sequel) on Sunday, last
weekend, (along with Git) and have been building a very simple,
canonical example of user login round-trip as a way of teaching
myself.

I have created a small project in GitHub called Frank, which aims to
be useful to ruby-noobies like myself, looking for a really fast light
well documented solution for the basic user / role functions any user-
aware website needs. It's a testament to the power of Sinatra that I
could go from messing about with git and readme files, to a working
and tested app so fast. I've found the people in the #sinatra channel
in IRC very helpful.

I figure with some good collaborators who know more about all of this
than I do, I'll not only fast-track my own learning curve, but get a
much better ride with it.

The code up there now supports a very simple user with username,
password and email, allows login with username or email, and stores
the password securely using bcrypt. It includes some simple
migrations and a db:seed rake task and it fully unit tested

The project is in GitHub at http://github.com/davesag/Frank

Enjoy

Dave


On Sep 6, 4:08 am, Chris Schneider <ch...@christopher-schneider.com>
wrote:
> > salted+hashed.  Probably using BCrypt (seehttp://is.gd/eWa11for some
> > On 5 September 2010 01:44, tripdragon <colo0l...@gmail.com> wrote:
>
> >> ----- Sinatra, the singing voice is rich -------
>
> >> Hi folks. In my 3 day search on learning Sinatra I have now run into
> >> what seems a black art in Sinatra. Admin Views.
>
> >> For records and tags for the future searchers of this skill.
> >> Authentication Authorization Administration. The Darkness of security,
> >> or " HOW The FU%K do I secure my clients web site!
>
> >> I ran into the following active gems on git { sinatra-authentication,
> >> chowder, sinatra-warden, padrino, Sinatra-Authlogic-Template, Monk }
> >> As well as the Sinatrahttp://www.sinatrarb.com/extensions.html
> >> storing the password in the code secure?http://www.sinatrarb.com/faq.html#auth

Michael Breen

unread,
Sep 9, 2010, 12:29:05 PM9/9/10
to sina...@googlegroups.com
Hi Dave,


The project is in GitHub at http://github.com/davesag/Frank

There's an existing ruby gem named "frank" for building static web sites. This may cause some confusion for the ruby-noobies you're reaching out to.

Best.
Mike

davesag

unread,
Sep 9, 2010, 7:45:08 PM9/9/10
to sinatrarb
Ah yes I see - http://github.com/blahed/frank

I can see that project and mine are trying to achieve parallel but
very different things. I guess the name was a pretty obvious choice
eh. No matter, this won't be a gem as it's not meant to be a finished
lib but a canonical example of Sinatra in use. I'm not sure I can be
bothered changing the name :-)

Cheers

Dave


On Sep 10, 2:29 am, Michael Breen <hard...@gmail.com> wrote:
> Hi Dave,
>
> > The project is in GitHub athttp://github.com/davesag/Frank
Reply all
Reply to author
Forward
0 new messages