

Server-side authentication using GraphQL + JWT + Ruby on Rails
source link: https://medium.flatstack.com/server-side-authentication-using-graphql-jwt-ruby-on-rails-8820e0471ed4
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.



I want to share with you how I implemented a simple authentication system using GraphQL and JWT in my Ruby on Rails app. This article is intended for those who are already familiar with technologies such as GraphQL and JWT. For beginners, I’ll attach links at the end of the article.
Pre-requirements:
Connect GraphQL to app
By documentation you just should run rails g graphql:install
that will mount our app with GraphQL: it generates GraphQL endpoint, adds app/graphql
folder with some base objects.
Execution error responder
To build an error message if some action will fail I added concern to app/graphql/concerns
folder that uses GraphQL::ExecutionError
class from graphql-ruby gem to raising error messages. This class will add the “errors” key to the response that contains the error message, status, code, and location. I included ExecutionErrorResponder
into BaseMutation
object to use execution_error
method in mutations.


Below I attached an example of a response with error message:

User registration mutation
To add the ability to register user, I created Mutations::RegisterUser
mutation that takes email, password, and password_confirmation as arguments that looks like as:

Method #resolve
takes all available attributes that are described in 3–5 lines (3rd pic.) and then we can modify or sanitize these params if needed. Since mutation returns values via fields, we should describe them in this class like in 7–8 lines (3rd pic.). null: false
in this case, means that the field always contains the value.
But I wanted to refactor this code a little bit and moved field describing in a separate folder named “payloads”:


For implementing registration logic I used organizer from interactor gem (Users::Register.call(user_params: params)
on line 18 in the 4th pic.) that firstly saves new user in the database and then generates JWT for him. I did not use refresh tokens in my case, I am just generating a token that is valid for one day. I will talk about the implementation of the token generation a little later.
To check locally how works registration system I use helpful GUI for editing and testing GraphQL queries and mutations is https://www.electronjs.org/apps/graphiql.

And we receive the next response for the query above:

If registerUser
mutation will be failed, I will receive an error message that generates by ExecutionErrorResponder
in response:

User login mutation
To log in user, I use almost similar logic to registerUser
mutation. But for this case, I permit only required email and password as arguments:

In the organizer (line 17 on 9th pic.), I first try to find existed user and then generate a token for him. Payload data for this mutation are identical to registerUser
:

Authentication implementation
I will not go into detail about how the JWT works, as there are a lot of such articles on the Internet. Here I just wanted to show how use GraphQL with JWT technology. As I wrote earlier, I generate a token for each case when a user logs in or signs up. I use common interactor that responsible for this action. You can also use another algorithm for cryptographic signing or add some payload data.

When we have generated token for the user we should authenticate him for each request. To realize this action I wrote some decoder that receives user ID from the token that will be placed in the request header. I wrapped this logic into controller’ concerns:

GraphQL provides the ability to pass some specific values for the request using context. In my case, to share current_user
with GraphQL mutations I used this feature. I just pass current_user
in GraphqlController
like as:

But that is not all. We also should implement authentication logic on the GraphQL side. I used #ready?
method for this that was provided by gem. It allows checking current_user
existence before running mutations. I also wrapped this logic into concerns to simply include in each mutation:

The method #ready?
will be run before #resolve
and if current_user
will be nil method will raise an unauthorized error. For example, I tried to create a company as an unauthorized user:

And then an error message:

That’s all it takes to easily implement an authentication system using JWT and GraphQL in Ruby on Rails apps. I will be happy to answer your questions.
Useful links:
https://en.wikipedia.org/wiki/JSON_Web_Token
https://github.com/jwt/ruby-jwt
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK