Thanks for the sharing Sergio. This content, as usually done on your channel, is more that valuable for anyone who has wished to learn programming in a professional manner
What about session based Authentication? Can we get session based Authentication object from the cookie in request header ? Previously in Zuul gateway we are using via SecurityContextHolder but in Spring cloud gateway its not working
I've never done it. And I don't find a Spring configuration which does it by its own. I think you may create a custom filter where you create a cookie in the requests when authenticated. And when the cookie already exists, forward the cookie information to the target internal microservice.
hi .. i have a question ... where we should configure (& how) JWT configurations ... ideally i think in API Gateway only .. but it does not include any code other than navigating to microservice .. so how to handle cors issues
I'm not sure to understand your question about the JWT configuration. All the security configuration should be done in the API Gateway. About the CORS and CSRF, I've never tried to setup this security in the API Gateway, so I can't help you here.
@@TheDevWorldbySergioLema can i use gateway+security+jwt together in api gateway service and use it as authentication service also before routing the request
Yes, you should have a dedicated microservice for the authentication. Then, the other microservices will request it to validate the credentials of the user, or use some redirection as i did in the video prior to the request itself
Hi Sergio,wonderful as usual tutorials but pls help me how do i implement login for this with react js front end?which api do i call to log my user in pls?am stuck on that
Thanks. I've done an older playlist where I build a React application. th-cam.com/video/QI1RlF3pBkk/w-d-xo.html. The endpoints to call are the same as the one used in the current video, just be sure to store the JWT token for each request.
Why did you pass the user ID at the request (when you were adding a new header in the Gateway filter)? Like, for what reason you are going to use this user ID?
I pass the User ID as an example. I may use the username, roles, first name and last name. All what may need the subsequent microservices without the need to request the user service again.
Excelente explicación. Yo estoy migrando los microservicios de un proyecto de Spring Boot a Quarkus para aprovechar mejor GraalVM y el ahorro de memoria ram ya que con SpringBoot aún no está muy "púlida" la integración con GraalVM. Pero el api gateway pienso mantenerlo con Spring Cloud/Eureka. Me subscribo al canal esperando más videos como éstos.
I love your work. That's amazing.I am looking forward to seeing more advanced edge functions of the Spring Cloud Gateway. So please do more videos about Spring Cloud Gateway and other stuff
Thank you for the useful video, here you have added the authentication details as the query parameters, how we can add as a form parameters, please help
Thank you for watching. You can do it by simply change the content type by "multipart/form-data" (which is the default content type used when submitting an HTML form) and use the adequate format instead of JSON.
Hi Sergio, Thanks for the tutorial!! I have a question, can we filter the requests based on roles in JWT ? If yes where we can have that filter logic(in each microservice or in gateway service itself)? Thanks in advance!!
In the video, I show how to read a JWT from the request and include the userId in a headers for the subsequent requests for the inner services. What you can do, is read the JWT from the request and include the userId and the roles in the headers for the subsequent requests. Then in the inner microservices you can easily check if the role is available or not just by looking in the headers
@@TheDevWorldbySergioLema Thanks for the comments!! Is there any annotation(like PreAuthorize in spring security) or method to check for role in header and return 403 forbidden(if HTTP method is not allowed for that user) in inner microservice?Thank you!
You can use PreAuthorize annotation, but you will need a filter which injects a user authenticated object in the security context depending on the headers information.
Olá Sérgio, somente uma questão. E se caso do Gateway colocasses no yml o código abaixo, já seria compatível com o _spring-boot-starter-web_ ? spring: main: web-application-type: reactive
Thanks! but why didn't you handle the exception properly? for example, I always get an exception with code 405 or the like with the message {"timestamp":"","path":"","status":405,"error":"Method Not Allowed","requestId": ""}, but I don't know why...
What is the request you are testing? I don't handle the methods correctly, because that's out of the scope of this video. If you want know how to correctly catch an exception, check this video: th-cam.com/video/2bB1WBAHBIY/w-d-xo.html
It's hard to say without looking at the code. Did you try to debug? Do you reach the inner microservice? Do you reach the filter? Who answers "Method not allowed", the gateway or the inner microservice?
@@TheDevWorldbySergioLema Thanks for your comment, I solved the problem, the problem was that in the bean and I gave the webclient and it should have been a builder ... but still the issue with the handling is relevant, if there is an opportunity to do this it would be great (global exception handling in the gateway filter...)
Hello, congratulations for the video. I would like some help in configuring the "routes" of the gateway, how do I create a personalized redirect. Like, I have 3 instances of the same "lb://service-books" but according to some header, url parameter something like that, the requests always fall in the same instance among the 3.
Thanks. I'm not sure to understand your question. If you have 3 instances of service-books, you shouldn't need to select which instance to redirect. This is the job of the load balancer or the service discovery. On the other, side, if you want a complex behavior for the redirections, you can check how I've done it here : github.com/serlesen/microservices-bookstore/blob/alt/springcloud/backend-user/src/main/java/com/sergio/bookstore/backend/user/config/AuthFilter.java
Oh, i think i got it. Check my github repository, i've separated both process. The register has its own URL while the signIn is redirecting all the requests
First, thank you very much for the sequence of videos. It is an excellent learning. Once I implement the AuthFilter and make a request with the correct token, it gives me a 200 response, but the empty content, maybe any ideas?
@@TheDevWorldbySergioLema If I have the code as is the example but it does not make the call to the service, therefore it does not return anything more than an OK 200 request
If it returns nothing but a 200 code, it means that this is the default behavior of Spring Boot, it means that your controller/filters are not taken into account. As I said, maybe you missed a filter.chain() at the end of the filter, or you're exiting your filter in another way (with a return or an exception). Try to debug your filter to know its workflow.
Hi Sergio, If I remove spring web dependency my CORS configuration will get disturbed, I will be unable to use WebMVCConfigurer to configure the CORS. What is the alternative for WebMVCConfigurer or can we configure the CORS in application.yml using spring cloud gateway filters.
You can't use the web dependency, as a gateway already has it, and no endpoint can be used in a gateway. Nevertheless, you can configure the CORS of your gateway in the application yaml file. Check it here, cloud.spring.io/spring-cloud-gateway/multi/multi__cors_configuration.html
Hello, thanks for the tutorial!!! I have a question, with this method, it seems that every request passing throught the API gateway filter call the validatetoken endpoint, is there any method to relay the token to all our microservice? Thanks in advance
In this video, I've separated the authentication (the token validation) into a separated microservice. If what you want is that each microservice is able to validate a token, the routes configuration (in the application.yml) will be simplified and the authentication filter can be avoided.
@@TheDevWorldbySergioLema thank you for your answer. So what I mean is could we only validate the token once and relay it to the other microservice. I means that we only check one time the user.it is like session scope something like that. Maybe with what I want to do, i Will not be able to prevent the token expiration. So I will go with your method. Thanks a lot
In fact, with my method I tried to show a way to validate the token once against a user-auth microservice, then store some user information in the header of the inner request. This information will only be internal and ensure that the user was already authentication by the user-auth microservice.
Muy buena explicación. Gracias. Aunque me pregunto ¿de que manera los microservicios internos tendrían acceso a la información de la persona autenticada (Principal)? la información contenida en el JWT para verificar roles, etc...
En este video devuelvo únicamente el ID del usuario para enviarlo a los servicios internos en un Header. Pero podria devolver una información mas completa, serializarla y enviarla tambien en un Header a todos los servicios para que sepan quien está realizando la llamada
I like this tutorial for JWT filters in the gateway, but how can I send the 401 (not authorized) error to the client? My gateway will received an 401, but send a 500 to the client :(
You can try to catch the error like this (stackoverflow.com/questions/68825377/spring-gatewayfilter-auth-how-to-catch-error-500-and-return-the-response-from). Then, you can throw an error that will be caught by an ExceptionHandler.
@@TheDevWorldbySergioLema I found a better (proper) solution: after bodyToMono() you should put onErrorResume(e -> Mono.just(new UnauthException()). This will force to stop the stream and return an exception to the client. If your UnauthException will have a StatusCode 401 everything will be fine. Within the onErrorResume method you can also do magic, but for a simple project, this will just work.
Hello Man. I dont understand that flow with checking JWT in a gateway service. Ok, u validate it. And then pass string (which u call id). Eventually u have just user id ... no claims, no information about roles etc. U can for header, but parse it on filter of service (for example book service and he will delegate it to ur JWT validate service and in response get all information about user - his claims) Schema( gateway (filtering if header is exist) -> book service (delegate in his filter to outer service JWT parsin and get claims) and then u add it to SpringSecurityContext) thats all. Am i missing something?
In fact, i just wanted to show a usage of the API Gateway with Spring Cloud. If you need a more advanced usage of the JWT maybe the header is not enough, as you said, you may need the roles, the claims or more. My topic was to identify a request from a specific user. This way, the user information (its ID) is always in the subsequent requests
@@TheDevWorldbySergioLema I have some doubts about Security. Mb u can explain me... For example, I fill out the SpringSecurityContext in the Gateway Service (the user logged out, there is a session and for the next request we have SecurityContext by Session, its ok) and then on another service I also have secuirty. It turns out I need to fill in the SecurityContext for example in a filter so that the query successfully reached? Or its somehow pass from GateWay service when we use Eureka Server. I wonder today about that.
You don't need to have the security in all your microservices, ensure at the beginning of the request that the user is correctly authenticated, then maintain somehow the user information in the subsequent requests (i e in a header as i did)
una consulta espero que me contesten. Estoy trabajando con eureka y cloud gateway .. el problema que tengo es que para producción en que servidor se puede publicar gateway.. intente con jboss y wlidfly y no funcionan..
No sé si entendí tu pregunta. Spring cloud gateway es una aplicación Spring Boot, puedes arrancarla simplementd con el comando de maven de Spring Boot.
@@TheDevWorldbySergioLema cuando se desplega en un servidor jboss o wlidfly no funciona siempre me devuelve un http 404. y no encuentro video o tutorial de como desplegar gateway en algun servidor
Lo que tienes que buscar es como hacer que una aplicación Spring Boot se lance en JBoss, ilya-murzinov.github.io/articles/spring-boot-jboss/. El hecho que sea Spring Cloud Gateway no cambiará nada. Si consigues que arranque en el servidor JBoss y aún así tienes un HTTP 404, tendrás que habilitar los logs Debug para obtener más resultado sobre las rutas.
@@TheDevWorldbySergioLema los servicio y eureka si funcionan correctamente en un servidor jboss y wildfly solo tengo el inconveniente con gateway. segun un docente de udemy me respondio lo siguiente "no se puede ya que Spring Cloud Gateway es con el api web reactiva de spring reactor + webflux, solo se puede desplegar en servidores con soporte reactivo como netty o jboss Undertow." e buscado información sobre eso y no he encontrado.
Ya entiendo, de serie Spring Cloud Gateway tiene un servidor web integrado, Tomcat, por eso no necesita una configuración web como un app Spring Boot. Además tiene la componente reactiva que solo es compatible con Tomcat os los que mencionaste (esta parte no lo sabía, gracias por la información)
In the example I show, i delegate the authentication to another microservice. Spring Cloud Gateway only makes the routing. You can manage the authentication as you want doing the correct routing
En principio ya tienes un nivel de seguridad superior puesto que esos microservicios son inaccesibles desde el exterior, pero nunca está de mas añadir una comunicación más segura
Dependerá de la complejidad a añadir una comunicación HTTPS y sobre todo la facilidad (o dificultad) de acceder a los servicios internos. Personalmente siempre intento implementarlo.
Maybe you're not using the same version of the libraries. You can check the code I've used at Github. You can find the code in the description of the video.
Re bonjour, j'ai également implémenté cette solution, toutefois, j'ai l'impression que mon filtre ne s'applique pas. J'utilise un service pour l'authentification , un gateway et un autre service sur lequel je souhaite appliquer le filtre. Ce dernier est censé me renvoyer un simple message cependant sans même préciser de header je reçois un message
Je te conseillerais d'ajouter de point d'arrêt (ou des logs) sur le gateway, pour savoir s'il passe vraiment par le filtre. À partir de là, tu sauras si c'est la configuration du filtre qui n'est pas appliquée (application.yml) ou la logique du filtre qui appelle quand même le service interne sans validation de l'authentification. Je ne peux pas trop t'aider sans plus de context.
@@TheDevWorldbySergioLema justement j'ai utilisé des break point au niveau du return (exchange, chain) et lancé la gateway en mode debug mais le programme s'arrête immédiatement. De plus, j'ai ajouté un break point dans le premier if de la méthode apply mais rien ne se passe. Cela signifie que la méthode n'est même pas exécuté ?
"lancé la gateway en mode debug mais le programme s'arrête immédiatement" qu'est-ce que tu veux dire par là ? Une erreur directement ? Si l'application ne s'arrête pas dans les breakpoint, c'est sûr, la méthode ne passe pas par là. Pour savoir si Spring utilise bien le filtre, serait de passer les logs de Spring en mode debug (attention, t'en auras énormément). Regarder quand ton Bean est chargé et sur quelles URLs. Une alternative (toujours dans le debug de Spring), c'est d'ajouter un controlleur, et mettre un breakpoint dans le controller. Comme ça tu sais quand Spring charge ton Bean.
@@TheDevWorldbySergioLema oui pardon je voulais faire allusion au debugger. Il s'arrête sans montrer le contenu des variables lors de l'exécution. Bien sûr l'application continue de tourner pendant ce temps. Cela m'amène vraiment à penser que mon filtre n'est pas pris en compte par spring boot. Pourtant j'ai bien utilisé @Component, il devrait donc être dans le contexte de spring 🤔
Ton filtre n'étend peut-être pas la bonne class. Ton filtre n'est peut-être pas scanné (ajoute l'annotation ComponentScan avec le package en question). Regarde les logs debug de Spring pour voir si ton filtre est tenu en compte par Spring (peut-être que c'est juste une question que ton filtre est configuré sur une autre URL).
Gracias! Lo he utilizado en un proyecto, está bien, pero prefiero Jhipster que me deja despues un control total sobre el proyecto sin tener que utilizar su framwork
@@maeskii Para empezar con Spring Boot, te recomiendo esta playlist, donde creo un backend desde cero con Spring Boot, explicando cada componente: th-cam.com/play/PLab_if3UBk9-TuyqwMy3JvNHeCh7Ll9Wz.html
@@TheDevWorldbySergioLema hola gracias, no entiendo por qué se hacen paquetes de modelo, controlador, servicios y repositorio. Sabes dónde puedo encontrar información sobre eso ?
Es para separar, para organizar el código: * modelo contendrá la estructura de la base de datos, las entidades que reflejan la base de datos; * controlador tendrá los puntos de entrada de las llamadas HTTP; * servicios tendrá toda la lógica de la aplicación, siempre que sea heterogénea (si es muy concreta a una entidad/modelo, mejor que esté en modelo); * y repositorio tendrá los repositorios de Spring JPA para hablar con al base de datos, para realizar búsquedas en la base de datos. Toda esta estructura intenta seguir la filosofía DDD (Domain Driven Development, es.wikipedia.org/wiki/Dise%C3%B1o_guiado_por_el_dominio).
I"m not sure about your question. You have all the methods of the Flux interface here: projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html. You can use the block() methods to read the elements or map the response into some other operations.
If it is possible can anyone explain this block of code? return webClientBuilder.build().get() .uri("localhost:8081/master-service/v1/api/countries/all?token=" + parts[1]) .retrieve() .bodyToMono(AuthRequest.class).map(userDto -> { exchange.getRequest().mutate().header("X-auth-user-id", String.valueOf(userDto.getUsername())); return exchange; }).flatMap(chain::filter); I'm not able to route to any microservice, even the jwt token is valid still it's showing 500 with org.springframework.web.reactive.function.client.WebClientResponseException$ServiceUnavailable: 503 Service Unavailable from UNKNOWN I have registered the microservice to the eureka-server. Can anyone please tell me what I'm missing here? I'm trying to create a CustomFilter. But w/o the above code routing will work properly.
The above code will: * before performing the original request, another intermediary request will be made; * first make a GET request to an endpoint of master-service with a token as a query param; * the response be mapped into an object AuthRequest; * from the previous mapped object AuthRequest, the username will be read and used as a value for the header "x-auth-user-id"; * the header "x-auth-user-id" will be sent to the original request; * continue with the following available filters with chain.filter().
Does the endpoint "localhost:8081/master-service/v1/api/countries/all?token=" respond well with a valid JWT? If no, the problem is located with this intermediary microservice. If yes, maybe the mapping to the DTO AuthRequest isn't correct.
Here you are: github.com/serlesen/microservices-bookstore/blob/alt/springcloud/backend-user/src/main/java/com/sergio/bookstore/backend/user/config/AuthFilter.java
Thanks for the sharing Sergio. This content, as usually done on your channel, is more that valuable for anyone who has wished to learn programming in a professional manner
Thanks for your comment. That was the purpose, show how to work in a professional environment
Finally someone who explains how to apply a GatewayFilter in yaml configuration. Thanks!
Glad it helped you
I support you bro keep going good work!
Thank so much!
Que buena explicación, es justo lo que estaba buscando.
Gracias!!
What about session based Authentication? Can we get session based Authentication object from the cookie in request header ? Previously in Zuul gateway we are using via SecurityContextHolder but in Spring cloud gateway its not working
I've never done it. And I don't find a Spring configuration which does it by its own. I think you may create a custom filter where you create a cookie in the requests when authenticated. And when the cookie already exists, forward the cookie information to the target internal microservice.
Why did you use constructor injection here and not requiredargsconstructor like in previous videos?
Good point, I've missed it
Cool! Thank you so much!❤
Do i have plans to have some examples for webflux + security+ gradle?
I'm preparing something with WebFlux and Security 😉, but Gradle is not in the scope 😅
To the point tutorial. Thanks a lot
Glad you liked it
Thank you! It was useful
Don't hesitate to share it in your network 😊
hi .. i have a question ...
where we should configure (& how) JWT configurations ... ideally i think in API Gateway only ..
but it does not include any code other than navigating to microservice ..
so how to handle cors issues
I'm not sure to understand your question about the JWT configuration. All the security configuration should be done in the API Gateway. About the CORS and CSRF, I've never tried to setup this security in the API Gateway, so I can't help you here.
Why did you remove web dependency after adding gateway dependency in pom.xml?
Because a gateway is already a web server implicitly
@@TheDevWorldbySergioLema can i use gateway+security+jwt together in api gateway service and use it as authentication service also before routing the request
Never tried, but i don't think so.
@@TheDevWorldbySergioLema ok, which service should have authentication implemented if not api gateway, do we need separate service just for auth
Yes, you should have a dedicated microservice for the authentication. Then, the other microservices will request it to validate the credentials of the user, or use some redirection as i did in the video prior to the request itself
Hi Sergio,wonderful as usual tutorials but pls help me how do i implement login for this with react js front end?which api do i call to log my user in pls?am stuck on that
Thanks. I've done an older playlist where I build a React application. th-cam.com/video/QI1RlF3pBkk/w-d-xo.html. The endpoints to call are the same as the one used in the current video, just be sure to store the JWT token for each request.
Great content thank you!
Thanks!
Why did you pass the user ID at the request (when you were adding a new header in the Gateway filter)? Like, for what reason you are going to use this user ID?
I pass the User ID as an example. I may use the username, roles, first name and last name. All what may need the subsequent microservices without the need to request the user service again.
I'm using spring version - 2.7.0 & cloud version - 2021.0.3 . Filter apply method code is not executed.
Have you added the Component annotation? Are you sure the package is scanned by Spring Boot? Have you correctly extended the Filter?
@@TheDevWorldbySergioLema Yes @Component added. It's probably scan.
Excelente explicación. Yo estoy migrando los microservicios de un proyecto de Spring Boot a Quarkus para aprovechar mejor GraalVM y el ahorro de memoria ram ya que con SpringBoot aún no está muy "púlida" la integración con GraalVM. Pero el api gateway pienso mantenerlo con Spring Cloud/Eureka. Me subscribo al canal esperando más videos como éstos.
Gracias! Me tendría que meter algo con GraalVM que está muy bien, pero aún no he tenido tiempo de jugar con el.
Hi..Is there a way to use token relay functionality of spring cloud gateway with password grant?
I'm sorry, but i've never tested this feature
What if the user tries to acess Microservice directly insted of api Gateway..??
He can't. The microservices are in private network and not reacheable from the outside.
For the load balancer, what if we use the new Spring Cloud LoadBalancer which is considered to be more abstractions?
Never tested, but seems more compact, yes. Thanks for sharing this information
I love your work. That's amazing.I am looking forward to seeing more advanced edge functions of the Spring Cloud Gateway. So please do more videos about Spring Cloud Gateway and other stuff
Thank you! I took some rest, but i will come back with more content
Thank you for the useful video, here you have added the authentication details as the query parameters, how we can add as a form parameters, please help
Thank you for watching. You can do it by simply change the content type by "multipart/form-data" (which is the default content type used when submitting an HTML form) and use the adequate format instead of JSON.
Hi Sergio,
Thanks for the tutorial!!
I have a question, can we filter the requests based on roles in JWT ? If yes where we can have that filter logic(in each microservice or in gateway service itself)?
Thanks in advance!!
In the video, I show how to read a JWT from the request and include the userId in a headers for the subsequent requests for the inner services. What you can do, is read the JWT from the request and include the userId and the roles in the headers for the subsequent requests. Then in the inner microservices you can easily check if the role is available or not just by looking in the headers
@@TheDevWorldbySergioLema
Thanks for the comments!!
Is there any annotation(like PreAuthorize in spring security) or method to check for role in header and return 403 forbidden(if HTTP method is not allowed for that user) in inner microservice?Thank you!
You can use PreAuthorize annotation, but you will need a filter which injects a user authenticated object in the security context depending on the headers information.
Wondering how long it took for you to spot the typo on the prices predicate.
😅 when starting the application, it already cried an error. I've corrected and continued. All of this was removed in the post-production video.
Even after it was working your log seems to show some exceptions but you didn’t seem to notice them.
Olá Sérgio, somente uma questão. E se caso do Gateway colocasses no yml o código abaixo, já seria compatível com o _spring-boot-starter-web_ ?
spring:
main:
web-application-type: reactive
En principio, si, pero nunca lo he probado.
@@TheDevWorldbySergioLema gracias por contestarme, lo intente hoy, si que resulta
Thanks! but why didn't you handle the exception properly? for example, I always get an exception with code 405 or the like with the message {"timestamp":"","path":"","status":405,"error":"Method Not Allowed","requestId": ""}, but I don't know why...
What is the request you are testing? I don't handle the methods correctly, because that's out of the scope of this video. If you want know how to correctly catch an exception, check this video: th-cam.com/video/2bB1WBAHBIY/w-d-xo.html
@@TheDevWorldbySergioLema thanks for the answer, but I also handle the exception like this, I guess I'm doing something wrong
It's hard to say without looking at the code. Did you try to debug? Do you reach the inner microservice? Do you reach the filter? Who answers "Method not allowed", the gateway or the inner microservice?
@@TheDevWorldbySergioLema Thanks for your comment, I solved the problem, the problem was that in the bean and I gave the webclient and it should have been a builder ...
but still the issue with the handling is relevant, if there is an opportunity to do this it would be great (global exception handling in the gateway filter...)
Hello, congratulations for the video.
I would like some help in configuring the "routes" of the gateway, how do I create a personalized redirect. Like, I have 3 instances of the same "lb://service-books" but according to some header, url parameter something like that, the requests always fall in the same instance among the 3.
Thanks.
I'm not sure to understand your question. If you have 3 instances of service-books, you shouldn't need to select which instance to redirect. This is the job of the load balancer or the service discovery.
On the other, side, if you want a complex behavior for the redirections, you can check how I've done it here : github.com/serlesen/microservices-bookstore/blob/alt/springcloud/backend-user/src/main/java/com/sergio/bookstore/backend/user/config/AuthFilter.java
please how can we make the register not signIn?
I really need it can you share it if you have an example
I'm not sure to understand you. The register and the signIn are the same
Oh, i think i got it. Check my github repository, i've separated both process. The register has its own URL while the signIn is redirecting all the requests
First, thank you very much for the sequence of videos. It is an excellent learning. Once I implement the AuthFilter and make a request with the correct token, it gives me a 200 response, but the empty content, maybe any ideas?
Thanks for watching. Make sure that at the end of the filter you call filter.chain to allow the rest of your code being run
@@TheDevWorldbySergioLema If I have the code as is the example but it does not make the call to the service, therefore it does not return anything more than an OK 200 request
If it returns nothing but a 200 code, it means that this is the default behavior of Spring Boot, it means that your controller/filters are not taken into account. As I said, maybe you missed a filter.chain() at the end of the filter, or you're exiting your filter in another way (with a return or an exception). Try to debug your filter to know its workflow.
Hi Sergio,
If I remove spring web dependency my CORS configuration will get disturbed, I will be unable to use WebMVCConfigurer to configure the CORS. What is the alternative for WebMVCConfigurer or can we configure the CORS in application.yml using spring cloud gateway filters.
You can't use the web dependency, as a gateway already has it, and no endpoint can be used in a gateway. Nevertheless, you can configure the CORS of your gateway in the application yaml file. Check it here, cloud.spring.io/spring-cloud-gateway/multi/multi__cors_configuration.html
Hello, thanks for the tutorial!!! I have a question, with this method, it seems that every request passing throught the API gateway filter call the validatetoken endpoint, is there any method to relay the token to all our microservice? Thanks in advance
In this video, I've separated the authentication (the token validation) into a separated microservice. If what you want is that each microservice is able to validate a token, the routes configuration (in the application.yml) will be simplified and the authentication filter can be avoided.
@@TheDevWorldbySergioLema thank you for your answer. So what I mean is could we only validate the token once and relay it to the other microservice. I means that we only check one time the user.it is like session scope something like that. Maybe with what I want to do, i Will not be able to prevent the token expiration. So I will go with your method. Thanks a lot
In fact, with my method I tried to show a way to validate the token once against a user-auth microservice, then store some user information in the header of the inner request. This information will only be internal and ensure that the user was already authentication by the user-auth microservice.
@@TheDevWorldbySergioLema Thanks for your explanation
Muy buena explicación. Gracias. Aunque me pregunto ¿de que manera los microservicios internos tendrían acceso a la información de la persona autenticada (Principal)? la información contenida en el JWT para verificar roles, etc...
En este video devuelvo únicamente el ID del usuario para enviarlo a los servicios internos en un Header. Pero podria devolver una información mas completa, serializarla y enviarla tambien en un Header a todos los servicios para que sepan quien está realizando la llamada
Sirvió de mucho. Bien!
Encantado de que te sirviera! 😁
I like this tutorial for JWT filters in the gateway, but how can I send the 401 (not authorized) error to the client? My gateway will received an 401, but send a 500 to the client :(
You can try to catch the error like this (stackoverflow.com/questions/68825377/spring-gatewayfilter-auth-how-to-catch-error-500-and-return-the-response-from). Then, you can throw an error that will be caught by an ExceptionHandler.
@@TheDevWorldbySergioLema I found a better (proper) solution: after bodyToMono() you should put onErrorResume(e -> Mono.just(new UnauthException()). This will force to stop the stream and return an exception to the client. If your UnauthException will have a StatusCode 401 everything will be fine. Within the onErrorResume method you can also do magic, but for a simple project, this will just work.
Yes, this seems to be a better solution. Good for you!
Hello Man. I dont understand that flow with checking JWT in a gateway service.
Ok, u validate it. And then pass string (which u call id). Eventually u have just user id ... no claims, no information about roles etc. U can for header, but parse it on filter of service (for example book service and he will delegate it to ur JWT validate service and in response get all information about user - his claims)
Schema( gateway (filtering if header is exist) -> book service (delegate in his filter to outer service JWT parsin and get claims) and then u add it to SpringSecurityContext) thats all.
Am i missing something?
In fact, i just wanted to show a usage of the API Gateway with Spring Cloud. If you need a more advanced usage of the JWT maybe the header is not enough, as you said, you may need the roles, the claims or more. My topic was to identify a request from a specific user. This way, the user information (its ID) is always in the subsequent requests
@@TheDevWorldbySergioLema I have some doubts about Security. Mb u can explain me... For example, I fill out the SpringSecurityContext in the Gateway Service (the user logged out, there is a session and for the next request we have SecurityContext by Session, its ok) and then on another service I also have secuirty. It turns out I need to fill in the SecurityContext for example in a filter so that the query successfully reached? Or its somehow pass from GateWay service when we use Eureka Server. I wonder today about that.
You don't need to have the security in all your microservices, ensure at the beginning of the request that the user is correctly authenticated, then maintain somehow the user information in the subsequent requests (i e in a header as i did)
una consulta espero que me contesten. Estoy trabajando con eureka y cloud gateway .. el problema que tengo es que para producción en que servidor se puede publicar gateway.. intente con jboss y wlidfly y no funcionan..
No sé si entendí tu pregunta. Spring cloud gateway es una aplicación Spring Boot, puedes arrancarla simplementd con el comando de maven de Spring Boot.
@@TheDevWorldbySergioLema cuando se desplega en un servidor jboss o wlidfly no funciona siempre me devuelve un http 404. y no encuentro video o tutorial de como desplegar gateway en algun servidor
Lo que tienes que buscar es como hacer que una aplicación Spring Boot se lance en JBoss, ilya-murzinov.github.io/articles/spring-boot-jboss/. El hecho que sea Spring Cloud Gateway no cambiará nada. Si consigues que arranque en el servidor JBoss y aún así tienes un HTTP 404, tendrás que habilitar los logs Debug para obtener más resultado sobre las rutas.
@@TheDevWorldbySergioLema los servicio y eureka si funcionan correctamente en un servidor jboss y wildfly solo tengo el inconveniente con gateway. segun un docente de udemy me respondio lo siguiente "no se puede ya que Spring Cloud Gateway es con el api web reactiva de spring reactor + webflux, solo se puede desplegar en servidores con soporte reactivo como netty o jboss Undertow." e buscado información sobre eso y no he encontrado.
Ya entiendo, de serie Spring Cloud Gateway tiene un servidor web integrado, Tomcat, por eso no necesita una configuración web como un app Spring Boot. Además tiene la componente reactiva que solo es compatible con Tomcat os los que mencionaste (esta parte no lo sabía, gracias por la información)
can spring cloud gateway authorized users? It's so hard to archive it
In the example I show, i delegate the authentication to another microservice. Spring Cloud Gateway only makes the routing. You can manage the authentication as you want doing the correct routing
Deberiamos segurizar los servicios internos que se comunican entre ellos? O no tiene mucho sentido?
En principio ya tienes un nivel de seguridad superior puesto que esos microservicios son inaccesibles desde el exterior, pero nunca está de mas añadir una comunicación más segura
@@TheDevWorldbySergioLema Que recomendas ? Gracias ! ( Los servicios internos están dentro de un cluster de Kubernetes en un Mesh)
Dependerá de la complejidad a añadir una comunicación HTTPS y sobre todo la facilidad (o dificultad) de acceder a los servicios internos. Personalmente siempre intento implementarlo.
Hi this does not work on my local machine
Maybe you're not using the same version of the libraries. You can check the code I've used at Github. You can find the code in the description of the video.
Re bonjour, j'ai également implémenté cette solution, toutefois, j'ai l'impression que mon filtre ne s'applique pas. J'utilise un service pour l'authentification , un gateway et un autre service sur lequel je souhaite appliquer le filtre. Ce dernier est censé me renvoyer un simple message cependant sans même préciser de header je reçois un message
Je te conseillerais d'ajouter de point d'arrêt (ou des logs) sur le gateway, pour savoir s'il passe vraiment par le filtre. À partir de là, tu sauras si c'est la configuration du filtre qui n'est pas appliquée (application.yml) ou la logique du filtre qui appelle quand même le service interne sans validation de l'authentification.
Je ne peux pas trop t'aider sans plus de context.
@@TheDevWorldbySergioLema justement j'ai utilisé des break point au niveau du return (exchange, chain) et lancé la gateway en mode debug mais le programme s'arrête immédiatement. De plus, j'ai ajouté un break point dans le premier if de la méthode apply mais rien ne se passe. Cela signifie que la méthode n'est même pas exécuté ?
"lancé la gateway en mode debug mais le programme s'arrête immédiatement" qu'est-ce que tu veux dire par là ? Une erreur directement ?
Si l'application ne s'arrête pas dans les breakpoint, c'est sûr, la méthode ne passe pas par là.
Pour savoir si Spring utilise bien le filtre, serait de passer les logs de Spring en mode debug (attention, t'en auras énormément). Regarder quand ton Bean est chargé et sur quelles URLs.
Une alternative (toujours dans le debug de Spring), c'est d'ajouter un controlleur, et mettre un breakpoint dans le controller. Comme ça tu sais quand Spring charge ton Bean.
@@TheDevWorldbySergioLema oui pardon je voulais faire allusion au debugger. Il s'arrête sans montrer le contenu des variables lors de l'exécution. Bien sûr l'application continue de tourner pendant ce temps. Cela m'amène vraiment à penser que mon filtre n'est pas pris en compte par spring boot. Pourtant j'ai bien utilisé @Component, il devrait donc être dans le contexte de spring 🤔
Ton filtre n'étend peut-être pas la bonne class. Ton filtre n'est peut-être pas scanné (ajoute l'annotation ComponentScan avec le package en question).
Regarde les logs debug de Spring pour voir si ton filtre est tenu en compte par Spring (peut-être que c'est juste une question que ton filtre est configuré sur une autre URL).
Eres brutal. Qué opinas de Vaadin?
Gracias! Lo he utilizado en un proyecto, está bien, pero prefiero Jhipster que me deja despues un control total sobre el proyecto sin tener que utilizar su framwork
@@TheDevWorldbySergioLema thanks
No entendí nada
Siento que sea así. Es por culpa de mi explicación? La complejidad? Los subtítulos?
@@TheDevWorldbySergioLema oh no, es porqué es el primer video de spring boot que veo jeje
@@maeskii Para empezar con Spring Boot, te recomiendo esta playlist, donde creo un backend desde cero con Spring Boot, explicando cada componente: th-cam.com/play/PLab_if3UBk9-TuyqwMy3JvNHeCh7Ll9Wz.html
@@TheDevWorldbySergioLema hola gracias, no entiendo por qué se hacen paquetes de modelo, controlador, servicios y repositorio. Sabes dónde puedo encontrar información sobre eso ?
Es para separar, para organizar el código:
* modelo contendrá la estructura de la base de datos, las entidades que reflejan la base de datos;
* controlador tendrá los puntos de entrada de las llamadas HTTP;
* servicios tendrá toda la lógica de la aplicación, siempre que sea heterogénea (si es muy concreta a una entidad/modelo, mejor que esté en modelo);
* y repositorio tendrá los repositorios de Spring JPA para hablar con al base de datos, para realizar búsquedas en la base de datos.
Toda esta estructura intenta seguir la filosofía DDD (Domain Driven Development, es.wikipedia.org/wiki/Dise%C3%B1o_guiado_por_el_dominio).
Help Required!!!! Can you tell How to read the body -> exchange.getRequest().getBody(), as it returns Flux .. Thanks in advance :-)
There is a requirement to parse the body too..& extract the data and validate few of the fields coming the request body of post request
I"m not sure about your question. You have all the methods of the Flux interface here: projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html. You can use the block() methods to read the elements or map the response into some other operations.
If it is possible can anyone explain this block of code?
return webClientBuilder.build().get()
.uri("localhost:8081/master-service/v1/api/countries/all?token=" + parts[1])
.retrieve()
.bodyToMono(AuthRequest.class).map(userDto -> {
exchange.getRequest().mutate().header("X-auth-user-id",
String.valueOf(userDto.getUsername()));
return exchange;
}).flatMap(chain::filter);
I'm not able to route to any microservice, even the jwt token is valid still it's showing 500 with
org.springframework.web.reactive.function.client.WebClientResponseException$ServiceUnavailable: 503 Service Unavailable from UNKNOWN
I have registered the microservice to the eureka-server. Can anyone please tell me what I'm missing here? I'm trying to create a CustomFilter.
But w/o the above code routing will work properly.
The above code will:
* before performing the original request, another intermediary request will be made;
* first make a GET request to an endpoint of master-service with a token as a query param;
* the response be mapped into an object AuthRequest;
* from the previous mapped object AuthRequest, the username will be read and used as a value for the header "x-auth-user-id";
* the header "x-auth-user-id" will be sent to the original request;
* continue with the following available filters with chain.filter().
Does the endpoint "localhost:8081/master-service/v1/api/countries/all?token=" respond well with a valid JWT? If no, the problem is located with this intermediary microservice. If yes, maybe the mapping to the DTO AuthRequest isn't correct.
@@TheDevWorldbySergioLema thanks I'll check this one. Thanks for the replay👍🏽
Can I get the GitHub link of this example code?
Here you are: github.com/serlesen/microservices-bookstore/blob/alt/springcloud/backend-user/src/main/java/com/sergio/bookstore/backend/user/config/AuthFilter.java