# Authentication Bypass
All sensitive actions on your website should require the user to be *authenticated* (i.e. to have identified who they are) and to be *authorized* (i.e. to have sufficient permissions to perform that action). If web routes fail to check the user identity, attackers will be able to access sensitive resources.
JavaScript frameworks typically uses a routing library that updates the browser URL and the page contents in response to user actions. You should check whether the user has been authenticated before permitting them access to sensitive routes. Here’s some examples.
=== Angular
Routing in Angular is usually done with the `AppRoutingModule`:
“`typescript @NgModule({ imports: [RouterModule.forRoot([// These paths are available to all users. { path: ”, component: HomeComponent }, { path: ‘features’, component: FeaturesComponent }, { path: ‘login’, component: LoginComponent }, // These routes are only available to users after logging in. // This is the fall-through component when the route is not recognized. ])], |
=== React
Routing in React is usually done with the `react-router` library:
“`jsx function Routes(props) { return ( <Router> <Switch><!– These routes are publicly available. –> <Route path=”/login”> <Login/> </Route> <Route path=”/news”> <News/> </Route> <Route path=”/about”> <About/> </Route> <!– These routes are only available to authenticated user. –> <AuthenticatedRoute path=”/profile” loggedIn={props.loggedIn}> <Route path=”*”> </Switch> /** return <Redirect to={{ pathname: `/login` }} /> |
Authorization checks on the client-side can be overridden by an attacker, however, so it is important to check whether
the user is logged in when you load the data into your application. These authorization checks **must be performed in
server-side code**, and your client-side code should handful an authentication failure gracefully:
=== Angular
“`typescript export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {}canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<true | UrlTree> { // Check the user is logged in, redirect them to the login screen if they are not. return true “`typescript // Whether the user is currently logged in. // The user object. // Check whether the user is logged in. // 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 Feed extends React.Component { constructor(props) { super(props)this.state = { loading : true, posts : [], error : null } } async componentDidMount() { // Load the data for this component. if (response.ok && data.success) { // Set the data in the component state. // Shown an error message if the feed cannot be loaded – for instance, render() { let body return ( |
## Further Considerations
Authentication bypass 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 unauthenticated users cannot 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-288](https://cwe.mitre.org/data/definitions/288.html)