Модель данных, которая состоит из сопоставления ролей и привилегий, является достаточно гибкой и подходит для большинства целей.
Затем вы назначаете роли пользователям (концепция, по сути, та же, что и у групп) ... у пользователя может быть несколько ролей, и его роль (и) определяет привилегии, которые они имеют.
В коде вы проверяете (через свои роли), что пользователь обладает необходимой привилегией для выполнения функции.
Аутентификация является отдельной, это просто проверка того, кто пользователь, а не то, что он может сделать. Обычно вы должны поддерживать это разделение (хотя существуют схемы, разработанные таким образом, чтобы они заботились только о том, что может сделать пользователь, а не о том, кто они).
В вашем проекте вы можете визуализировать систему контроля доступа в виде матрицы (роли для привилегий).
Я бы также остановился на ответе «не хранить пароли» - вообще не создавайте собственную схему аутентификации. Вы, вероятно, ошибетесь. Повторно используйте тот, который доказан.