06 September 2020
In the previous section, we talked about how to adjust CORS settings for API-only rails applications. This week, we will introduce doorkeeper gem that makes it easy to get the OAuth 2 provider functionality.
Oauth is an authorization specification that is widely used in web applications. Programming languages have different libraries that implement the OAuth 2.0 specification and provide an abstraction to use without knowing all the implementation details. We will use the
doorkeeper gem for the bookmarker application.
To understand how OAuth works and how we’re going to use it, you need to read the blog post from Alex Bilbie. Keep in mind that we will use the
resource owner credentials grant in the
bookmarker application and make sure you understand this part before continue to read the chapter. As a difference from the blog post explanation, we will not have a specific trusted client application since we will not serve to any other external client.
Let’s start with adding
doorkeeper gem to
Gemfile and run
bundle install command.
Then we need to execute the following commands to install the
doorkeeper gem and generate corresponding migration files. (Do not forget to run
rubocop --auto-correct for generated files.)
Let’s do step by step what the
doorkeeper gem suggests to complete integration. First, we need to modify the doorkeeper initializer file to have
resource_owner_from_credentials (also called password) grant.
activerecordas an ORM.
resource_owner_authenticatorcode block since we will use
resource_owner_from_credentialsgrant. Inside the block, we called the
authenticateclass method on the
Usermodel to authenticate our users. (We will implement the authenticate method later in the chapter.)
api_onlyflag because it will skip all views management and change how the doorkeeper responds to requests.
I would also like to introduce oauth scopes when we build premium accounts for the bookmarker app, but we don’t need it until then since there will be only one type of user.
As a second step, we will run the migration generator for the
Before running the migration that is created by the doorkeeper, I would like to remove
oauth_access_grants tables from the migration and also their corresponding foreign keys and indexes. We delete them because we will not expose our API to the external clients as I mentioned above, and therefore we don’t need to differentiate which application we’re using. (If you would like to publish your API to external developers and ask them to generate their oauth applications to use your API, then you need to keep those tables.)
Apart from removing those tables, we need to remove
null: false constraint from application reference because of the reason we just mentioned. We also don’t need to create foreign key for
application_id column in
oauth_applications tables. So applying those changes, the migration should look like this:
Then we can run the
rails db:migrate command to create
oauth_access_tokens table in our database.
You need to run
rubocop --auto-correct again to fix rubocop offenses that are caused by the
doorkeeper migration file. It’s also better to exclude
db/migrations folder and
db/schema.rb file from rubocop rules since they are not going to be the places that we heavily write ruby code. Besides that, it’s better to be pragmatic here not to solve all the offenses from external party migrations and generated schema code.
Apart from the previous configurations, since we will not use applications and authorization flows from the doorkeeper, it’s better to disable them on the routes.
In the first step of doorkeeper suggestions, we mentioned that we would use the
authenticate method from the
User model to authenticate our users. Let’s create an authenticate method in the
User model and use it from the doorkeeper to find authenticated resources. Add authenticate method to
app/models/users.rb file as the following.
We’re basically using find_for_authentication method from
devise to authenticate user. If we can’t authenticate the user, we’re returning
We can now send a request to get an OAuth token for the user that we created with the user creation endpoint.
And the response should be like this one:
(I suggested to have the generic structure for API payloads in make API payloads generic chapter, but I would like to break this rule for doorkeeper related endpoints. We can have the same structure, but I don’t think it’s worth to do so many workarounds without getting a huge benefit.)
Now we completed the functionality of the token creation endpoint. We can continue by documenting it with the swagger. Let’s create
Let’s add those three classes into the
ApidocsController class since we generate swagger documentation from this file.
If you enter to the http:/localhost:3000/swagger you should see the
api/v1/oauth/token endpoint documentation.
And as the last step, we need to write a test for the
authenticate method on the
Let’s run all the tests again to see everything is still working as expected as well as new changes.
UPDATE: Added one more commit after publishing the chapter to fix
OauthTokenController class and file names for swagger documentation. Make sure you also get those changes here.
This chapter, we integrated the OAuth 2.0 authorization framework into the
bookmarker application by using the
doorkeeper gem. From now on, the clients can request a new access token whenever they want to log any user in. We also provided swagger documentation for
api/v1/oauth/token endpoint. You can find the source code of bookmarker application on github. You can also find the previous chapter here.
Thank you for reading! If you want to be notified when I publish a new chapter, you can follow me on twitter.