Before calling React.render() be sure to initialize/configure the SDK.
ReactStormpath.init();If you want to configure it, simply pass an object with the configuration you want to use.
ReactStormpath.init({
// Optional: Set if you want to use your own Flux dispatcher.
dispatcher: instanceOfYourOwnFluxDispatcher,
// Optional: Set if you want to to use another API endpoint.
// Values shown below are the defaults.
endpoints: {
baseUri: null,
me: '/me',
login: '/login',
register: '/register',
verifyEmail: '/verify',
forgotPassword: '/forgot',
changePassword: '/change',
logout: '/logout'
}
});Router that extends ReactRouter with Stormpath routing functionality.
<Router history={history}>
<Route path='/' component={App}>
<IndexRoute component={IndexPage} />
</Route>
</Router>Route to redirect to when logging out.
<HomeRoute path='/' component={MainPage} />Wrap the HomeRoute in an AuthenticatedRoute to specify the route you want to redirect to when you register or login.
<AuthenticatedRoute>
<HomeRoute path='/profile' component={ProfilePage} />
</AuthenticatedRoute>Route that when used, requires that a session is established before continuing. Else redirects the user to the LoginRoute path.
<AuthenticatedRoute path='/profile' component={ProfilePage} />Specify the option inGroup to only allow users in a certain group to access the path.
<AuthenticatedRoute path='/admin' inGroup="administrator" component={AdminPage} />If you want to specify more complex groups, please see section Group Expressions.
Important: In order to use the inGroup option, you must expand the groups resource for the /me endpoint.
Route that marks a specific route as the place to go in order to login.
<LoginRoute path='/login' component={LoginPage} />Route that when accessed, ends the user session.
<LogoutRoute path='/logout' />Specify redirectTo to set the path to redirect to after logging out. If this isn't specified, then it falls back to the unauthenticated HomeRoute path.
<LogoutRoute redirectTo='/pathToRedirectTo' />If you want to know if the user is authenticated or not, include the authenticated context.
class AuthenticatedExample extends React.Component {
static contextTypes = {
authenticated: React.PropTypes.bool
};
render() {
return (
<p>
{ this.context.authenticated ?
'Authenticated!' :
'Not authenticated!'
}
</p>
);
}
}If you want to retrieve the user, then include the user context. The value will be undefined if the user is not authenticated.
class UserExample extends React.Component {
static contextTypes = {
user: React.PropTypes.object
};
render() {
return (
<p>
Hello {this.context.user.givenName}!
</p>
);
}
}Renders any child components if there is an established user session.
<Authenticated>
You are authenticated!
</Authenticated>Specify the option inGroup to only show child components when a user is in a certain group.
<Authenticated inGroup="administrator">
You are authenticated as an administrator!
</Authenticated>If you want to specify more complex groups, please see section Group Expressions.
Important: In order to use the inGroup option, you must expand the groups resource for the /me endpoint.
Renders any child components if there isn't an established user session.
<NotAuthenticated>
You are not authenticated!
</NotAuthenticated>Specify the option inGroup to only show child components when a user isn't in a certain group.
<NotAuthenticated inGroup="administrator">
You are authenticated as an administrator!
</NotAuthenticated>If you want to specify more complex groups, please see section Group Expressions.
Important: In order to use the inGroup option, you must expand the groups resource for the /me endpoint.
Renders a username and password login form.
<LoginForm />Specify redirectTo to set the path to redirect to after logging in. If this isn't specified, then it falls back to the authenticated HomeRoute path.
<LoginForm redirectTo='/pathToRedirectTo' />Specify hideSocial to hide the ability to sign in with a social provider.
<LoginForm hideSocial={true} />Customize the form by providing your own markup.
<LoginForm>
<p>
<label htmlFor="username">Username or Email</label><br />
<input id="username" type="text" name="username" />
</p>
<p>
<label htmlFor="password">Password</label><br />
<input id="password" type="password" name="password" />
</p>
<p spIf="form.error">
<strong>Error:</strong><br />
<span spBind="form.errorMessage" />
</p>
<p>
<input type="submit" value="Login" />
</p>
</LoginForm>If you want to handle the form onSubmit() event, then simply provide a callback for it.
class LoginPage extends React.Component {
onFormSubmit(e, next) {
// e.data will contain the data mapped from your form.
console.log("Form submitted", e.data);
// To return an error message, call next() as:
// next(new Error('Something in the form is wrong.'));
// Or if you want to change the data being sent, call it as:
// next(null, { myNewData: '123' });
// If you call next without any arguments,
// it will simply proceed processing the form.
next();
}
render() {
return <LoginForm onSubmit={this.onFormSubmit.bind(this)} />;
}
}Renders a registration form.
<RegistrationForm />Specify redirectTo to set the path to redirect to after registering. If this isn't specified, then it falls back to the authenticated HomeRoute path.
<RegistrationForm redirectTo='/pathToRedirectTo' />Specify hideSocial to hide the ability to register with a social provider.
<RegistrationForm hideSocial={true} />Customize the form by providing your own markup.
<RegistrationForm>
<div spIf="account.created">
<span spIf="!account.enabled">To verify your account, click the verification link that we sent to your email then proceed to login by going to <LoginLink />.</span>
</div>
<div spIf="!account.created">
<p>
<label htmlFor="firstName">First name</label><br />
<input id="firstName" type="text" name="givenName" />
</p>
<p>
<label htmlFor="lastName">Last name</label><br />
<input id="lastName" type="text" name="surname" />
</p>
<p>
<label htmlFor="email">Email</label><br />
<input id="email" type="text" name="email" />
</p>
<p>
<label htmlFor="password">Password</label><br />
<input id="password" type="password" name="password" />
</p>
<p spIf="form.error">
<strong>Error:</strong><br />
<span spBind="form.errorMessage" />
</p>
<p>
<input type="submit" value="Register" />
</p>
</div>
</RegistrationForm>If you want to handle the form onSubmit() event, then simply provide a callback for it.
class RegistrationPage extends React.Component {
onFormSubmit(e, next) {
// e.data will contain the data mapped from your form.
console.log("Form submitted", e.data);
// To return an error message, call next() as:
// next(new Error('Something in the form is wrong.'));
// Or if you want to change the data being sent, call it as:
// next(null, { myNewData: '123' });
// If you call next without any arguments,
// it will simply proceed processing the form.
next();
}
render() {
return <RegistrationForm onSubmit={this.onFormSubmit.bind(this)} />;
}
}Renders a password reset form.
<ResetPasswordForm />Customize the form by providing your own markup.
<ResetPasswordForm>
<div spIf="form.sent">
<p>We have sent a password reset link to the email address of the account that you specified.<br />
Please check your email for this message, then click on the link.</p>
</div>
<div spIf="!form.sent">
<p>
<label htmlFor="email">Email</label><br />
<input id="email" type="text" name="email" />
</p>
<p spIf="form.error">
<strong>Error:</strong><br />
<span spBind="form.errorMessage" />
</p>
<p>
<input type="submit" value="Request Password reset" />
</p>
</div>
</ResetPasswordForm>If you want to handle the form onSubmit() event, then simply provide a callback for it.
class ResetPasswordPage extends React.Component {
onFormSubmit(e, next) {
// e.data will contain the data mapped from your form.
console.log("Form submitted", e.data);
// To return an error message, call next() as:
// next(new Error('Something in the form is wrong.'));
// Or if you want to change the data being sent, call it as:
// next(null, { myNewData: '123' });
// If you call next without any arguments,
// it will simply proceed processing the form.
next();
}
render() {
return <ResetPasswordForm onSubmit={this.onFormSubmit.bind(this)} />;
}
}Renders a change password form. The parameter spToken is required in order for the token to be validated.
<ChangePasswordForm spToken={this.props.location.query.sptoken} />After the user has changed their password, the default form will show a link the user can click on that takes them to the login page. If you want to automatcially log the user in after they've changed their password, then add:
<ChangePasswordForm spToken={this.props.location.query.sptoken} autoLogin={true} />Customize the form by providing your own markup.
<ChangePasswordForm spToken={requiredSpToken}>
<div spIf="form.sent">
<p>Your new password has been set. Please <LoginLink />.</p>
</div>
<div spIf="!form.sent">
<p>
<label htmlFor="password">Password</label><br />
<input id="password" type="password" name="password" required />
</p>
<p>
<label htmlFor="confirmPassword">Password (again)</label><br />
<input id="confirmPassword" type="password" name="confirmPassword" required />
</p>
<p spIf="form.error">
<strong>Error:</strong><br />
<span spBind="form.errorMessage" />
</p>
<p>
<input type="submit" value="Change Password" />
</p>
</div>
</ChangePasswordForm>If you want to handle the form onSubmit() event, then simply provide a callback for it.
class ChangePasswordPage extends React.Component {
onFormSubmit(e, next) {
// e.data will contain the data mapped from your form.
console.log("Form submitted", e.data);
// To return an error message, call next() as:
// next(new Error('Something in the form is wrong.'));
// Or if you want to change the data being sent, call it as:
// next(null, { myNewData: '123' });
// If you call next without any arguments,
// it will simply proceed processing the form.
next();
}
render() {
return <ChangePasswordForm spToken={requiredSpToken} onSubmit={this.onFormSubmit.bind(this)} />;
}
}Renders a form that allows you to update the user profile.
<UserProfileForm />Important: In order to update user data, you need to provide your own POST API for the me endpoint.
Using the express-stormpath library, simply expose a new endpoint as shown below.
app.post('/me', bodyParser.json(), stormpath.loginRequired, function (req, res) {
function writeError(message) {
res.status(400);
res.json({ message: message, status: 400 });
res.end();
}
function saveAccount() {
req.user.givenName = req.body.givenName;
req.user.surname = req.body.surname;
req.user.email = req.body.email;
req.user.save(function (err) {
if (err) {
return writeError(err.userMessage || err.message);
}
res.end();
});
}
if (req.body.password) {
var application = req.app.get('stormpathApplication');
application.authenticateAccount({
username: req.user.username,
password: req.body.existingPassword
}, function (err) {
if (err) {
return writeError('The existing password that you entered was incorrect.');
}
req.user.password = req.body.password();
saveAccount();
});
} else {
saveAccount();
}
});Customize the form by providing your own markup.
<UserProfileForm>
<p>
<label htmlFor="givenName">First name</label><br />
<input id="givenName" type="text" name="givenName" />
</p>
<p>
<label htmlFor="surname">Last name</label><br />
<input id="email" type="text" name="surname" />
</p>
<p>
<label htmlFor="email">Email</label><br />
<input id="email" type="text" name="email" />
</p>
<p spIf="form.error">
<strong>Error:</strong><br />
<span spBind="form.errorMessage" />
</p>
<p spIf="form.successful">
Profile updated.
</p>
<p>
<input type="submit" value="Update" />
</p>
</UserProfileForm>If you want to handle the form onSubmit() event, then simply provide a callback for it.
class ProfilePage extends React.Component {
onFormSubmit(e, next) {
// e.data will contain the data mapped from your form.
console.log("Form submitted", e.data);
// To return an error message, call next() as:
// next(new Error('Something in the form is wrong.'));
// Or if you want to change the data being sent, call it as:
// next(null, { myNewData: '123' });
// If you call next without any arguments,
// it will simply proceed processing the form.
next();
}
render() {
return <UserProfileForm onSubmit={this.onFormSubmit.bind(this)} />;
}
}Renders an email verification view. The parameter spToken is required in order for the token to be validated.
<EmailVerificationView spToken={this.props.location.query.sptoken} />Renders a link that points to the LoginRoute or /login if no LoginRoute is specified.
<LoginLink />
<LoginLink><img src="wrap-something-in-a-login-link.png" /></LoginLink>Renders a link that can be used to sign in with a social provider.
<SocialLoginLink providerId='facebook' />
<SocialLoginLink providerId='facebook'>Sign in with Facebook</SocialLoginLink>Renders a link that can be used to sign in using a social provider.
<SocialLoginLink providerId='facebook' />Set specific scopes by providing the scope option.
<SocialLoginLink providerId='facebook' scope='email user_friends' />Set your own redirect URI by providing the redirectUri option. If this isn't set then it defaults to [protocol]://[host]/callbacks/[providerId].
<SocialLoginLink providerId='facebook' redirectUri='http://www.example.com/callbacks/facebook' />Renders a button that can be used to sign in with a social provider.
<SocialLoginButton providerId='facebook' />
<SocialLoginButton providerId='facebook'>Sign in with Facebook</SocialLoginButton>If you don't want the button to show an icon, then simply disable it by setting the hideIcon option.
<SocialLoginButton providerId='facebook' hideIcon={ true } />Note: The same options that are supported by the SocialLoginLink component are also supported by this.
Important: This component relies on Font Awesome in order to render icons for the various social providers. So if you want to use this button with icons, you also need to install Font Awesome on your site.
Renders a link that points to the LogoutRoute or /logout if no LogoutRoute is specified.
<LogoutLink />
<LogoutLink><img src="wrap-something-in-a-logout-link.png" /></LogoutLink>Group expressions are expressions that can be applied to components that support groups. These expressions are plain JavaScript boolean statements but with the exception that they are scoped so that the groups are global variables.
This means that you can write dynamic expressions such as:
(administrator || support) && !engineerWhich when executed would roughly translate into:
if ((administrator || support) && !engineer) {
return true;
} else {
return false;
}Note: If a group name contains a space, then that space should be replaced with a underscore. I.e. group super administrator should be super_administrator as illustrated below:
super_administrator || engineer