node.jsspring-bootspring-mvcjava-8angular-cli-v8

angular route static paths access urls directly without permission


I am trying to fix a bug in a web application using java 8, spring boot, Spring MVC and front end with angular cli. When the user logins the application and is created a menu considering the user profile permission with java, but the application uses angular router with static paths, so if the user rewrite the URL he can access anything even without permissions.

const routes: Routes = [
  {
      path: '',
      component: WebservicesComponent,
      children: [
        { path: 'perfis', loadChildren: './wsperfis/wsperfis.module#WsperfisModule', },
        { path: 'acessos', loadChildren: './wsacessos/wsacessos.module#WsacessosModule', },
        { path: 'novoAcesso', loadChildren: './novo-acesso/novo-acesso.module#NovoAcessoModule', },
        { path: 'servicos', loadChildren: './wsservicos/wsservicos.module#WsservicosModule' },
        { path: 'novoperfil', loadChildren: './wsnovoperfil/wsnovoperfil.module#WsnovoperfilModule' }
      ]
  }
];


@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class WebservicesRoutingModule {
}

@CrossOrigin
    @RequestMapping("/menu")
    public List<Object> menu(@RequestParam(value = "idPerfil") int idPerfil) {

        List<Menu> menus = menuService.getMenus(idPerfil);

        List<Object> menu = new ArrayList<Object>();

        Map<String, Object> mapMenu = new HashMap<String, Object>();
        Map<String, String> mapSubMenu = new HashMap<String, String>();
        List<Object> listMapSubMenu = new ArrayList<Object>();

        for (Menu menuItem : menus) {

            if (!mapMenu.containsValue(menuItem.getPaiPrompt())) {

                mapMenu = new HashMap<String, Object>();
                listMapSubMenu = new ArrayList<Object>();

                mapMenu.put(LABEL, menuItem.getPaiPrompt());
                mapMenu.put(URL, menuItem.getPaiUrl());
                mapMenu.put(ICON, menuItem.getPaiIcon());

                for (Menu submenu : menus) {

                    if (menuItem.getPaiPrompt().equals(submenu.getPaiPrompt())) {
                        mapSubMenu = new HashMap<String, String>();
                        mapSubMenu.put(LABEL, submenu.getFilhoPrompt());
                        mapSubMenu.put(URL, submenu.getFilhoUrl());
                        mapSubMenu.put(ICON, submenu.getFilhoIcon());
                        listMapSubMenu.add(mapSubMenu);
                    }

                }
                mapMenu.put(ITEMS, listMapSubMenu);
                menu.add(mapMenu);
            }

        }

        return menu;
    }

Solution

  • You should add a validation on your front and backend, for example, when path changes in frontend and component is mounted it checks for session sending its path id, backend compare that versus asigned menu, all this before making any other api call.

    Another solution more complex (and secure) is adding the validation on api itself, by checking menus or user profiles, this way even if user access a page he should not (its mapped in js), he won't access unauthorized apis.