Rails API and Facebook login (featuring Doorkeeper and OAuth 2 authorization).
When it comes to add Facebook login to Rails application there’re tons of guides and examples how to do it using Devise and Omniauth gems. That works well when you need to make it work with “classic” Rails application. But if you have Rails API application that powers your iOS/Android application it’s a bit different story.
Note: This post is only about backend part and it assumes that you know how to obtain Facebook access token (it’s described in this doc).
So that’s what we have:
- Rails API application with protected endpoints that are accessible only by authenticated users (authenticated through Facebook).
- iOS/Android client that does Facebook authentication and provides us users’s Facebook access token.
We gonna use Doorkeeper gem to add OAuth 2 authorization support for our Rails API. By default Doorkeeper supports all common grants like
Implicit grant, etc. But it doesn't work for us. All that we’re going to get from mobile clients is users's access token from Facebook. Here comes the
Assertion grant. Since it's not supported by Doorkeeper by default we need to use this
doorkeeper-grants_assertion extension. That's how the flow works:
where Relying Party is our Rails API, Client is iOS/Android app, Token Service is Facebook.
Let’s configure Doorkeeper to support that flow. That’s how your config/initializers/doorkeeper.rb might look:
Yeah, that simple.
Authentication::Facebook class is just a simple service that fetches the user information using Facebook's access token and tries to create a new user or return existing one based on user's Facebook id. It might look like this:
That’s basically it. Finally, you can test that everything works by making a request to our Rails API:
OAUTH_CLIENT_ID is your id of Doorkeeper's OAuth Application (you can read more about it here),
YOUR_FACEBOOK_ACCESS_TOKEN is your Facebook access token (just to test, you can generate it in Facebook's Graph API Explorer). After running that request you'll get something like:
That’s all! Here’s the
access_token you can use to do authorized requests to your endpoints!