Build and Test Reactive Microservices with Spring Cloud Gateway

Arilson Santos

Thanks Matt!. Great article!

Matt Raible

I would recommend comparing your CarServiceApplication with the finished one on GitHub. If you’re running from your IDE, you might need to install the Lombok plugin for things to work.

Sanjay Yadav

Spring has released Reactive Web Framework and it is one of the hot topics in Spring world.Our controllers now run on Spring Reactive Engine. Check out a Basic Spring Web-Flux Crud example.

saguadoi

Thanks fir this article Matt, but i have a problen when display gateway. The error code is:

Caused by: java.lang.IllegalArgumentException: clientRegistrationRepository cannot be null

who has any idea why it could be?

Matt Raible

I’ve seen this happen when your Okta values aren’t set. Does your application.properties have okta.* keys defined and values for your app?


okta.oauth2.issuer=$issuer
okta.oauth2.client-id=$clientId
okta.oauth2.client-secret=$clientSecret

Sanjo Ganguly

If I add this in Login redirect URIs as http://localhost:8080/login/oauth2/code/okta. I am getting this below error

http://localhost:8080/login/oauth2/code/okta?code=d1mYJJwUuEVQNKsyAiM8&state=-fESRLHyz6x59FOKnkY8WpkMStBX1hF1ZqfBrzILyIw%3D

This application has no configured error view, so you are seeing this as a fallback.

Sat Aug 08 00:51:21 IST 2020
There was an unexpected error (type=Unauthorized, status=401).

Any updates is there any problem with I tried will latest spring boot that also same result . Is there any problem with OKTA configuration

Brian Demers

Double check to make sure your client-id/secret are correct in your properties files.
The login on the Okta side was likely fine, this type of problem is usually with the last leg of the OAuth exchange.
You also need to make sure your backend can make HTTP calls to your Okta org (if you have a restrictive corporate firewall/vpn)

Let us know if that helped!

Sanjo Ganguly

No it does it does not works

Sanjo Ganguly

Create a Web Application in Okta
Log in to your Okta Developer account (or sign up if you don’t have an account).

From the Applications page, choose Add Application.

On the Create New Application page, select Web.

Give your app a memorable name, add http://localhost:8080/login/oauth2/code/okta as a Login redirect URI, select Refresh Token (in addition to Authorization Code), and click Done.

Copy the issuer (found under API > Authorization Servers), client ID, and client secret into application.properties for both projects.

If I add this http://localhost:8080/login/oauth2/code/okta it show this error but again if I change to
https://dev-450392.okta.com… i got different attached gif

okta plugins also not working properly it there any bug I used Auth0 it was not so buggy

Sanjo Ganguly

https://uploads.disquscdn.c…

Matt Raible

It looks like the redirect URI you’re trying to use is not allowed by your app. If you copy the URL from your address bar (when you see the 400 error) into a text editor, you’ll see the redirect URI it’s trying to go to. Add that redirect URI to your Okta app and it should work.

Sanjo Ganguly

Add that redirect URI to your app and it should work. ?? Did not understood line what is your app mean here ? developer.okta.com -> Application or spring boot apps

Matt Raible

I mean your app on Okta.

Sanjo Ganguly

I will try once again and update

Sanjo Ganguly

NO I am getting different error now https://uploads.disquscdn.c… https://uploads.disquscdn.c…

P.S Not this time I clone from your git repo and only change

okta.oauth2.issuer=
okta.oauth2.client-id=
okta.oauth2.client-secret=

Please suggest

Matt Raible

I am able to reproduce this issue and I’m not sure why it happens. The last time I tried this, it worked. I’ll investigate and report back about what I find.

Matt Raible

I realized today that this tutorial only adds an access token for requests to /cars. For the faveCars() method, you need to make some changes to the method.


@GetMapping("/fave-cars")
public Flux<car> faveCars(@RegisteredOAuth2AuthorizedClient(“okta”) OAuth2AuthorizedClient authorizedClient) {
return carClient.build().get().uri(“lb://car-service/cars”)
.header(“Authorization”, "Bearer " + authorizedClient.getAccessToken().getTokenValue())
.retrieve().bodyToFlux(Car.class)
.filter(this::isFavorite);
}

I think it should be possible to configure the WebClient bean to be aware of the OAuth2AuthorizedClient, but I haven’t found a solution yet.

Abdelrahman Mahmoud

Hi,
Great efforts…
I’m trying to add a new End point in car service (reactive example) to read the authenticated user group as bellow:

@RequestMapping("/info")
@ResponseBody
public String oauthUserInfo(@RegisteredOAuth2AuthorizedClient(“okta”) OAuth2AuthorizedClient authorizedClient,
@AuthenticationPrincipal OAuth2User oauth2User) {

}

and getting all the attributes from oauth2User parametter as oauth2User.getAttributes() … and i updated the gateway to allow the new end point as → route(“car-service”, r → r.path("/cars","/info")

However, when i try the new end point on the browser I’m getting bad request with the below description:
The ‘redirect_uri’ parameter must be an absolute URI that is whitelisted in the client app settings.

When i checked the URL in the browser, i founded as below:
https://dev-274060.okta.com…

If i added this redirect_uri, It will also produces another error because as per my understanding, we aren’t allowed to access port 8081 because it’s behind the Gateway 8080 and after applying TokenRelayGatewayFilterFactory in gateway routing

Is there anything I’m missing?

Edit:
If i moved this end point (info) to the FaveCarsController which in the ApiGateWay, it’s working fine

Matt Raible

It sounds like the token isn’t being relayed to your downstream service, or it’s not setup to be a resource server. Make sure your car service has the following in its security config:


http

.oauth2ResourceServer()
.jwt();

Lakshyajit Laxmikant

@mattraible kudos for this great article!
Could you suggest how to retrieve the user details from the token inside of a microservice so that I may store it in a db?