react-if-auth v1.0.15
React-if-security
As a grails developer I am used to taglibs (serverside) like:
<sec:access expression="hasRole('ADMIN')">
Rendered content on admin access.
</sec:access>
I thought it would be nice to have this on react as well. This library allows you to do this:
<Access expression={(sec)=> sec.hasRole('ADMIN')}>
<Then><span>Rendered on authorized</span></Then>
<Else><span>Rendered on unauthorized</span></Else>
</Access>
This library is a composition of react-if https://github.com/romac/react-if.
Installation
yarn add react-if-auth
Configuration
First create a configuration:
import AuthProvider,{configureAccessDecisionManager} from 'react-if-auth';
let accessDecisionManager = configureAccessDecisionManager({
authLookup: ()=> ({username:'admin',roles:['ROLE_ADMIN']})
});
Secondly add the AuthProvider to your app and pass in the accessDecisionManager:
<AuthProvider accessDecisionManager={accessDecisionManager}>
<App/>
</AuthProvider>
Redux and redux-router
This module integrates with redux-auth-wrapper (https://github.com/mjrussell/redux-auth-wrapper), simple add it to your dependencies:
yarn add redux-auth-wrapper
Now you can use react-if-auth Guards. A Guard is a UserAuthWrapper, but uses the accessDecisionManager to decide to allow access. To add a Guard to a route, first import them:
import Guard,{ chainGuards } from 'react-if-auth/Guard'
Then declare them on your routes:
export const UserIsAuthenticated = Guard({
expression: (sec) => sec.isAuthenticated(),
redirectAction: routerActions.replace,
wrapperDisplayName: 'UserIsAuthenticated'
})
export const UserIsAdmin = chainGuards(UserIsAuthenticated,Guard({
expression: (sec) => sec.hasRole('ADMIN'),
redirectAction: routerActions.replace,
failureRedirectPath: '/',
wrapperDisplayName: 'UserIsAdmin',
allowRedirectBack: false
}));
<Route path="foo" component={UserIsAuthenticated(Foo)}/>
<Route path="admin" component={UserIsAdmin(Admin)}/>
Please see the basic example for a complete example.
Available component:
Access
Access requires to add a expression function which receives a sec object which allows a subset of springsecurity spel expressions: https://docs.spring.io/spring-security/site/docs/4.0.x/reference/htmlsingle/#el-access Currently implemented:
- hasRole(role); without ROLE_ prefix. This is automatically appended. AuthConfig can be configured with defaultRolePrefix.
- hasAnyRole(roles); roles array
- hasAuthority(authority); like hasRole(), but with ROLE_
- hasAnyAuthority(authorities);
- permitAll(); always resolves to true
- denyAll(); always resolves to false
- isAnonymous(); if anonymous access is configured in authConfig this resolves to true.
- isRememberMe(); requires a rememberResolver setup in authConfig.
- isAuthenticated(); Returns true if the user is not anonymous
- isFullyAuthenticated(); Returns true if the user is not an anonymous or a remember-me user
<Access expression={(sec)=>sec.hasRole('ADMIN')}>
<When></When>
<Else></Else>
</Access>
IfNotGranted
<IfNotGranted roles={['ROLE_ADMIN']}>
<When></When>
<Else></Else>
</IfNotGranted>
Username
<Username/>
Authentication
The authentication that is resolved by authLookup that's supplied to the accessDecisionManager requires, by default, to look like (default JWT response of grails-spring-security-rest):
{
username:'Dennie de Lange',
roles:['ROLE_ADMIN','ROLE_USER']
}
But the accessDecisionManager allows you to override how everything is resolved. The defaults are:
const NO_ROLES = [];
const DEFAULT_ROLE_NAME_PREFIX = 'ROLE_';
const ANONYMOUS_AUTHENTICATION = {
username: ANONYMOUS,
roles: NO_ROLES
};
const defaults = {
principalResolver:auth => auth,
rolesResolver: auth => auth && auth.roles ? auth.roles : NO_ROLES,
usernameResolver: auth => auth ? auth.username : null,
rememberMeResolver: auth => auth? auth.remembered || false : false,
roleNameResolver: (role,prefix) => role.startsWith(prefix)? role: prefix+role,
isAuthenticatedResolver: (authentication) => !isEmpty(authentication),
defaultRolePrefix: DEFAULT_ROLE_NAME_PREFIX,
anonymous: ANONYMOUS_AUTHENTICATION,
};