> Markdown version of [Role-Based Access Control](https://vaadin.com/docs/next/hilla/lit/guides/security/role-based-access). Section index: [llms.txt](https://vaadin.com/docs/next/hilla/llms.txt)

# Role-Based Access Control for Views

It’s possible to restrict access for selected Hilla views, based on roles defined for the logged-in user. This article explains how to do this.

To follow the examples here, you’ll need a Hilla application with authentication enabled. See [Authentication With Spring Security](https://vaadin.com/docs/next/hilla/lit/guides/security/spring-login.md) to set that up; that page also defines the `auth.ts` helpers and the `UserInfo` bean that the examples here build on.

## <a id="define-roles-with-spring-security"></a>Define Roles with Spring Security

Roles are a set of string attributes representing the authorities that are assigned to a user. In Spring Security, the user details used for authentication also specify roles.

Typically, roles are defined in authority strings prefixed with `ROLE_`. After successful authentication, these are accessible via the `GrantedAuthority` objects returned by `Authentication.getAuthorities()`. See the [Authentication With Spring Security](https://vaadin.com/docs/next/hilla/lit/guides/security/spring-login.md) page for examples of configuration.

## <a id="using-roles-in-typescript"></a>Using Roles in TypeScript

A convenient way to use roles for access control in TypeScript views is to add a browser-callable service that gets user information, including roles, from Java during authentication. The `UserInfo` bean defined in [Authentication With Spring Security](https://vaadin.com/docs/next/hilla/lit/guides/security/spring-login.md#login-view) already carries the authorities of the logged-in user, so all that’s needed is a service method that returns it to the client:

`UserInfoService.java`

```java
@BrowserCallable
public class UserInfoService {

    @PermitAll
    @Nonnull
    public UserInfo getUserInfo() {
        Authentication auth = SecurityContextHolder.getContext()
                .getAuthentication();

        final List<String> authorities = auth.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority).toList();

        return new UserInfo(auth.getName(), authorities);
    }

}
```

The `auth.ts` helpers from the same page store that user information on login, and provide the `isUserInRole()` helper that the access checks below build on:

`auth.ts`

`auth.ts`

```typescript
export function isUserInRole(role: string) {
  if (!authentication) {
    return false;
  }

  return authentication.user.authorities.includes(`ROLE_${role}`);
}
```

## <a id="routes-with-access-control"></a>Routes with Access Control

To enable allowed roles to be specified on the view routes, define an extended type `ViewRoute`, that has a `rolesAllowed` string, like so:

`routes.ts`

`routes.ts`

```typescript
export type ViewRoute = Route & {
  title?: string;
  children?: ViewRoute[];
  rolesAllowed?: string[];
};
```

Add a method to check access for the given route by iterating `rolesAllowed`, using `isUserInRole()`, as follows:

`routes.ts`

`routes.ts`

```typescript
export function isAuthorizedViewRoute(route: ViewRoute) {
  if (route.rolesAllowed) {
    return route.rolesAllowed.some((role) => isUserInRole(role));
  }

  return true;
}
```

Then use the method added in the route action to redirect on unauthorized access like this:

`routes.ts`

`routes.ts`

```typescript
export const routes: ViewRoute[] = [
  {
    path: 'protected',
    component: 'protected-view',
    title: 'Protected',
    rolesAllowed: ['ADMIN'],
    action: async (context, commands: Commands) => {
      const route = context.route as ViewRoute;
      if (!isAuthorizedViewRoute(route)) {
        return commands.prevent();
      }
      await import('./protected-view');
      return undefined;
    },
  },
];
```

## <a id="hiding-unauthorized-menu-items"></a>Hiding Unauthorized Menu Items

Filter the route list using the `isAuthorizedViewRoute()` helper defined earlier. Then use the filtered list of routes as menu items:

`main-view.ts`

`main-view.ts`

```typescript
private get menuRoutes() {
    return routes.filter((route) => route.title).filter(isAuthorizedViewRoute);
  }
```
