Previously you created a CRUD application using Spring Boot, React and Stormpath where React handled the data view and the Stormpath Spring Boot Starter set up the login and registration pages. Now you’ll see how to use Stormpath’s React SDK to create login and signup pages manually so that every view on your site is managed by you.
Re-wire Stormpath and React
The Stormpath Spring Boot Starter sets up local server endpoints such as /login
and /register
that both serve up the front-end templates (for get
requests) and receive back-end API requests (for post
and put
). You need to wire the get
endpoints to your own React-based HTML. You will use the React Router to handle each URL, and the pages themselves will call the starter post
and put
endpoints when logging in, registering etc.
Configure Spring Boot and Stormpath
Start with a clone of the repository from a follow-on tutorial (which added webpack functionality):
git clone https://github.com/stormpath/stormpath-spring-boot-webpack-example
Strip out the security configuration by removing any Stormpath-related lines from application.properties
. The file should then read
spring.data.rest.basePath=/api
Now rename the endpoints you want to override for the front-end so that your URLs don’t clash with the Spring Boot Starter.
spring.data.rest.basePath=/api stormpath.web.login.uri=/signin stormpath.web.register.uri=/signup stormpath.web.forgotPassword.uri=/lostpass
Note: see the Stormpath documentation for a full list of these settings.
Remove the Stormpath code from configure()
in Security.java
.
@Configuration public class Security extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { } }
Install the project libraries and run webpack.
npm install webpack mvn spring-boot:run
If you navigate to localhost:8080
you should see a table with some rows. This is what the user should see after they’ve logged in.
Add Security with Stormpath for Authentication
Add the Stormpath-related lines back to application.properties
.
stormpath.application.href = ... stormpath.client.apiKey.id = ... stormpath.client.apiKey.secret = ...
Note: For security reasons you should never store your Stormpath keys inside of project files. Rather, use environment variables or an apiKey.properties
file.
Add the Stormpath lines back to Security.java
but change it to allow anyone access the homepage, public files, and the URLs for the user management pages.
@Configuration public class Security extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.apply(stormpath()).and() .authorizeRequests() .antMatchers("/","/public/**","/login","/register","/forgot").permitAll(); } }
Restart and you’ll see the table header and logout button but without any table rows. You’ve allowed anyone to view the main page but there isn’t any data coming through.
If you open the network console you’ll see what is happening—an authorization failure occurred on the /api/employees
REST endpoint. You need to set up React to redirect to a login page when an authorization failure like this happens.
Create Routes in React
The Stormpath React SDK uses React Router to specify pages like login. Add these libraries to your project:
npm install --save react-stormpath react-router
Now add the following imports at the top of your app.js
entry.
import ReactStormpath, { Router, AuthenticatedRoute, LoginRoute } from 'react-stormpath'; import { Route, browserHistory } from 'react-router';
These define which React components represent the login page, etc., and which URLs require authentication. Next initialize the SDK with the following after your imports:
ReactStormpath.init({ endpoints: { login: '/signin', register: ‘/signup’, forgotPassword: ‘/lostpass’ } });
The init
accepts various settings to configure the SDK. Here the management endpoint URLs are changed to match those specified in application.properties
. Change the render command at the bottom of app.js
to the following:
ReactDOM.render(, document.getElementById('root') );
You’ve specified that the root
element must render from Router (a Stormpath component) which uses React Router’s browserHistory
plugin to manage URLs. Then AuthenticateRoute
ensures that any visits to the homepage (/
) need to be authenticated and also rendered with the MainPage
component (you’ll derive this from the previous interface). Finally the LoginRoute
makes sure that any login requirements redirect to /login
and are rendered with a component called LoginPage
(which you still need to define).
Create Pages in React
Put each page into a separate file. Inside of src
create a folder called pages
.
Pull the previous components out of app.js
and export them from MainPage.js
.
import React from 'react'; import $ from 'jquery'; import toastr from 'toastr'; var Employee = React.createClass({ getInitialState: function() { return {display: true }; }, handleDelete() { var self = this; $.ajax({ url: self.props.employee._links.self.href, type: 'DELETE', success: function(result) { self.setState({display: false}); }, error: function(xhr, ajaxOptions, thrownError) { toastr.error(xhr.responseJSON.message); } }); }, render: function() { if (this.state.display==false) return null; else return (); } }); var EmployeeTable = React.createClass({ render: function() { var rows = []; this.props.employees.forEach(function(employee) { rows.push( {this.props.employee.name} {this.props.employee.age} {this.props.employee.years} ); }); return (
Name | Age | Years | Delete |
---|
Note: the main page now includes the logout button. This simplifies index.html
, our single page app holder, significantly.
React + Spring
Now create the login page in LoginPage.js
.
import React from 'react'; import DocumentTitle from 'react-document-title'; import { LoginForm } from 'react-stormpath'; var LoginPage = React.createClass({ render() { return (); } }); export default LoginPage; Login
Here you’re using the React Document Title library which you need to install. It allows you to set the browser title whilst using React Router.
npm install --save react-document-title
Now import the pages into your app.js
entry.
import MainPage from './pages/MainPage'; import LoginPage from './pages/LoginPage';
app.js
now looks like the following.
import React from 'react'; import ReactDOM from 'react-dom'; import ReactStormpath, { Router, AuthenticatedRoute, LoginRoute } from 'react-stormpath'; import { Route, browserHistory } from 'react-router'; import 'bootstrap/dist/css/bootstrap.css'; import 'toastr/build/toastr.css'; import MainPage from './pages/MainPage'; import LoginPage from './pages/LoginPage'; ReactStormpath.init({ endpoints: { login: '/signin', register: ‘/signup’, forgotPassword: ‘/lostpass’ } }); ReactDOM.render(, document.getElementById('root') );
Reroute Through Spring Boot
React Router artificially alters the URL to /login
, /register
,etc., but all requests still come through Spring Boot (i.e. server). You need to tell Spring boot to send those requests to our SPA in case someone refreshes the browser window. Change HomeController.java
to the following.
package tutorial; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class HomeController { @RequestMapping(value = {"/","/login","/register","/forgot"}) public String index() { return "index"; } }
Start Your Site
After running Webpack and refreshing you should be sent to the login page you just created.
Once you put in correct details you’ll see the data table populated as before.
Add Signup and Password Reset
There are two other pages you should specify – registration, and the forgot password screen. The first you can add using an ordinary React Router Route.
import RegisterPage from './pages/RegisterPage'; ...
For the page itself, use the one from the React SDK example project.
import React from 'react'; import DocumentTitle from 'react-document-title'; import { RegistrationForm, LoginLink } from 'react-stormpath'; var RegisterPage = React.createClass({ render() { return (); } }); export default RegisterPage; Registration
Your account has been created.
Login Now .Your account has been created. Please check your email for a verification link.
Back to Login
Add a link to the login page to /register
.
Register
Now, when you click the link you should see a signup page.
Add Forgot Password
Lastly, the forgot password page is configured in much the same way.
import React from 'react'; import DocumentTitle from 'react-document-title'; import { ResetPasswordForm } from 'react-stormpath'; var ForgotPage = React.createClass({ render() { return (); } }); export default ForgotPage; Forgot Password
import ForgotPage from './pages/ForgotPage'; …
Learn More!
Just like that you have created your own React user management components and tied them to the Spring Boot backend. You can clone the full source code on Github. To go further, check out the Stormpath React SDK API for more details or check out this blog post on how to create custom forms with React.
The post Tutorial: Build a Spring Boot Application with React and User Authentication appeared first on Stormpath User Identity API.