How to get roles from principal in Apache Shiro? - authorization

I am a bit stuck here.
Using a very simple Shiro configuration with jdbcRealm:
[main]
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager
# Create JDBC realm.
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
# Configure JDBC realm datasource.
ds = org.postgresql.ds.PGSimpleDataSource
ds.databaseName = pg_sensor
***
jdbcRealm.dataSource = $ds
# Configure JDBC realm SQL queries.
jdbcRealm.authenticationQuery = SELECT pass FROM users WHERE name = ?
# user id is a user Role )
jdbcRealm.userRolesQuery = SELECT id FROM users WHERE name = ?
So, I use userid as a role to do authorization in the code.
In one scenario I need to get role name to proceed.
Can anyone suggest how to do that from the Principal (SecurityUtils.getSubject().getPrincipal())?
I guess we need to use getRoles() withing SimpleAccount class, but not able to connect it with Principal.

Before anything, some comment about your shiro.ini:
Role query
First of all, your jdbcRealm.userRolesQuery does not really make sense: you are supposed to fetch the roles not the users for this query.
Assuming you have tables
CREATE TABLE user{
id INTEGER,
username VARCHAR,
password VARCHAR
}
CREATE TABLE user_role{
id INTEGER,
role_name VARCHAR,
username VARCHAR
}
your queries would like:
# Configure JDBC realm SQL queries.
jdbcRealm.authenticationQuery = SELECT password FROM user WHERE username = ?
# user id is a user Role )
jdbcRealm.userRolesQuery = SELECT role_name FROM user_role WHERE username = ?
Principal
I'm assuming that your subject is already successfully authenticated. So far, SecurityUtils.getSubject().getPrincipal() will only return the login or username, anything which identify your user but nothing more. In my above example, it would return the value stored in username column.
Role check
I think, you are rather looking does this authenticated user has role "MyRole"?. In this case, you can have a look around SecurityUtils.getSubject().hasRole("MyRole"). As far as I know, there is no way to list all the roles a subject currently has. You can only check if the subject has such or such role
Feel free to comment if I misunderstood your question

Related

Implement GetRoleAsync method with field in the Database

I need to implement the role retrieval method in identity. Currently I do GetRoleAsync (id) and I pull out all user roles.
But when I remove a role from the user, I don't want to delete it, but deactivate it.
So I would like to tell GetRoleAsync (id) to pull out all roles with ENABLED = true
How can I do?
I suggest you can use build-in RemoveFromRoleAsync method to remove role reference with current user:
//get current user
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var user = await _userManager.FindByIdAsync(userId);
//remove role from current user
await _userManager.RemoveFromRoleAsync(user, "TheRoleName");

Getting the Roles of the current user in .NET Core2.1

I use usermanager.GetUserName(User) to get the username of the current user, but there is no GetUserRole for usermanager.
How can I retrieve the Roles of the user in .NET Core2.1
Any help would be appreciated.
UserManager has GetRolesAsync() method, which gets a list of role names the specified user belongs to.
var role = await _userManager.GetRolesAsync(user);

Web2py, authenticating two types of profile

In one application I need to create two types of accounts, let's say users and tutors.
Each of them should be able to register/login/... user/tutor account defined by different tables in db.
e.g.
[app]/user/register should provide a form with fields: username, email, password, hobby
[app]/tutor/register should provide a form with fields: username, email, pass, name, surname, telephone
Web2py auth service allows using auth_user table which can be customized. Is there a way to use two tables separately according to controller in one application?
Field auth.settings.table_user contains reference for auth_table but I probably shouldn't use it for this purpose.
The Auth system isn't designed to work this way. Instead, it would probably be better to put all the fields for both user types in the single auth_user table and then selectively set the readable and writable attributes of the fields to True or False depending on the context.
In the model file defining Auth:
user_extra_fields = [Field('hobby'), ...]
tutor_extra_fields = [Field('telephone', ...]
auth.settings.extra_fields['auth_user'] = (
[Field('user_type', requires=IS_IN_SET(['User', 'Tutor']))] +
user_extra_fields + tutor_extra_fields)
In the controller that manages the Auth functions:
def user():
if request.args(0) in ['register', 'profile']:
hidden_fields = (user_extra_fields if request.args(1) == 'tutor'
else tutor_extra_fields)
for field in hidden_fields:
field.readable = field.writable = False
return dict(form=auth())

Make openam/opensso return role name instead of role universal id

I'm using OpenAM 9.5.2 for authenticating users on an application. The authentication works well but I'm having issues to get user memberships from final application.
I've defined the group "somegroup" in openam and added my user to this group. Now in my application, I want to test if authenticated users is member of this group. If I'm testing it with:
request.isUserInRole("somegroup");
I get false result. Actually, I have to test
request.isUserInRole("id=somegroup,ou=group,dc=opensso,dc=java,dc=net");
in order to get a true response.
I know that it's possible to define a privileged attribute mapping list in the sso agent configuration to map id=somegroup,ou=group,dc=opensso,dc=java,dc=net on somegroup, but it's not suitable in my situation since roles and groups are stored in an external database. It's not convenient to define role in database and mapping in sso agent conf.
So my question : is there a way to make openam use the "short" (i.e. somegroup) group name instead of its long universal id ?
This is not an answer, just one remark.
I've performed some researches in openam sources and it seems to confirm that the role name stored in repository is replaced by universalId when openam build the request. This is performed in com.sun.identity.idm.server.IdRepoJAXRPCObjectImpl.java class:
public Set getMemberships_idrepo(String token, String type, String name,
String membershipType, String amOrgName,
String amsdkDN
) throws RemoteException, IdRepoException, SSOException {
SSOToken ssoToken = getSSOToken(token);
Set results = new HashSet();
IdType idtype = IdUtils.getType(type);
IdType mtype = IdUtils.getType(membershipType);
Set idSet = idServices.getMemberships(ssoToken, idtype, name, mtype, amOrgName, amsdkDN);
if (idSet != null) {
Iterator it = idSet.iterator();
while (it.hasNext()) {
AMIdentity id = (AMIdentity) it.next();
results.add(IdUtils.getUniversalId(id));
}
}
return results;
}
To my knowledge this is not possible currently with out of box code. In case you have limited amount of groups, then privileged attribute mapping could be a way to go, but if not, then the issue gets more complicated.
You could try to change the AmRealm implementation (authenticateInternal method) to match your requirements and hook the new class into the container-specific ServiceResolver class (like http://sources.forgerock.org/browse/openam/trunk/opensso/products/j2eeagents/tomcat/v6/source/com/sun/identity/agents/tomcat/v6/AmTomcatAgentServiceResolver.java?r=700&r=700&r=700 )
You can also create a JIRA issue about providing a config property to put membership information into roles in non-UUID format.

What is used to login in LDAP mail server?

If I added data on LDAP in this way:
$ldapserver = "mail";
$ds = ldap_connect($ldapserver);
$r = ldap_bind($ds, $ldaprootun, $ldaprootpw);
add = ldap_add($ds, "cn=$full_name,ou=$domain,o=mygroup.com", $infonew);
Then does that mean that when I log in to my account I will use:
`cn="mynameHere",ou="domainIused",o=mygroup.com`
as my username? Or just my uid?
My account cannot login but I'm sure that it exists in LDAP.
Answers are very much appreciated. =)
Typically in LDAP applications you only ned to login with your UID, not your full X.500 name.
Try calling ldap_bind() with your creds and see what it returns?
Usually, the user provides a simple name. Then the app searches the LDAP source for some attribute that has that value. Then you bind or password compare in your code, as that full DN.
You can use uid which is Unique ID, which is required to be unique. I.e. If you find more than one instance of it, that is an error.
You can try CN, but that can often be multi valued depending on your LDAP implementations schema.
If you know you are going against eDirectory, then uid is fine, or CN just do something if it is multi valued.
If you know you are going against Active Directory, you can assume sAMAccountName is unique since the system enforces uniqueness. userPrinicpalName ought to be unique, but nothing actually enforces it.
You can always use mail, which is the email address pretty uniformly.