Add users roles in Meanjs - roles

Recently I began to use MeanJs, it's pretty amazing but I don't understand some stuff.
I need to create a simple user management for my backend.
From official blog they say:
New usability features:
Added roles to the User model - the defaults
are ‘user’ and ‘admin’, you can add and remove them as needed.
After a search I found some examples but all of these about meanio, not meanjs, there are a package MEAN-ADMIN in meanio that does it for us but in meanjs I not found.
Someone know the best way to implement a user management? some example?
Thanks guys.

The meanjs generator comes with some basic user roles built in. The roles is an array on the user model.
roles: {
type: [{
type: String,
enum: ['user', 'admin']
}],
default: ['user']
},
To add a user with the role admin just attach it to the user object before saving.
user.roles = ['admin'];
If you want to use roles apart from admin and user you need to add then to the type enum.

Related

Handle one user in multiple "accounts" with AWS Cognito?

We have a use-case with using AWS Amplify and Cognito for user authentication where a user will be given certain roles for authorization, e.g. "create object", "delete object", etc.
Now we have a new requirement where a user should be able to belong to multiple organizations.
This means that the user will have to have the option of belonging to different roles in different organizations, e.g. being able to delete in one organization but not in the other (being logged in with the same account/e-mail).
As there is a variable number of organizations creating groups or roles per organization is not an option (as there would potentially be millions of groups).
Can this be solved using Cognito at all or would a custom coded solution be preferred and only use Cognito for the authentication?
I proposed a doable solution to this requirements in https://github.com/aws-amplify/amplify-cli/issues/630. And it is working in my app.
Yes, as there could be so many organizations, it is not feasible to use a Cognito group to represent an organization.
The idea of my solution is to have 3 custom models: User, Organization, and Membership. This allows many-to-many relationships between users and organizations: A user can belong to multiple organizations, and an organization can employ multiple users.
User could contains its own info. You could also let a user has the same id as in cognito such that you can align a cognito user with a User stored in DynamoDB.
Organization could contains its own info.
Membership is the critical bridge as it connects to both ends (user and organization) and you can encode role info here.
See many-to-many section to understand how does Membership work in AWS Amplify GraphQL Transform.
The schema.graphql looks like:
type User #model {
id: ID!
organizations: [Membership] #connection(name: "Membership_User")
}
type Organization #model {
id: ID!
users: [Membership] #connection(name: "Membership_Organization")
}
type Membership #model {
id: ID!
user: User! #connection(name: "Membership_User")
organization: Organization! #connection(name: "Membership_Organization")
role: Role!
}
type Role {
canCreate: Boolean!
canDelete: Boolean!
}
In my github issue, think of Project as your Organization, and the rest are almost the same.

Wolkenkit: ACLs for authorization and user roles

I am trying to understand on how to extend the wolkenkit auth layer.
Say i want users with different roles: normal, moderator and admin.
normal users can see and modify their own content, but aren't allowed to modify content from other users.
moderator users are allowed to modify all entries, but don't have permission to delete anything than their own content.
admin users can modify and delete everything.
There are also unauthenticated guest users who can read everything but modify nothing.
Reading the docs for Write model: Configuring authorization i can model the guest/normal use case by writing something along the lines of:
const initialState = {
isAuthorized: {
commands: {
issue: { forAuthenticated: false, forPublic: false }
},
events: {
issued: { forAuthenticated: true, forPublic: true }
}
}
};
For my requirements i would need additional roles defined in this object. Something like { forModerator: true, forAdmin: true }.
There is also Granting access from a command to change permissions at runtime, but i am not sure if that would work. Even if it does, that feels quite hacky.
Is this somehow possible?
Disclaimer: I am one of the developers of wolkenkit.
To cut a long story short: No, right now unfortunately this is not possible, but this feature is on our roadmap. At least today, I can't tell you when this will be available.
Your best option would be to do it on your own. One way to do this might be to use your identity provider to include a moderator claim in the JWTs of the moderators, and then handle this in the command handler appropriately.
In the command handler you have access to the token by
command.user.token
so you can get the claims as needed. I'm very sorry, that there is no better answer right now :-(

How to allow signing-up through multiple authentication-providers, while sharing the same email-address?

This is probably a question a bit in between SO and UX.se.
I'm implementing a signup/login sytem which allows for multiple ways of authentication: social signups using Facebook, Twitter, Github and a local (username + password) signup.
In the backend I'm having a User model and a Passport model. A User may have multiple Passports, meaning a User may authenticate through different means (e.g.: through local signin,. or through facebook for example)
For good measure: the Passports of a particular User will always be from a different provider (facebook, twitter, local). I.e.: a Facebook-passport, a Local-passport, etc.
This seems like a good way and would allow me to have a User account connected to multiple ways of authentication.
I'm familiar with the security issues this might raise, so for passports to be combined/merged a User has to be logged in to both.
Ok on to the problem. Consider the following flow:
user-a signs up with a provider, say local, with email user-a#gmail.com
user-a signs out (or has it's session expired).
user-a signs in using another provider, say facebook. Chances are the facebook account has a email-record of user-a#gmail.com
Currently, I've defined email to be unique on the User-model. This would mean the above signup would fail, because there's already a User-account that, by means of the local Passport, has the mentioned email-address.
What would be considered a best practice in a situation like this? I trust there must be many implementations floating around that must have seen this problem pop-up.
Options:
Warn the user the authentication isn't possible and mention the user that the current email-address is already registered by means of another authentication mechanism? This would be reasonably user-friendly.
Note that a User-account, by means of a different provider exists with the same email-address and as a consequence merge the new Passport with the User.. I just put this in for good measure: this is a pretty big attack-vector and would allow a user-b to get access to an account by faking the email-address (through a social provider which doesn't do email-validation)
Don't have a uniqueness constraint on <user,email>, but on <passport, email>. This would allow a new User and associated Passport to be created and all goes well. Now the same actual person probably has 2 User Accounts: 1 for each authentication provider. As a next stage allow the User-accounts to be merged, by signing in to both and acknowledging the merge.
I'm leaning towards 3, but 1 is simpler. I'm not sure, what do you think?
Have you encountered this before?
Yes, #3. I have implemented this myself. The concept you're looking at is: Associate multiple SSO accounts. My user structure is as follows:
name : {
first: { type: String},
last: { type: String }
},
emails: [{ type: String, unique: true, 'index': true }], //all known emails as provided by SSO services. we use this to cross ref when the user uses a different SSO to login after initial setup. this avoids account dupes
sso: [{
provider: { type: String, required: true}, //matches the name of passport strategy name employed
userid: { type: String, required: true } //the specific SSO provider userID that's unique in the provider's realm
}]
So, in your auth sequence, you look it up by email OR provider+userid combo, if you don't find the SSO provider, you attach it. The reason for or, someone may update their email but the specific SSO provider ID never changes.
Another common practice (if it makes sense in your app) is to allow the user to "link" SSO accounts. That allows you to handle different email addresses. Example: user FB email is a personal one but in LinkedIn he lists as primary the business one. LinkedIn sadly gives you only the primary via their OAuth2 call.

How to restrict access some part of module in ZendFramework 2 (i.e. only administrator can do some actions)

so!
I have a question: how to allow access some part of module only for adminisitrator, for example.
For example, I have module album. It has controllers index, delete, add, edit, full. I want full and index controller be available for all roles, but edit, delete and add action only for administrators.
What module I have to use to do that? I found Zend\Authentification.
Table is: username, password, role.
How to authentificate user?:
// do the authentication
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($authAdapter);
if ($result->isValid()) {
// success: store database row to auth's storage
// system. (Not the password though!)
$data = $authAdapter->getResultRowObject(null, 'password');
$auth->getStorage()->write($data);
$this->_redirect('/');
} else {
// failure: clear database row from session
$this->view->message = 'Login failed.';
}
After that I will get access to user data, for example, by:
Zend_Auth::getInstance()->getIdentity()->username;
So, in action, in which I want to restrict access I just need to use:
if(Zend_Auth::getInstance()->getIdentity()->role == admin) {
redirect("auth/login");
}
Right?
The questions:
Is my suggestion about how to check user role in each contoller correct?
Do I understand correctly how to work with Zend\Authentification and restrict access to some actions? So in future I will just use same for each action, right?
Additional question: Does Aclmodule uses for managing permissions? So Acl is needed to help Zend_Auth with permissions, right?
To be able to do this you have to build or implement an ACL (Access Control List). You can also use a third party solution in combination with the earlier mentioned Zend_Auth (or any other authentication module). You can read more on Zend ACL here: Zend ACL introduction
You could for example also take a look at BjyAuthorize. This ACL module provides a complete authorization solution for your application but depends on ZfcUser for user authentication and registration. It might be a good way to get started.
If you are done building or implementing BjyAuthorize you can easily tie your access permission checking to your routes (but there are many other ways). You can see how this works here on the BjyAuthorize GitHub page
These modules will teach you a lot about how authentication and authorization can be build into your Zend Framework 2 application.

Is it RESTful to send user role in http response?

I'm trying to find a way to modify a web page based on the a user's authorization. For example, the owner of a resource should see edit and delete buttons while a regular user should not see those.
The following is a method I am thinking about, but am unsure if there is a more common/better way.
For example, assume there is a resource
project: {
name: string,
owner_id: id,
moderators: [ids],
other_stuff: string
}
Would it be RESTful and good practice to extend this object with an attribute that describes what role the current logged in user is? For example, assuming this user is one of the moderators, it'd send
project: {
name: string,
owner_id: id,
moderators: [ids],
other_stuff: string,
user_role: "moderator"
}
Then the client-side framework would use project.user_role to display role-based controls such as delete and edit.