Spring OAuth2 authentication with token - reactjs

I have this SpringBoot app, which uses the OAuth2 login via Google. And it works just fine on it's own.
However, I'm trying to connect it with my React frontend and thus: trying to develop the exchange of tokens.
SecurityConfig
http.cors()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/oauth/**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.oauth2Login();
Now, I'm obtaining the token this way:
OAuth2AuthorizedClient client = authorizedClientService.loadAuthorizedClient(authentication.getAuthorizedClientRegistrationId(), authentication.getName());
String token = client.getAccessToken().getTokenValue();
and send it to my React client.
The question is: how to receive and interpret the authorization token at SpringBoot app?
Right now it's giving me a CORS issue as soon as I attach the Authoriation header...

you have to configure the allowed CORS requests in your spring boot app or serve your react frontend from the same domain.
personally ive always done the second option, with the spring boot app serving the react bundle on some url (e.g. /static/js/).

Related

React page not rendering when using Okta

I working on React app which is secured by Okta OAuth provider. Currently, all of my routes are authenticated. I want a public route where anyone can access it. Eg: https://my.example.com/welcome
These are the configs that I have used
application.yml
okta:
oauth2:
issuer: https://xxxxxxxxx.okta.com/oauth2/default
clientId: xxxxxxxxxxxxxx
clientSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
post-logout-redirect-uri: /
redirect-uri: /login/callback
Spring security config
httpSecurity.authorizeRequests()
.antMatchers("/", "/welcome").permitAll()
.anyRequest().authenticated()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and().oauth2Client()
.and().oauth2Login();
return httpSecurity.build();
React Route
<Route path={"/welcome"} exact={true} render={(props) => (<WelcomePage/>)}/>
When I visit /welcome route I'm getting a blank page with this warning message in the browser
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://xxxxxxx.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=xxxxxxxxx&scope=profile%20email%20openid&state=rDYLqV7WDv2la1onSvQsTNeXCvDmWhS0_ZoPFlMAE80%3D&redirect_uri=https://xxxxxx.xxxxx.com/careportal/login/callback&nonce=XvMoC5iP5OGYsvG0bS-QfQh1yfYmhNohmD7GvfukyCo with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Can anyone help me to access a public route without auth?
TIA
If you have anything else than spring-boot-starter-oauth2-resource-server as OAuth2 lib in your Spring project, remove it and configure your Spring REST API as a resource-server.
With the helper lib from second tutorial, this might be enough:
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<!-- replace "webmvc" with "weblux" for reactive app -->
<!-- replace "jwt" with "introspecting" if Okta access-tokens are not JWTs -->
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<version>6.0.4</version>
</dependency>
#EnableMethodSecurity // replace with #EnableReactiveMethodSecurity for reactive app
#Configuration
public class SecurityConfig {
}
com.c4-soft.springaddons.security.issuers[0].location=https://xxxxxxxxx.okta.com/
com.c4-soft.springaddons.security.issuers[0].authorities.claims=groups
com.c4-soft.springaddons.security.permit-all=/,/welcome
# following might be too permissive, restrict if needed
com.c4-soft.springaddons.security.cors[0].path=/**
With Spring spring-boot-starter-oauth2-resource-server only, there is quite some more Java conf to write (refer to first tutorial)
Do not forget to request groups (and maybe openid and offline_access) scopes when you authenticate users from your React app or other clients like Postman.

Vercel React app makes rest calls to http endpoints

Hi I have a react application that runs on vercel so in https and the backend is on a vps, the backend has no https and when I run the rest calls from frontend to backend I have the following error how do I solve it?
Error:
xhr.js:220 Mixed Content: The page at 'https://vmgroupfrontend.vercel.app/#/login' was loaded over HTTPS, but requested an insecure
XMLHttpRequest endpoint 'http://myendpoint.org:3001/user/login'.
This request has been blocked; the content must be served over HTTPS.

CORS policy is allowed in app.py but still not working

The front-end app is built on ReactJs and development server is running on http://localhost:3000. The back-end API is built with Flask 2.0.2 and is running on http://localhost:5000
In app.py file, the CORS has been allowed as mentioned in the documentation like:
CORS(app, resources={r"*": {"origins": "*"}})
When I try to submit the login form I still get the following error:
if you Enables CORS on your backend api , it should work.
I don't think this is an issue with your react frontend application.
cors is a security measure put in by browsers.
You could bypass the Cross-Origin-Policy with chrome extension but it's not advisable -
Try this on your backend API:
Ensure you have flask cors installed
create a configuration dictionary like this
api_v1_cors_config = {
"origins": ["http://localhost:5000"]
}
You can then set a global cors for your app like this
CORS(app, resources={"/api/v1/*": api_v1_cors_config})
// this would allow all methods, origins

CORS errors when react gets redirected to login page

I am getting the following error messages:
-Fetch API cannot load http://localhost:8080/oauth2/authorization/google due to access control checks
-Failed to load resource: Cross-origin redirection to https://accounts.google... denied by CORS policy: Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin
I made a Kotlin-SpringBoot API and I'm in the process of developing a front end in React-TypeScript.
I used SwaggerCodegen to import the functions to interact with my API with OpenAPI docs.
I want my users to be authenticated with google OAUTH, so I decided to use Spring Security to make all my endpoints need authentication. I did it using this class:
#Configuration
class SecurityConfig : WebSecurityConfigurerAdapter() {
override fun configure(http: HttpSecurity) {
http
.antMatcher("/**").authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
}
}
Now, the api is in port 8080 and the frontend is on 3000
So if I access localhost:8080/restricted I get prompted to login and it works as expected.
But if my frontend on localhost:3000 tries to retrieve any data from the API I thought It'd just redirect me anyways, but I get the CORS error above.
I have looked everywhere and just want to know if my approach is conceptually wrong or how I can authorize this type of redirecting (or if I even should).
Thanks for any help!

React App + Spring Boot - JWT auth token inside a cookie is not set in Chrome

I'm trying to configure Spring Boot to set-cookie containing JWT auth token following a sign-in request from my react app, and then the expectation is that the browser will automatically set this cookie to all requests as specified by the cookie path. The behaviour is ok on my friend's environment - same code, Chrome browser, different machine. I tried clearing node_modules, mvn clean install, also tried different browsers Chrome and FireFox, no success.
Here is the all the relevant code (let me know if I'm missing something else important)
React is running on localhost:3000
Spring Boot is running on localhost:8080
There is a proxy in the package.json
"proxy": "http://localhost:8080",
To test the auth flow we are issuing a sign-in request from the sign-in form (react), the request is successfully proxied to port 8080 and the response from the server is successfully returning the JWT token as part of an auth cookie. The cookie is specified to the /api path. Network request as seen in Chrome below:
Immediately after the login, the react app is issuing a second HTTP request to the back-end, but a break-point on the server shows no cookies are passed from the browser as part of this request. The request is to http://localhost:3000/api/user.
In the front-end we are using fetch to make that request and it looks like this:
fetch("/api/user, {
credentials: "same-origin"
})
Just for additional context this is how we return the original cookie from the server, upon a successful login:
#PostMapping("/signin")
public ResponseEntity signin(#RequestBody AuthenticationRequest data, HttpServletResponse response) {
try {
String username = data.getUsername();
Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, data.getPassword()));
User user = (User) authentication.getPrincipal();
String token = jwtTokenProvider.createToken(user);
final Cookie cookie = new Cookie("auth", token);
cookie.setSecure(!environment.acceptsProfiles(Profiles.of("dev")));
cookie.setHttpOnly(true);
cookie.setMaxAge(Integer.MAX_VALUE);
cookie.setPath("/api");
response.addCookie(cookie);
return ok(buildUserResponseObject(user));
} catch (AuthenticationException e) {
throw new BadCredentialsException("Invalid username/password supplied");
}
}
Is there anything wrong with our approach? What could be preventing my browser from passing on the auth cookie?
Oh this is embarrassing...
The issue was this line
cookie.setSecure(!environment.acceptsProfiles(Profiles.of("dev")));
!environment.acceptsProfiles(Profiles.of("dev")) was evaluating to true and it was causing the cookie to be only passed if the connection is secure, which it wasn't because it was localhost. Mystery solved.

Resources