Simple authentication in Sinatra with Janrain Engage
Everybody knows Sinatra and I'm sure that almost everybody has played with it. The simplicity of creating an app is just awesome. Unfortunately, as soon as the app gets a bit more complicated, and you need a more sophisticated feature - say authentication - you can't rely on all the nice plugins available for Rails (eg. devise or authlogic). So you end up either writing something yourself, or using an external solution.
So, inspired by this blog post we ended up with a fully functional (and good looking) authentication solution with minimal effort (check out the full source).
Setup
Sign up for Janrain Engage first and walk through the wizard that sets up your account. Fortunately the basic version is free (and that's all you really need for an in-house app). The only thing at this point that links Engage to your app, is the token URL you have to specify in the wizard. We skip over all the other configuration options here, because they aren't necessary to make the sign-in work.
Authentication in less than 30 lines of ruby code
In our code, we need an endpoint for Engage. This should (of course) map to the token URL specified before, so with
eg. http://example.com/signed-in you should end up with something like:
post "/signed-in" do
if authenticate(params[:token])
redirect "/"
else
redirect "/sign-in"
end
end
Now to the interesting part, the authenticate helper:
def authenticate(token)
response = JSON.parse(
RestClient.post("https://rpxnow.com/api/v2/auth_info",
:token => token,
:apiKey => "[your api key]",
:format => "json",
:extended => "true"
)
)
if response["stat"] == "ok"
session["user"] = response["profile"]["identifier"]
return true
end
return false
end
We pass in the received token and use the beautiful rest client gem to authenticate the user with Engage. The result is a (across all providers) standardised JSON response. In our case, we just store the identifier in the session and the user is authenticated! Now, to make our life easier, we add a couple more helper methods:
helpers do
def logged_in?
!!current_user
end
def current_user
User.first :identifier => session["user"]
end
end
The end result

