Microservices Security Using JWT | Spring Cloud Gateway | JavaTechie

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone welcome to Java techy microservices are more popular nowadays and maximum company following this micro service pattern to build their Enterprise application being a developer if you mention microservice in your resume then you will get the first question from the interviewer how do you handle Security in microservice architecture isn't it so in this tutorial we'll demonstrate how to implement JWT based Security in microservices using spring Cloud Gateway okay all right so before I go next I am assuming that you guys have basic knowledge on microservice architecture with each and every components and you have also knowledge on the Spring Security using JWT if not then this tutorial might not help for you because I am not going to cover other components of microservices here I will only focus on security implementation but don't worry already I have covered this concept and you can find them in my YouTube channel so if you'll search javate key the recent video I have uploaded on Spring Security using JWT and if you go to the Java Tech any playlist you can find something called microservices okay so you should understand this micro service playlist as well as this particular JWT implementation video to grab the security implementation and Gateway concept okay don't worry I'll share the link in video description so that you guys can check that out fine so without any further delay let's get started [Music] so before we directly jump into the implementation let me walk you through what all microservices components we need to design for this flow okay so let's assume we have two microservices Sugi service and restaurant service and they both are communicating with each other okay next we register these two Service as a client in Eureka service registry so that load balancing and service call will be quite easy between the micro Services right also we restricted user to not directly access to the microservices so we have defined API Gateway which will helps to Route the request to corresponding microservices for example if user will pass slash Sugi slash app then Gateway will route that request to the Sugi service similarly if user will pass slash restaurant then Gateway will redirect that request to the restaurant service okay this is what typical microservices flow and I believe every one of this basic understanding if we all are in the same page then let's move to the next step assume that you got a requirement to secure your microservices how will you do that it's very simple right I can write the security implementation in two different Services I can write in the Sugi Services I can also write the security implementation in my restaurant services but what if I have 100 of microservices then writing the same security implementation in each and every microservices is not a good practice rather we do in each and every microservices we can ask someone to do on behalf of us right or we can ask someone to do that then who is that person or who is that component that is API Gateway okay since we understand API Gateway will intercept each and every request coming to my microservices then why can't we ask to the Gateway hey pay Gateway once you receive any request please authenticate that request if it is a valid then please send it to me otherwise give error to the user that makes sense right we can absolutely write our security specific implementation in API Gateway but again this is not a good practice because Gateway is meant for routing the request so let's not combine routing and security logic in one place then how we can segregate it let's follow the best practice and create another microservice who will hold all my security related stuff so let's create another service called authentication Service or you can name it as your identity service and register that as a client in your Eureka next Define few endpoint like register any user generate a JWT token and validate the token using JWT implementation now user before accessing any endpoint first you need to get the token from auth service once user have token then you can happily access any endpoint with that specific token for example let's say user try to access the Sugi app so he given the URL so he sent the request to API Gateway with JWT token what he received from authentication Service okay once API Gateway receive the request first API Gateway will validate whether user pass the token as part of header or not if yes then he will ask authentication Service to validate the token if token is valid or if user is authenticated successfully then Gateway will read app service okay same way if you have 10 Micro Services API Gateway will intercept each and every request and authenticate them before request delegate to the corresponding microservices okay so this is what the typical security implementation in the microservices architecture okay so I hope this workflow is clear for you let's begin with the implementation so as per the workflow we understand we need to create four component two microservices and then one Gateway and one service registry okay so already I created these four component for you and the rest thing we need to do we need to create the authentication Service and we'll demonstrate how each and every request coming to the API Gateway can be integrated to the auth service to authenticate that request okay this is what the steps I will show you but before that I just want to give you the heads up about the two micro Services what I have been created okay so if you go to the intelligent idea you can see I have two application sugiyap restaurant service these two are the micro services and Sugi service registry which is nothing the Eureka service registry and then I have created Sugi Gateway okay so if you go to the Sugi app if you go to the let me open the project of it let's say I will go to the Sugi app controller okay so if You observe here user will give the order ID will check the restaurant service so if You observe here I have created a client class and there I am just doing the rest API call to the restaurant service so I have given the service name because I have registered both my micro service in Eureka service registry okay so from sugiyap the request will goes to the restaurant service through the rest API call so if you go and check in the restaurant service if you go to its controller class let me Zoom this for you let me do this If You observe here this is at the end point we are exposing from the restaurant service and if you will check the service get orders I have hard coded few information you can see here right this is the order ID and this is the corresponding order object similarly I have created one map but you can integrate any DB since I just want to demonstrate the security implementation I have not used any DV in this restaurant service so I have few hard-coded information we'll ask user hey give me the order ID I will give you the order object that's it okay that is what the endpoint I have exposed from restaurant service on the same endpoint is being consumed from the Sugi app okay so these are the two micro services are communicating with each other from Sugi app we are doing the rest call to the restaurant service okay that's it now if you go to the service registry I just Define enable Eureka server and if you go in the resource and check the application.aml I am telling Eureka to register this application as a server okay now if you go to the API Gateway um this is where the main class of fa Gateway and everything we have done in the configuration okay if you open the application.aml file I am telling to API Gateway hey if user is giving URL redirect that request to the Sugi app okay so Gap is nothing my service name what is registered in Eureka okay so you can see here sugiya is my microservice has been registered in the Eureka with this name okay so that is what I have defined here I mean this already explained in my micro service playlist how to play with Gateway just have a look okay so if you release this then delegate request to this particular micro service if your release last restaurant then delegate that request to restaurant microservices okay so if you check the port of each micro service let me show you the Gateway Gateway I have not specified anything so it will run on Port default 8080 okay and if you'll check the Sugi app go to the application.aml file it will run on Port 8081 and restaurant service should run on 8082 let me open the application.aml file yeah it's running on 8082 and my service registry is running on 8761 so all my four Services running on different port I need to access the API Gateway that is what we understand here right if user send request to the API Gateway with Slash Sugi then that request need to redirect to the Sugi service we have not Implement any authentication related stuff I just want to show you the workflow if it is working then we'll start implementing the authentication Service then we'll integrate that in our API Gateway so first let's verify whether application is working or not so first let me go to the restaurant service and I will take some order ID okay let's say this is the order ID my Gateway is running on port 8080 so I should always send request to Gateway then Gateway will redirect the redirect that request to the micro service so what I will do here I will create a new request HTTP request http localhost 8080 I want to hit the Sugi app which is my micro service so I will give the URL Sugi slash give the order ID okay because if You observe I specified Sugi because that is what I have defined in Gateway right if URL is coming with Slash Sugi then only redirect that request to the sugiya then from the sugary sugiya which particular endpoint you want to access go to the sugar application and if you go to the controller I want to access this particular endpoint what argument it is expecting order ID just give it here that's it okay this is where the order ID right now let me send the request I am getting the response order ID is this name is paneer butter masala quantity one price is this order date is this delivered is this okay now if you want to access the restaurant service from the gateway then what URL you need to provide if you go and check in the Gateway we need to provide the this is what the URL right so just go to the postman and change the url to this and access it what is the URL you want to access from the restaurant let me verify go to the controller class okay the URL is different right apart from slash restaurant you need to Divine you need to Define this URL as well okay go to the postman and I will just Define here this order ID I already given here that's it now if you'll send the request first let me remove one additional slash we are getting the response okay now this Sugi service and restaurant service I am trying to access from API Gateway this is working as expected only the things you need to verify how we can integrate authentication part here okay so the first step all our component is ready for running we need to start implementing the authentication Service by defining these three endpoint okay so I'll create a new project file new project click on next specify the group ID com.java techy artifact ID entity service you can name it any name okay you can define auth hyphen service or identity service or Security Service it is up to you I'll change let it be 17 since I have already installed it identity service and name it com.java TK so this particular identity service what I am defining will be the same application what I have done here okay so I will do it quickly because I don't want to eat more time so I'll do it quickly but make sure if you are getting confused just watch this particular video fine now click on next now I'll add the dependency Lambo I will add the dependencies spring web I will also add jpa because I want to store the user information right so I need this JP and MySQL as well MySQL then also I need to register this application as a client in service registry so I need Eureka as well okay Eureka client okay anything I am missing here lumbok with GPA driver Eureka okay so main thing we are missing here I want to make this application to act as a security right so I need to implement this security dependency Spring Security and rest JWT type security JWT dependency will add manually now click on next import this project so project imported successfully now what we need to do we have added the security implementation or dependency we need to add the JWT specific dependency okay so I'll just add it down let me do them have an update then meanwhile I will create couple of packages so I'll create don't suggest this plugin that's fine I'll create a package called entity then I'll create a package Repository then I will create package called service then controller then I'll create config okay fine so next quickly create the entity and repository then we'll Define three different endpoint I mean create a user generate a token using JWT and also validate the token okay first let me create a entity new Java class I'll name it user info or we'll give some valid name we can specify user credential okay and we'll Define few field ID name email and password since this is my entity I need to Define entity and I now need to Define address table I need to Define this as my primary key I need to Define generate value I mean Auto generated value strategy identity let me Zoom this for you fine also I need to define the getter and Setter so I'll use lumbok data I need all argument Constructor I need no argument Constructor that's it now since we have created The Entity repo using the GPA first I need to configure the data source I can configure in my application.properties file okay so let me take this up I don't want to Define any port at this time we'll Define either you can Define here or you can go in the yml file but we will decide it later now we'll quickly create the repository new Java class we'll name it I mean it will be interface we'll name it user credential Repository okay extends it from JP repo now defined T is nothing your user credential class and data type of your primary key which is nothing integer right that's it let me Zoom this this is what my JP repo so he created entity we created repo now I'll create a service new Java class I'll name it authentication Service okay auth service we need to Define other service here then I need to inject the repository here private what is the repository name we have defined user credential Repository inject using Auto add fine now I'll write a method to save the user First Once user is there in my DV then only I can authenticate I can generate the token using that user details and I can authenticate it right so I need to write a method public but or you can return something string save user or add user give the object which is nothing the user credential user credential fine so you can use the Repository dot save this particular object and I will just return some string value return user added to the system fine but if you observe in the user credential what field we have ID name email and password so in authentication Service we are storing the user with string password which is not a recommended way so what we can do we need to define the password encoder so I will create a config class new Java class I'll name it auth config I need to Define at the rate configuration then I need to define the mean of public password encoder there is some class decrypt password encoder okay and I need to Define this at the red bin so one thing you need to understand this is the config class where we can tell the spring boot app what API need to be authenticate or what could be bypassed I will come to that point we need to configure that but let's not get confused at this time so we need this bin okay now I will inject this in my service private password encoder password encoder use Auto add fine now before you save it what you can do credential dot set password take the password encoder dot m code the password get it from the credential and set it okay now this is how the password will be encrypted in DV that's fine now we need to write a method see here if you understand it correctly we need to write a method to register the user then also you need to write the method to get a JWT token and validate that token so for that to generate a token and to validate a token I can write a util class or I can write a service class new Java class I will name it JWT service okay better I will make it small now here you need to write all your logic or you can create a util class origin okay so I'll Define this as a service now here you need to use the library from JWT or you need to write the code since already I tried it many times let me copy paste and I will explain let me paste it here fine okay see here there is no rocket science we have defined the secret of 32 bit this is what you can generate I have already explained in this particular tutorial how you can generate the secret just have a look and I have defined the same then I have defined a method to generate a token this will call the create token method to create a token okay so what it contains as part of the token claims claims is nothing your header payload and signature whatever you are given from the input okay and said subject is nothing your username when the token is issued that timestamp and what is the expiration limit that is what the timestamp and which type of algorithm you are using to encrypt your token this is what the algorithm okay so this is the predefined methods are given by the jwts parser so you can use that and create token and validate token I have different two methods so you can make it boiled you don't want to return anything let's make it void only after validate we don't want to do anything okay so you can do like this fine so if you understand we have defined register method we have defined generate the token method we have defined validate the token method fine so what I'll do I'll go to the service class Earth service I'll write a method here to generate and validate the token so I can use private then I can inject it JWT service or a limit JWT service which makes sense inject using Auto add fine now we'll Define a method public string generate token so this would be T small so to generate the token you need to give username that's it right I can call return JWT service generate token I can give this username let me go to this generate token yeah generate token will internal call the create token that's fine I mean you can keep in a same method but let's follow the proper coding standard now in the auth service I have written this now I will also write another method to validate a token public void validate token give him the token to validate I'll simply call JWT service dot validate token give the token fine I have defined these three method in my auth service or identity service now what next I need to call these three method from my controller class so what I'll do I'll just Define new Java class I'll name it auth controller I'll join this and it turn it here at the rate rest controller then I need to Define request mapping I mean the root URL that is Slash auth I mean you can Define anything okay now we need to inject your service private or service inject using Auto add now the next step you need to call all the three method these are the three method generate the token validate the token and register a user so just go to the intelligent idea Define public string add new user give him the object user credential object or you can name it user okay it's not confused we'll give user as a variable name and we'll call return service Dot save user and give this user object then you need to annotate this at the rate request body and you need to Define here at the rate post mapping you can Define the URL slash register now I'll write another method public will give me the token string get token this is this should be small how we can get the token by giving the username so what I'll do either you can create a new class or you can use the same class to pass the token username I'll use the same class user credential written service dot generate token give the username from this user credential dot get username okay that's it you need to Define this at the rate gate mapping and you can Define token fine next we'll write a method to validate a token so I'll just copy this and we'll just change the name validate token so change the url and you need to pass the token here right string [Music] token so you can pass anyway you can use the request param or you can use the path variable it is up to you I will use the request param okay now you need to call the service dot validate token give the token but it won't return anything just remove it you can return something okay if there is no exception you will get some message token is valid if exception will get the error right I mean if this validate token will having not correct value will get the exception if it is correct then you will get this string as a response back so we have defined these three method since you know we have implemented the Spring Security using the JWT Spring Security by default enable every end point to pass the username and password to access this particular endpoint now if I'll run this application and if I will try hitting the slash register or slash token I will get the error because Spring Security will force me to give the authentication information for each and every endpoint what you have defined I need to bypass those things so what I can do very simple go to your config Define first this is a wave security something enable web security next you need to define the security filter chain okay so I have already explained let me add it so you can Define like this security filter chain this is the spring boot 3.0 changes and here I am telling if request is coming with slash auth slash register or slash Earth slash token or slash Earth slash validate let me verify whether the value is correct or not this is the validate this is the token and this is the register okay go to the config if URL is coming with these three URL then permit all the requests Don't force them to authenticate okay but if I will force it to authenticate no one can able to access this endpoint right so that is the reason I must need to bypass these three call fine now we are all good right we have defined the controller to register any user to get a token and to validate the token now anyone can hit this particular endpoint okay let me show you then we'll understand further so what I'll do I can register this as a Eureka client okay we need to do that otherwise we can comment out the Eureka related stuff and we can test this flow but since this is the application we want to register in a Eureka service registry let's do that what steps you need to follow you need to Define at the rate enable Discovery client right enable Discovery client and next you need to define the where is your Eureka up and running so go to the resource create a file new file application dot oml okay now let me let me Define the application name spring application name this I will register as a identity service next I can Define the record line where is my server is up and running and also I can Define the port let me Define the port server dot port we can Define let's say 9090 or some some different okay 9898 fine now we register this application as a client and we have defined all the three required method we understand in the flow now first let's test it then we will find out the problem and we'll fix it so let me go to the main class I'll just run it If You observe currently we have these three application registered Right restaurant service Gateway now once I started my authentication or identity service and I registered that as a client in few second once the application will be up you can find that service name here so let's verify if it is up and running yeah it's up and running on Port 9898 now go to the browser just refresh this can you see here the identity service is registered as a client in Eureka that's fine that's not our intention to check what we want to do we want to verify this endpoint we'll register some user will generate a token and will validate that okay now first let me hit this endpoint so what is the input we have in user credential ID will be Auto generated name email and password I need to give okay and what is the endpoint URL slash register okay that's fine go to the postman I will hit the I'll search for slash register I mean I tried it before in security example buddy yeah so the URL is what is the URL uh identity service the URL is let me check the console 9898 right just go to the postman nine eight nine eight auth slash register let's say name equal to percent password equal to PWD one Millet equal to basant gmail.com now let me send the request user added to the system meanwhile let me open the database now let me add other user let's says Suraj his password is pwd2 Suraj let me send the request we have added second user now let me another user Rahul his password equal to 3 Rahul gmail.com now so in the request we have added three user right so if you go and verify in the DV close close what is the table name we have created user credential right so I'll just run select star from user credential we have stored three user with encrypted password okay and we are able to access this endpoint because we are bypassing the call in the config class okay now let's validate the or generate the token first so what I'll do I will just call this method to generate the token go here to generate the token I need to pass the username right so I will create another endpoint let me copy this new it should be request of type post then you can try the URL get the token this is of type post so what you need to pass as part of the body only the name right so you can pass the name let's say I will pass the name call I mean this can be a username you can give the proper name of your attribute or you can create a auth request as a detour and you can play with it let's I will give name let's say John send the request what is the problem let me see so if we'll go here okay my bad this should be post mapping and we need to annotate here at the rate request body because you need to pass the body right which is user credential okay so what I'll do I'll create a detail to make it to make it better I'll create a package called dto I'll name it new Java class auth request okay and then I'll Define private string username and private string password so I will go to the entity class and I will just copy paste The annotation of Lambo that's it fine now here I can use the auth request I mean you can give a try with this entity class directly but let's not get confused I'll Define auth request auth request and I can specify here auth request Dot get username okay that's it this is request body post mapping so let me restart this so it started now let's go to the postman change the field username change the field password some some password okay now I want to generate the token by giving this particular field username and password send the request we are getting the token that is correct but do we register this user in our DV know right John is not part of my database then we should not allow every user to get the token then to whom we need to allow only those user who is present in my system okay so we need to authenticate the username and password before giving them the token so that is what one step we need to do here okay so what we can do first we need to inject the authentication manager in the Spring Security private Authentication let me check the class name Authentication manager right authentication manager and you need to Define at the rate auto ad once you define the authentication manager once you inject it you need to create Bean of authentication manager so go to the config class and here you can define a dean of authentication manager so once authentication manager is ready with you what you can do the next step go to your controller class here just call authentication manager hey authentication manager please authenticate the request which type of request new username password authentication token and I am giving you the username auth request dot get username and take the password as well auth request dot get password you take this input username and password authenticate it if you found that user is present in my DB with the correct credential okay then give me the token back so what I can do here I am telling if authenticate this is what the variable I have defined right authenticate dot is authenticated then only give me this token otherwise throw the exception through new some some exception okay runtime or you can Define your custom exception user invalid invalid access fine this is how we have defined now authentication manager need to talk to your DV but authentication manager can directly talk to your DV so he needs someone's help that guy is your user Detail Service so by writing this step won't help for authenticating a user you need to Define your user details class who will connect to your DV okay so what I can do in a authentication config class Define just be enough user Detail Service so let me minimize this public user details service you can see here user Detail Service okay now create your own user Detail Service who will connect to the DV and will give the information to the authentication provider and authentication provider can connect back to the authentication manager so that is how it can authenticate okay so I need to create my own user Detail Service so I'll name it user or a Limit Custom user details service so you need to create this class create this class I want to create inside service right or we can change here only right no okay it's fine here is the option to change the package so but anyway it's fine right I can create in the config and letter we can move it if required so once you create the class it implements from user Detail Service and it will force you to override a method to load the user by username okay now here you can inject your repository private user credential Repository inject using Auto add you can also Define this as a component fine now here what you need to do you have the username with you okay by taking this username go and check in your DV whether you have user object or not if present then return it back okay so we'll do that step what you can do here you can do simply repository dot find by username but before the first let me check what is the field I have defined in my entity class go to the entity where it is I've defined name not username okay so I need to Define find by name and I can pass this username as a field this will return me the optional I am expecting it to return the optional of user credential object from DV now we need to create this method this is where the spring data GP right now once you have this information with you once you get the user object from your DB then we need to return it back but the return type of this method is user details so you need to convert your credential object to user details and then send it back so how we can do that so we will simply create a class by extending from user details and all the credential object will map to that and will return it back okay so what I'll do in the config only I will create a new Java class I'll name it custom user details object then extends it form or implements right because I believe this is the interface yeah implements from user details so again it will force you to override few method override all the method and what all field you want to bind here I want to bind the username and password private string username private string password I don't want to specify any rule at this time so the password is nothing you can also since we have defined the field you can Define The Constructor and you can just map the value so what you can pass here user credential object that is what I am giving I am getting from the DV right so this user credential dot get username user credential dot get password that's it okay and rest everything you can set this as a password this as a username and rest everything make as a true okay everything we have made as a true that's fine then next we can simply map it it's very simple step just go back here you have the credential object give it to this custom user details class what you created and then map it very simple so what you can do just do return okay already you have it so simply return it I mean remove it you have the credential object with you just map that object to the user details class what you created custom user details okay once you map it just check or else because it will return you the optional or else just validate and throw the exception that user not found okay so you can define something like this uh new user not from exception with some message user not found with name the username what you are getting okay you can map here username that's it so we have created our user Detail Service so that authentication manager can connect directly to the user Detail Service for that you need the help from authentication provider so simply just configure the authentication provider here go to the auth config I mean this each and every steps I have explained in the security video just have value I have to Define this as at the red bin then I need to define the authentication provider so let me add it authentication provider I am giving Dao authentication provider and I am giving the who is my usual details and type of password encoder while decrypting and authenticating okay so these are the things you need to configure in your security config in your identity service and you have already defined all the endpoint now we will verify all these three endpoint we have properly implemented the security in our identity service let me restart this if you will find any error then we'll fix it so you don't take much time so you can see here it started on Port 9898 go to the postman so let's let's try getting the token okay I am giving John and password is this now if I'll send the request what I am getting I am getting four not three because this is not the correct user if you check in the output this should throw the user not found exception but then it's fine now we'll try with the valid input let's say I will give basant and the PWD one is my password if I will send the request I am getting the token if I'll slightly do the mistake in my password I won't get any value because while generating the token we are authenticating the user whether the user name and password is correct or not if correct then only give him the token so I am getting the token now now next I can validate the token new it should be request 8989 the URL will be validate question mark I mean I am giving the request form right give the token equal to this send the request I am trying what is there okay let me check the URL okay it is 9898 right so just go here send the request token is valid okay so all the endpoint is working correctly right and if you can understand the flow what we discuss we have defined these three endpoint in authentication Service or identity service that part we are good we are done with our identity service implementation now next user can access that identity service from APA Gateway itself right so what I need to do I need to configure that identity service in API Gateway first how we can do that the way we have configured sugiya and restaurant service in application.aml file similarly I need to register my authentication Service so simply just copy this and just paste it here Define this identity service identity service and you need to give the name same name you need to give what you have specified here copy it okay now paste it here if user is giving slash Earth then delegate that request to the identity service now with this particular configuration user can directly access the identity service from API Gateway see Here If You observe here now we are hitting directly the micro service of identity service to get the token or to validate the token since we registered our microservice in Gateway someone can easily call your identity service from Gateway itself now if I will give eight zero eight zero it should work but we have not restart our application right so we'll verify it right away let's go to the Sugi Gateway we have configured it now let me re-run it it will take few seconds so you can see here it started eight zero eight zero and if we'll refresh it all the four Services is working as expected now user first need to register and you need to get the token from Identity service directly but will not allow user to directly call the identity service then how we can call through the Gateway so for example whatever the URL we we tried it let's try it using the APA Gateway endpoint so first let me register someone okay so I will give your eight zero eight zero I want to call the identity service from API Gateway I'll give somebody let's say Kumar or I'll give Peter password is PSS Peter we are trying to access the identity API from the Gateway since we registered it in the Gateway right we configured it now send the request user added to the system will verifying the DV Peter is added to the system so we send the request to whom APA Gateway APA Gateway redirect that request to the authentication Service okay it didn't validate any token so far that implementation we need to give but before validate the token you need to get it first right so that is the reason I am telling how we can register the user and get the token from APA Gateway now go back here I want to give this username and password to get a token so this is your right post Earth token body username equal to Twitter will equal to pass it should give me the token we are getting the token back now I want to validate that token simply go here and just paste your token so in the request this is wrong because I am hitting the eight nine eight nine eight I need to hit 8080 okay that is how I am communicating through the API Gateway to the corresponding microservice fine so the token is valid we have this particular token which is valid but we don't want to do the steps manually right so whenever the request comes to API Gateway I want API Gateway to do the validate token first you will check whether user pass the token aspect of header or not if user pass it then validate it so how we can do that so we need to implement a filter in API Gateway once request reach to the filter API Gateway will check okay filter please check whether user pass the token or not he passed the token well and good then just do the validate token call to check whatever the token he pass is valid or not if valid don't cry immediately send that request to the corresponding microservice which he want to access that is what the very simple flow will do it right away go to the intelligent idea in the Gateway I need to create a filter okay so I will just create a package here new package name it filter so then quickly create a class called JWT auth filter or you can name it Authentication filter fine once you create this filter let's annotate this at the red component next you need to extend that filter from obstruct Gateway filter Factory given by JWT okay or spring Cloud Gateway so just extends it from obstruct Gateway filter Factory okay and here you need to define the filter class and you need to define a config class that doesn't make any sense but you need to follow these you need to create a class called config so okay I'll create it here public static class config okay now it will force you to override a method that is I mean there are multiple method you can use the first one where it will take the config as a argument fine now since you have the config what you can do you can Define the Constructor and you need to call the super config.class not this the config what you created okay okay this should be simple dot class rate I am doing this mustang fine I've defined the filter and we are doing the super call to the config class then the main thing what what logic you need to write inside this particular method now what logic you need to write so for that make sure you should have the with flux dependency in your project okay you can see here this this particular web flux dependence is required because this abstract Gateway will take the input in the form of wave flux so go here take the argument okay exchange and chain these are the two argument so here we'll write the logic okay where this is giving error okay I'm going to draw the return statement return statement is nothing just doing the call again to the filter chain dot filter give him the exchange that's fine now you need to write your actual logic here inside this particular space so what you want to do here you want to check first it contains the header or not okay if it contains header then you need to do the validate token call that is a simple step you need to perform here but before that first you need to tell for what all endpoint you want to validate these steps right I want to validate only for slash restaurant slash Gateway so for what all endpoint you want to validate that so for that what I can do simple step I will create one validator class new Java class route validator okay then I'll configure those endpoint so simply add this I'll just Define other component I mean this you can remove we don't have the server implementation so no API docs so see the servlet request you need to import this from the reactive if you input it from the server HTTP it will cry add all the record input statement the availability function better I will just do Java util star fine so there is no error I am telling if request is coming with Slash Earth slash register slash auth slash token slash Eureka then ignore it even from API Gateway also bypass these three requests okay because if You observe in the presentation we need user must pass to the Token so if you will force user to validate while getting the token that does not make any sense so will allow him to get the token going forward while trying to any service he must need to pass the token as part of the request header and we will authenticate that token in the API Gateway fine just go to the intelligent idea we have just defined the route validator I need to inject this go to the filter private route validator validator inject using Auto add now here first I will check the request what I am getting if it is not part of that then allow it to do the authentication so how I can do that simple if route what I have defined validator right validator dot is secure DOT test exchange dot get request okay next check here header contents token or not how you can do that you can simply check if Exchange Dot get request dot get headers dot get or what I can say no get headers you need to check right if it contains key authorization we'll see that what is the in Num authorization something like that yeah HTTP header authorization if the header contains this then we'll end good in case if it does not contains then simply throw the error message so I will simply throw new runtime exception you can Define your custom exception okay ah missing authorization header missing authorization header all good fine if it contains then it's fine it will continue the flow now if it contains then get that header so I'll do string auth headers how can I get it Exchange dot get request now this get request Dot get headers simple thing we are just checking the authorization is present or not if it is present get it from the header itself get header Dot get and give the value this this authorization okay so I'll use the same in HTTP address dot authorization dot get the first index that is your my token okay what is the problem here okay cool let me format it next you have the header with you what you can do now first you need to check if header author if it is a not null and an author done dot contains a key called barrier okay or you can see auth headers dot starts with um this particular keyword b e a r e r if starts with this then remove the space so if You observe while sending this particular token as a barrier it will append seven empty space so you need to remove that first that is what by default add from the postman so we can do anything on that so I will just remove the space author done auth headers okay not headers it should be header right change it dot substring off seven now this authored or this value contains the actual token so you have token with you now simply what you can do here you can do the rest call to to auth service very simple right so what you can do either you can use the web client or rest template so simply you can do something like this create a package call config let's say app config and you can Define at the rate configuration fine then you can Define private not private public because you need the rest template or web client whatever is fine for you rest template template new rest template right you need to Define this as a bin once you define this as a bin inject it here private rest template template Define using Auto add now you can simply do here template dot what type of this validate token method in identity service this is gate method right what you need to pass only the token field so very simple what you can do here go to the Gateway you can do here get for object what is the URL you need to provide http you no need to provide the host and Port since it is registered in the Eureka you can Define the service name identity hyphen service then what is the URL go to the identity service the URL is validate and you need to provide the token go to the Gateway not here slash validate then question mark token and you can pass the token here the token is nothing your author correct and what type of response it will return it don't return anything right or it will return the string so we just Define string dot class okay so this will return you the value so you can simply what you can do here you can add a try catch and you can check for example we have ordered already added the try right just Define the cache capture the exception e then like this you can add a log statement or you can print or you can create your custom error object and you can map the error response okay so for now I will just print it this out or I'll just throw runtime exception okay I'll do both throw new runtime exception you can customize this part okay how to handle the exception it is up to you I am not going to explain that so you can Define some messages here okay on authorized access to application something like that invalid access or some some thing I want to print we can do like this this will absolutely work there is no problem why this is crying what is the error expected where man oh okay cool now what is the error in the upcon fee I need to return this right fine so the way we have implemented will absolutely work but again from the API Gateway we are we are doing the another rest call to Identity service this code leads a security Breeze someone can easily get this input from the API call if they will track the or if they will just trying to hack it right so it's not good you can do it no one can stop it since you know there are multiple way you can perform a same action you can do it this way if you could mask your uh token again or if you can make it better secure just do a rest call and do the validate token API call okay if not just add those validate token related logic and get to itself that is simple right that way you will reduce the network call and also the way you have encrypt similar way you are trying to decrypt in the Gateway itself so I found that is the helpful solution rather than doing a another rest call so I'm just adding this as a comment for your reference you can give a try what I will do I will create a JWT util class and I will just write a logic to validate the token that that makes sense for me so first step just add the JWT dependency in your gateway okay so I'll just add it down okay it's already there I have added it before that's fine once you have added the jwd token just go to the I mean jwd dependency then just go to the identity service and just copy the logic to validate.token from JWT service we have defined the service here right better I'll copy the enter class then we'll modify copy because I want to see while generating the token I am using this secret to encrypt similarly I need the same secret while decrypting it right while validating it I need the same secret to validate so that is the reason I don't want to mess with this code I am taking a complete copy of it and I will paste in my Gateway class ah I can define a package called util and I can paste it here I'll rename the class to shift F6 JWT util fine so here I need only this validate token so for create token and all is not required for me I can remove this I need the sine K because I am using the same secret and I am just write a method to validate a token that's it ok so this is what the solution I feel is good to implement now let's use this JW Tut inside the filter to validate the token rather than doing the rest call we'll use this JW util so what I'll do I will just ignore this I will just inject private JWT util JW tutyl do the auto add fine now just call this validate token give the token fine all good now as for the flow if you try to understand any request user sent first will go to the authentication filter what we have written once it go to the authentication filter it will first check whether user is give the authorization header or not if it is present get the token and if that token is valid then allow him to access the endpoint or allow him to redirect the request to the corresponding microservices otherwise through the exception okay this is the simple flow now we need to tell to the Gateway hey please call this filter before you redirect a request to the corresponding microservices how can I tell that just go to the application.oml file here you can Tilt The Gateway when you are trying to send the request to the corresponding microservices first execute this filter do this security related validation if well and good then only route that request so you can Define in yml file so I want to secure these two micro Services restaurant and sugia so what I can do you can Define the filter so if we'll type here filters you can see here right in filter you can Define what is your filter name I can Define this is what the filter I want to execute before you send request to this so Gap so I can give like this similarly before you send request to restaurant service execute this filter okay I want that filter to be executed for these two micro services so I have configured here this is straight forward flow right request before reach to the API Gateway it will first go to the filter filter will validate lot of things I mean it will check the header it will validate the token if everything okay the request will come to the API Gateway and as per your ml configuration it will go to the corresponding micro Services that's it that is what the simple Spring Security implementation flow in API Gateway now we'll verify the entire flow in action okay so what I'll do we have changes in identity service which is up and running we have done the change in the Gateway only right just restart it so it is up and running okay so I will verify in the Eureka dashboard all the four Services up and running now I need to send request to the Gateway to access the either Sugi app or restaurant service but before that first I need to get the token okay once I get the token I can send that token as part of the header and I can verify the flow so this is the simple what we can do first I will go to the API Gateway since we already registered the user I'll directly ask to get the token for that specific user so this is the guy right we have registered before or we have also registered basant password is PWD one I am asking identity service hey take this credential and validate in your DV if this username and password is correct give me the token first then only using that token I can access to GIF and restaurant services let's get the token we are well and good we are getting the token now I want to access the Sugi app to check the order status okay so if you'll check in this app in the controller we need to give slash Sugi slash order ID so we have tried this right so let me directly try this this one and I am trying it from the 8080 which is from APA Gateway now if I'll send this request it should fail because okay I have already given it North I am not giving any authentication and I am trying to access the Sugi app from the Gateway now if I'll say in the request it is giving me error okay because user have not passed the authorization header it does not contains any token now we'll pass the token which we generate and we will see whether we are getting the result or not we're trying it from Gateway make sure to remember the port what we are using now I will send the request we are getting the result it means whatever the token we have passed we are able to my Gateway is able to validate using the authentication filter before delegating that request to the Sugi app similarly if I want to use the restaurant let's say this one I want to hit the restaurant endpoint so that request would go to the restaurant service now if I'll hit the request I will get the error because I have not passed the authorization header okay so you can customize this error message rather than showing the 500 you can make it four not three which could be forbidden okay you can customize that but that's not our Focus we just understand how we can integrate Security in Gateway now I will go to the authorization I will choose the barrier token and I will pass the token which we generate using the busanth and password pwd1 filter in the request I am getting the result now whichever microservices you can configure simply you can Define that microservices register as a client and all the endpoint need to validate in the authentication filter if you go here in the filter you need to configure all other microservices what you have in your project then if you go in the authentication filter accept these endpoint whatever you have defined in your validator if you go here except these endpoint any other endpoint you will try accessing from your API Gateway must need to validate through this filter logic it will check the authorization header and then if it found the header it will validate that token so to give you the complete flow what I will do I will run in the debug mode and I will just navigate with the flow so for now let me stop this I'll just add a breakpoint here to just verify request is landing to the filter after this validation if everything okay request is going to the let's say we will try for the sugiya okay request is coming here that is what I just want to show you so this also I need to stop and if I will refresh I have stopped two instance see here these are the down right it is not removed here but it is showing down so what I will do I will start in the debug mode even in Gateway I will start in the debug mode okay so it is up and running let's verify that both are up okay so I need to generate the token again so to access the token or to generate the token I can hit this endpoint this is not I mean this is allow right that is what we have defined in the route validator allow this particular endpoint don't ask for any credential otherwise how user can get the token I will hit this endpoint it will talk to my identity service and will give me the result what is the token ok so I want a token I got the token let me copy this token now I want to access the Sugi endpoint okay so go to the authorization header I need to remove this and then I need to paste the new one now I have ran in the debug mode now let me send the request can you see here request came to whom I'll minimize this here request came to filter class authentication filter okay then it will check the URL what user is trying is part of this no it came here if the request contains the authorization as a header this is what the key okay if it contains then pass it to the next what is the next step get the authentication header we are getting the authentication header I'll show you that is the reason I have did the substring of seven if I will show you see here barrier and there is a space we need to remove the seven index from the string so that is the reason I have did the substring now if you will just check the author after remove the seven string index we are getting the entire token now this validate token is there in my JW tutyl if the validation is done I will pass the breakpoint immediately request came to the this is another app the micro services and it will do the again rest call to the restaurant service and will face the result okay it means the request what I am sending with the authentication token is being validated in the Gateway if it is succeed then only request will redirect or route to the corresponding microservices okay this is what we just understand this flow will give you the complete picture of how you can implement the security in your micro Services now if you understand this particular JWT implementation in microservices you can configure hundreds of microservices and you can play with this okay and to be very honest this is one of the common interview question you will get if you mention micro service in your regime okay so practice well and try to understand the flow again and again until unless you understand it do let me know in a comment section if you have any doubts that's all about this particular video guys thanks for watching this video meet you soon with A New Concept
Info
Channel: Java Techie
Views: 43,444
Rating: undefined out of 5
Keywords: microservice jwt security, spring cloud gateway jwt, microservice security, spring cloud gateway jwt-authentication example, spring cloud gateway jwt filter, spring cloud gateway validate jwt token, microservice authentication jwt example, spring cloud jwt, javatechie, microservice, spring cloud, spring boot
Id: MWvnmyLRUik
Channel Id: undefined
Length: 85min 31sec (5131 seconds)
Published: Fri Mar 17 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.