Bootiful Development with Spring Boot and React
This post shows how you can build a UI and an API as separate apps. You’ll learn how to create REST endpoints with Spring MVC, configure Spring Boot to allow CORS, and create a React app to display its data. Finally, you’ll lock it down with Okta.
Eugene
Instead of CORS resolution I would recommend using proxy as described here https://github.com/facebook…
Matt Raible
Thanks for the link Eugene! I prefer to keep my apps separate and deploy them separately, which requires CORS. If you use a proxy, it’ll work in development, but not in production. Or you’ll have to package your client with your server, which I know a lot of people prefer as well. To each their own!
Eugene
True. If they run separately, then all good with CORS.
Donato Baonguis
Hi Matt,
This is really good and I was able to make it work (after about 8 hours, i struggled a bit lol) This is exactly the stack that I wanted to use to develop my project (SpringBoot + React) and OKTA is a nice addition. However, there’s so much into this that its so hard for me to understand why I only have to have one application (SPA) in OKTA and I can also use it’s key in the application.properties file in Springboot. Springboot app is not a SPA. So I am so confused. OAuth2 is already a beast and I watch Nate’s (of OKTA) video on youtube about OAuth2 and it was helpful to understand. But now, your implementation does not match what I learned from that. I don’t think you have a wrong implementation, I think its more of me not understanding how you made it work… LOL. I wish I could understand this more. Thanks for this tutorial!
Matt Raible
Hello Donato! I’m glad to hear you were able to make everything work. You can package an app like this as two separate apps (like this post shows), or combine them into one. I don’t have a blog post about how to do that, but I hope to write one soon!
I like having two separate apps because it allows you to develop your SPA independently and even point it to different environments (test, prod) to reproduce bugs found.
Check out JHipster if you’d like to see how to package an app with Angular and Spring Boot in the same artifact. JHipster allows you to use Okta with the authentication code flow you saw in Nate’s talk. I helped write the code, so let me know if you have any questions on how it’s implemented.
Adrian Skoczylas
Hi,
I have a problem. After adding interfaces i’m getting error: (6,11): interface name must start with a capitalized I
Matt Raible
Hello Adrian,
My guess is this happens because tslint rules changed in Create React App since I wrote this tutorial. Please make sure you’re using v1.5.2.
npm install -g create-react-app@1.5.2
You could also change your tslint.json
to match the one I used. Or, you could simply prefix your interfaces with “I”.
In Java-land, an “I” prefix on interfaces is an old pattern that’s no longer used. It’s funny to see the React folks bringing it back. ![:wink: :wink:](https://emoji.discourse-cdn.com/twitter/wink.png?v=10)
Rohit Patil
Thanks for such a wonderful tutorial !!
I tried to implement this and it’s working fine. But, may I know how to get user details from OKTA here ?
For example, user name, first name,… and other things that I would configure in OKTA to provide me.
Matt Raible
You’re welcome - I’m glad you like it! There’s a Profile.jsx in our React samples that shows there should be a this.state.userinfo
object available to you - provided by withAuth
.
Matt Raible
It’s funny you should ask, I just wrote some code to show how to do this today! You should be able to get all the info you need from java.security.Principal
if you’re using Spring Security.
package com.okta.developer.holdingsapi;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
import java.util.Map;
@RestController
public class UserController {
@GetMapping("/api/user")
@SuppressWarnings(“unchecked”)
public ResponseEntity getUser(Principal principal) {
if (principal == null) {
return new ResponseEntity<>("", HttpStatus.OK);
}
if (principal instanceof OAuth2Authentication) {
OAuth2Authentication authentication = (OAuth2Authentication) principal;
Map<string, object=""> details = (Map<string, object="">) authentication.getUserAuthentication().getDetails();
return ResponseEntity.ok().body(details);
} else {
return ResponseEntity.ok().body(principal.getName());
}
}
@PostMapping("/api/logout")
public void logout(HttpServletRequest request) {
request.getSession(false).invalidate();
}
}
This returns data like the following:
// 20180611212036
// http://localhost:8080/api/user
{
“sub”: “00ua49y18m0OpB30W0h7”,
“name”: “Okta Demo”,
“locale”: “en-US”,
“email”: “matt.raible@okta.com”,
“preferred_username”: “demo@okta.com”,
“given_name”: “Okta”,
“family_name”: “Demo”,
“zoneinfo”: “America/Los_Angeles”,
“updated_at”: 1526928068,
“email_verified”: true,
“roles”: [
“Everyone”,
“ROLE_USER”
],
“groups”: [
“Everyone”,
“ROLE_USER”
]
}
You can also use our Okta Java SDK if you need user management and group management.
Alejandro Bachi
Matt, you could also set up an HTTP Web Server in the same origin of the front end, that will redirect to the backend. This could useful when using security because the browser won’t make the extra pre-flight request.
Matt Raible
Yep, that’s a good option too. I’m working on a blog post that shows you how to package everything in the same artifact. There’s lots of options.
Rohit Patil
Thanks again ![:slight_smile: :slight_smile:](https://emoji.discourse-cdn.com/twitter/slight_smile.png?v=10)
As per the response that we get it seems like some predefined values are getting returned.
Can we customize this? Can we add some additional fields as well.
I am asking this question because previously we were using Web application using SAML and we configured fields that comes as assertion to the java end. Using SamlCredential class we got all those fields. For eg. We added user’s parent company id, etc…
Now, we are using this in Okta as a SPA, and I don’t see where to add those details that should come in response additionally to the values that you get in response.
Kindly suggest.
Matt Raible
Yes, you can add additional claims to your ID and Access tokens. In the example above, both “groups” and “roles” are claims I added. The Okta Java SDK will give you access to all attributes in the user’s profile as well. It’s super easy to use if you’re already using Spring. Just inject com.okta.sdk.client.Client
and call client.getUser(id/sub or email)
.
Antoine Hulin
Hello,
Since new rules with TSLint , empty interfaces are not allowed… any backup plans?
Matt Raible
Yeah, I saw that. The easiest solution for now is to copy the tslint.json that I used and put it in your project. There’s a lot of rules in Create React App that I don’t agree with now. Empty interfaces is probably OK, but prefixing interfaces with “I” and ordering imports alphabetically seems silly. I hope to update this post soon, and will figure out how to turn off the rules I don’t like.
Matt Raible
Hello Antoine: I’ve updated the blog post to show you how to adjust tslint.json
to allow empty interfaces.
Matt Raible
Hello Adrian: I’ve updated the blog post to show you how to adjust tslint.json
to turn off prefixes for interfaces.