In this video, I will show how to authenticate
a React frontend with a Spring Boot / Spring Security backend. With the JWT and the roles. I've
already done a video about authenticating a React frontend with a Spring Boot backend with the JWT.
Today, I will only modify the previous application to implement the roles. Okay, with the JWT I'm
able to access the backend. But I can't allow a single user access all the data in my Spring Boot
application. I have a website which selles farts from celebrities. I will have users who can buy
farts. Other users who can sell farts. And other users who can administrate the site. To split this
behavior, I have two things to do. In the backend, I must protect the buyer endpoint to be only
accessible by the buyers. Same for the sellers and same for the admins. But the frontend also
needs to know to whom the JWT belongs to display an adequate interface. So I will store inside the
JWT the roles information. Then, the frontend must be able to decrypt the JWT and read the roles
information. This way, the frontend can display a different interface depending on the role. As
said, I've already done a video about creating the JWT and configuring Spring Security. Today, I will
only apply the roles configuration. But first, click on the subscribe button. The roles are
restricted in the controller with the following annotations. I go to my controller. Controllers.
Fart controller. And here I add the annotations. preauthorize has Authority user. Celebrity and admin. But to use those annotations, I need to add a configuration of Spring
Security. So I go to the Spring Security configuration. And add another annotation. Enable
method security. With this annotation, I have now access to a lot of method level annotations.
With the annotation enable method security, I can use the following annotations in my endpoint
or anywhere else. Inside those annotations, I can use an SPEL expression. A Spring expression
language. This give me access to plenty of methods like this. This one permits all the requests
under any circumstances. And this one denies all the requests. Those check the authorities
present in the user authentication bean. Those are the same but the authorities must be prefixed
by ROLE. And this one is for more fine grain authorities. When using the permissions. The
permissions are a level under the roles. And I may want to protect my endpoints by permissions
instead of roles. So let's create a new field in the users's entity with the roles. And add
the roles in the user authentication bean. I start creating the enum with all the roles.
I create a new package enums. And I create an enum Roles. With the roles admin, celebrity and
user. Let's now add the attribute of the role to the user object. I go to the entities. Here
is my user. And I add a new field private role. Role. I specify it's a column. Nullable false.
And indicate it's an enum. Enumerated value, enum type string. This way, in the database,
I only store the name of the role, the name of the enum, not the integer value. Let's go to the
DTO to also add this field. DTO user. And I add the role at the last position. When creating
a user I want it to be by default a user. So I go to the service and in the register method,
where the user is created, I add user set role. Role user. I have a new field role, in the users
object I have my endpoint protected by a method. I need now to add the role in the authentication
bean when validating the request. Let's go to the config package and open the user authentication
provider. In the validate token, I create the user password authentication token bean. But here
I set empty to the authorizations. Now it's time to use the roles. I create an array list with the
user role. Get role. But the values in this input parameter must Implement Granted Authority.
So let's go to the enum to implement Granted Authority. Implement Granted Authority. And it returns the name of the enum.
Which will be admin, celebrity or user. My backend is ready now. But I said at the beginning I want
my frontend to be aware when the user is an admin, a celebrity or a regular user. So I need to
store the role inside the JWT. Back to the user authentication provider. Now I go to the create
token method. Here, when creating the token, I add a new claim with the name role and the value user
get role name. And now, let's go to the frontend to read the role information inside the JWT. To
decrypt the JWT, I need a library. npm install JWT decode. Now, I will create an object
which reflects the custom fields of my JWT with my custom claim. Go to the source folder, and create a directory entity.
With a new file custom JWT payload TSX. Export interface custom JWT payload. Which
extends the JWT payload. The JWT payload is the default object returned when I decode a JWT. And
here I add a new field role which is a string. And now I add the import of JWT payload.
import JWT payload from JWT decode. Now, when rendering the main component, I load
the adequate message depending on the role. Go to the app component and here I only have two
components, the login when I'm not authenticated, and the farts when I'm authenticated. Let's now
modify this. I start by importing the JWT decode dependency. Import JWT decode from JWT decode.
And in the use effect, when it's authenticated, I try to decode the JWT. Decode into my new created
interface. Custom JWT payload. The token decoded. Let's import this. Import custom JWT payload
from entity custom JWT payload. I create a new variable, const role, set role, use State user by
default. And on decoded, I set the role decoded. Role. And when rendering, I display the login if
I'm not authenticated, if I'm authenticated and the role is user I display Fart, if it's admin,
celebrity and display admin farts or celebrity farts. Let's add the imports. And let's test all
together. Here is the login page when I have no authenticated user.
I try first with an admin user. Admin admin. And here is the admin
interface. if I go to the console, remove the JWT from the local storage, this
way I simulate a log out. I refresh the page, and now I will log in with a regular user.
Sergio sergio. And now here is the users interface. Let's make a quick recap. I've added
the enable method security annotation. I've added the annotation pre-authorized to protect my
endpoints. When creating the authentication bean, I've added the authority from the role of
my user. The role enum must implement the Granted Authority interface. I've also added
a custom claim in my JWT. On the frontend, I've added a new dependency, JWT Decode. Once
the user logged, I decode the JWT to read the role value and display the adequate interface.
That's all for this video. I hope you liked it. Don't forget to click on the like button.
Subscribe to my channel. And see you soon. Bye!