# Improper Access Control
Correctly applied access control rules are key to keeping your data secure. Almost all applications need to protect sensitive data and operations, so putting careful thought into how to restrict access is important when designing a system.
Your access control strategy should cover three aspects:
* **Authentication** – correctly identifying a user when they return to the application.
* **Authorization** – deciding what actions a user should and should not be able to perform once they have been authenticated.
* **Permission Checking** – evaluating authorization at the point-in-time when a user attempts to perform an action.
## Access Control in React
Routing in JavaScript frameworks is usually done with a routing library that will update the browser URL and the page contents as the user interacts with your application. You should check whether the user has sufficient permission before permitting them access to sensitive routes. Here’s how to implement this using *Role-Based Access Control* and redirects:
=== Angular
“`typescript @NgModule({ imports: [RouterModule.forRoot([// These routes are available to all users. { path: ”, component: HomeComponent }, { path: ‘news’, component: NewsComponent }, { path: ‘login’, component: LoginComponent }, // These routes are only available to administrative users. // This is the fall-through component when the route is not recognized. ])], |
=== React
“`jsx function Routes(props) { return ( <Router> <Switch><!– These routes are available to all users. –> <Route exact path=”/”> <Home/> </Route> <Route path=”/news”> <News/> </Route> <Route exact path=”/login”> <Login/> </Route> <!– These routes are only available to administrative users. –> <AuthenticatedRoute path=”/admin/invites” role={props.role}> <Route path=”*”> </Switch> /** return <Redirect to={{ pathname: `/` }} /> |
Authorization checks on the client-side can be overridden by an attacker, however, so it is important to check whether the user has sufficient permission when you load the data for a code component or update state on the server. These authorization checks **must be performed in server-side code**. Your code should handful an authorization failure gracefully:
=== Angular
“`typescript export class AdministratorGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {}canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<true | UrlTree> { // Check whether this user is an administratoor. return isAdmin “`typescript // Whether the user is currently logged in. // The user object object encompassing the user’s name and role. Will be set // Check whether the current user is an administrator. // Get the user definition from local state, or the server (if this is the first time we are checking). return this.http.get<User>(‘/api/auth’, { export interface User { |
=== React
“`jsx class Users extends React.Component { constructor(props) { super(props)this.state = { loading : true, users : [], error : null } } async componentDidMount() { // Load a list of all users so an administrator can view them. if (response.ok && data.success) { // Set the user data in the state so we can render the page. // Shown an error message if the user list cannot be loaded – render() { let body // Render the user list returned from the server. return ( |
# Further Considerations
Access control vulnerabilities tend to occur when mistakes are made during the design phase. To avoid this, make sure you:
* Design your access control upfront and document it.
* Write unit tests to validate that only authorized users can access sensitive resources. These unit tests should cover client-side routes *and* server-side logic.
* Think like an attacker: focus on the biggest risks your organization faces and prioritize securing those.
* Record user activity in server-side logs, so you have audit trails of who did what and when.
# CWEs
* [CWE-284](https://cwe.mitre.org/data/definitions/284.html)