Strapi – GraphQL Authenticated CRUD Operations
Strapi GraphQL series is back! In the previous post related to Strapi and GraphQL, in a project named id-card-repository
I did CRUD operations without being authenticated which is dangerous enough as it enables all users (public users) to modify data.
Today, I would like to implement authentication and authorization so only authenticated users can conduct CRUD operations. However, this article may not cover Media (Image) data type.
— Continuing development using Strapi —
First, open Command Line Interface (CLI) and change the directory to the id-card-repository folder by typing :
$ cd id-card-repository
Run Strapi application using yarn :
$ yarn develop
Note :If you use npm :$ npm run develop |
Next, type localhost:1337 in any browser’s address bar, then you will be redirected to the strapi login page. Fill in your username and password to login. Dashboard page is seen immediately if login is successful.
Great, we can continue to the next step then.
— Creating a new User —
I will set public roles to be able create a new user.
Here we insert mutation to create new users named marc and paulo, respectively :
Now we have two users.
— Authorization —
According to Boston University :
” Authorization is a process by which a server determines if the client has permission to use a resource or access a file. “
Eventually I will change the authorization to only allow authenticated roles to create new users and forbid public roles to create a new user.
Previously, I have set public roles to be able to run CRUD operations. This is strongly not recommended so in Roles & Permission tab on the left side of the page, I will change authorization to public roles and authenticated roles as shown below :
Public role (not allowed at all) :
Authenticated role :
- count
- find
- findOne
- create
- update (I will change this later)
- delete (I will change this later)
Now, if I send a request without logging in, I am considered as a public user.
The result …. of course failed.
— Authentication —
According to SearchSecurity, authentication is the process of determining whether someone or something is, in fact, who or what it declares itself to be. Login refers to the authentication process.
Here is an example of authentication using mutation in GraphQL :
login using username
login using email
As you see, I got a JSON Web Token (JWT) which is used to authenticate a user. So, if I want to do CRUD operations, I have to send the jwt within a request. In brief, a jwt is used to prove that the user is authenticated.
Another example of login (without provider) :
Login without provider
Of course we do not have to include the provider but if we do so, the provider is set to local.
“ How do we send the jwt ? “
Well, we can send a jwt in the http header or using a browser extension called ModHeader, as stated in Strapi GraphQL plugin documentation.
Http Headers in GraphQL Playground
A tip from GraphQL Plugin documentation to install ModHeader
ModHeader is a browser extension whose main function is to modify headers.
You can add the ModHeader extension on Microsoft Edge, Opera Browser, Mozilla Firefox, and Google Chrome.
To send a jwt using ModHeader, the format is :
Bearer <jwt>
Bearer is set to prefix as we are going to use a bearer json web token(jwt).
— Create —
First, I am going to login to get a jwt. This login process has different queries but it does not matter if you use the query in the login section above.
Great! We got a jwt in the response.
=> Using Http Headers
Eventually, I am going to copy and paste the jwt in the Http Header.
=> Using ModeHeader Extension
Next, I am going to copy and paste the jwt in the ModHeader.
As you see, setting ‘Bearer’ as a prefix is a must. One more vital thing, do not forget to mark the checklist box. Otherwise your jwt will not be sent.
I am going to create a new entry as below :
BOOM! We have successfully created a new entry! Even Though I did not include all fields, you can update it later.
Before checking the Strapi dashboard, if you use the ModHeader extension, do not forget to uncheck the Request Header in the ModHeader extension. Otherwise an error will occur as we are sending the jwt everytime our browser refreshes.
Now let’s check on the dashboard to confirm.
There it is. You can see an entry with the Name field as ‘Luis Hernandez’. This is good.
— Read —
Basically authenticated and unauthenticated requests have the same queries. The only thing which distinguishes them are the jwt.
[ Fetching All Records ]
=> Using Http Headers
I am going to copy and paste the jwt to Http Headers.
=> Using ModHeader Extension
I will copy and paste the jwt to the ModHeader extension.
Then I will send the request :
Tada! We successfully fetched all records!
[ Fetching A Single Record ]
I need the id of the entry that I want to retrieve. So, I am going to copy and paste the id.
=> Using Http Headers
I am going to copy and paste the jwt to Http Headers.
=> Using ModHeader Extension
Just like using Http Headers, first, copy and paste the jwt.
Here is the query :
Good, we got another one!
— Update —
Actually this action is forbidden and I will change the permission later so users with Authenticated and Public roles can no longer update any records.
“ As of July 2020, Luis Hernandez has been promoted as a Chief Executive Officer in a global e-commerce company. His data also has been extracted recently.“
Now we have to update the occupation of Luis Hernandez, and also the extractedAt field at his record.
To update an entry, we need an ID, so like the previous one, I am going to take the ID from a record with the Name field as ‘Luis Hernandez’.
=> Using Http Headers
I am going to copy and paste the jwt to Http Headers.
=> Using ModHeader Extension
Next, input the jwt within the query :
Here is the query to update :
Great! No errors.
Uncheck the ModHeader checkbox, only if you use the ModHeader extension, then let’s check the dashboard.
There you go, the Occupation field was successfully updated.
— Delete —
Just like update action, actually this action is forbidden and I will change the permission later so users with Authenticated and Public roles can no longer delete any records.
“ Steven is a genius software engineer at Facebook but he also makes a load of money from his YouTube Channel. He was called by the Human Resource Department and was told that he has been fired as of today….”
Feeling sad but deleting Steven is our task now.
First, of course I am going to fetch the id of Steven.
=> Using Http Headers
I am going to copy and paste the jwt to Http Headers.
=> Using ModHeader Extension
Copy the id, build the query, and do not forget to check the ‘Request’ checkbox in the ModHeader extension.
Here is the mutation query to remove a record :
Goodbye Steven ~~
To make sure, first, if you use the ModHeader extension, uncheck the ‘Request’ checkbox in ModHeader extension then have a look at the dashboard.
He is not there anymore. OK, good.
Last but not least, I will change the permission on the Authenticated role, so users with this role can no longer update or delete a record.
So that’s all for today’s article and please feel free to leave a comment or suggestions:)
Thank you very much for reading, have a good day!
References
- Boston University. Understanding Authentication, Authorization, and Encryption. Available at : https://www.bu.edu/tech/about/security-resources/bestpractice/auth/.
- Search Security. Authentication. May 2018. Available at : https://searchsecurity.techtarget.com/definition/authentication.