How to get users by attributes key(key, value) in keycloak? - java

I am using keycloak-admin-client 13.0.0 in my Spring Boot Application. I can get all the users from KeyCloak. But I want to get users by attributes like mobile or em_no or dept.
User attribute:
key - value
mobile - 9876543210
em_no - 12334
dept - IT

I'm afraid that searching by attribute value would require fullscan over user entities and would be not very efficient if you will have huge number of users. Consider this feature apart from keycloak. How would you implement search by phone in standalone relational DB schema? I guess you would add index on this field. In this case you can add custom table to keycloak schema that will provide phone -> user mapping. See here (https://www.keycloak.org/docs/latest/server_development/#_extensions_jpa)
Considering dept attribute i would recommend to switch from attribute to groups. So you will have set of departments groups (IT,ACCOUNTING, ..) and join user to appropriate group. Then you can easily query members of desired group.
Similar approach works for roles. E.g. if you have finite numbers of values you can define them as roles and grant appropriate role to user instead of attaching this value as attribute. Querying by granted role also available right out of the box.
Note that there are available a lot of different OIDC mappers that will help you to add described mappings (no matter is this a attribute, group or role) to access token structure.

Related

How To Filter And Limit Attributes Of A Group Object In An LDAP

I want to get users of a group in an LDAP, with a given filter(Ex: uid="test*") and a limit(only 10 users in the results).
The group object looks like below.
cn=testRole,ou=Groups,dc=WSO2,dc=ORG
This object has multiple member attributes representing users of the role "testRole".
Now I'm using the following query to retrieve all the users in the group.
(&(objectClass=groupOfNames)(cn=testRole))
And member is set as the returned attribute.
When I run the query, all the 10000 users in the testRole are retrieved(as 10000 member attribute values).
Now,
How do I limit the number of member attribute values?
How do I filter member attribute values by applying a filter to the value of it's uid?
Thanks in advance!
I tried setting the returned attribute as member;range=0-99 but seems like it only works with AD, not with LDAP. I need a solution that would work with LDAP regardlessly it is an AD or not.
I think it's not possible as is with openLDAP. An idea would be to setup the memberof overlay in the first place so you can grab user entries - not by querying the group and fetching all member attributes - but by directly querying users that are memberOf this group. In this situation, you would be able to paginate the results with the desired range. Not to mention that you will also be able to filter by a specific member eg. (&(memberOf=<groupDN>)(uid=<uid>)) (which I think is what you ask in 2-). See these links :
How to enable memberOf
Simple Paged Results Control.
You can use the following filter :
(&(objectClass=groupOfNames)(cn=testRole)(member=uid=<uid>,ou=people,dc=example,dc=com))
But remember this query just grabs a groupOfNames entry with cn=testRole and containing a member with dn=..., adding the member filter here would just prevent the entry to match in case the member's <uid> does not exist, any matching uid would not change anything.
I think you can also keep the query as it is, iterating member attributes by range of x to y using java shouldn't be too hard, it all depends on what you need to do with it.

using ldap credential and search in postgresql tables

I'm a beginner with LDAP, and I want to use it in the future project with PostgreSQL database.
Suppose that I'll do the authentication with LDAP server, so the user table will not be inserted in PostgreSQL database, in the PostgreSQL database I'll have other tables that must be in relation with the identity of user (that will be retrieved from LDAP) so I have to add a column in each of this tables named uid that store the uid value of the user. Is my idea correct?
What you describe is perfectly fine. Just be aware that which attribute you use as the unique identifier depends on which LDAP directory you are using.
I really only know Active Directory, which does not use the uid attribute at all. AD has a few attributes that are enforced unique:
distinguishedName: Describes where the object is in the directory. It looks something like: CN=Gabriel Luci,OU=Users,DC=domain,DC=com. This is common to LDAP in general, but might be called something different in other LDAP directories.
sAMAccountName: This is commonly referred to as the "username". It must be unique on the domain, but it can be changed.
userPrincipalName: Uses the format username#domain.com. This must be unique in the AD forest, but it can be changed (a "forest" is when there are multiple AD domains in the same organization)
objectSid: (usually just called the SID). It is stored as a byte array, but can be converted to a string that looks like S-1-5-32-##########-###########-##########-#####. This is what is used by Windows in security permissions to grant accounts permissions to files, etc. This cannot be changed.
objectGuid: A GUID that is automatically assigned when the account is created. This cannot be changed.
The first three are human-readable (they will usually have the person's name in it). The other two are not, but they also stay the same for the life of the object (if the person changes their name, the SID and GUID will still be the same).
Which one you use depends on your requirements. The distinguishedName is unique and allows you to bind directly to the object when you need to (as opposed to having to search for the sAMAccountName to find the account). But if you want something that will never change even if the person's name changes, then objectSid or objectGUID is best.

How does Spring Security's ACL (access control list) deal with a principal having multiple permissions per OBJECT_IDENTITY?

I am trying to roll out my own custom ACL system in Spring security which is more fine-tuned to my project than the default ACL system. My question is this:
How does the default ACL implementation that comes out of the box with Spring Security deal with a single principal object (SID) having multiple permissions per domain object (OBJECT_IDENTITY), without cluttering the database?
The documentation states: "ACL_ENTRY stores the individual permissions assigned to each recipient. Columns include a foreign key to the ACL_OBJECT_IDENTITY, the recipient (ie a foreign key to ACL_SID), whether we'll be auditing or not, and the integer bit mask that represents the actual permission being granted or denied. We have a single row for every recipient that receives a permission to work with a domain object."
So the ACL_Entry is basically the join table between a single principal user, and a single domain object that user has permissions for.
Fine. However; on the controller layer, there are multiple CRUD methods that one can perform on a single object. What if one user has permission to update, and delete an object, but another user has only permissions to create, and read an object (for instance). Does the default Spring ACL system store a row in the database for EACH AND EVERY permission between a principal user and a domain object? For instance, Joe has permission to read this object. Row += 1. Joe also has permission to write this object. Row += 1 again and so on.
If it does work this way that will make it much easier to implement my custom rollout, because I was concerned about adding multiple permissions in the DB per object, per principal (You can see how if one principal gets read, write, and update permissions per object, that is three rows per user. Get 300 users and that's 900 rows, and you can see how this can be an exponential problem).
If not then how does this work? Thanks.
Does the default Spring ACL system store a row in the database for
EACH AND EVERY permission between a principal user and a domain
object?
Yes.
On the other hand, a permission only need one bit (on or off) and the Permission interface even has a getMask() method to combine several permissions into a single integer, so you could get away with only one record per sid/user and domain object. However, the built-in ACL permission evaluator in Spring Security can confusingly not handle such bit masks, but require a seperate row for every permission to grant. Edit: This limitation is described in issue report SEC-2342.
Regarding your concern about many rows to store the permissions: A security identity (sid) does not need to be a single user, it can also be a group. If there are many users, assign users to groups and set permissions on groups.

Need advice about design Restful with user role

I'm confusing about design restful for my API.
I have 2 roles are end-user and backend(admin). With backend role, i can access any resources of user
An user can have many orders.
So I defined base on users resource
GET /users/{userID} -- get User Information
GET /users/{userID}/orders -- list user order list
POST /users/{userID}/orders -- user make an order
But uhm.. after reference some online documents, implicit userID will be identified after authentication phase, so here are the different designs by using order resource:
GET /orders/ --list user order list by user account(backend can get all)
GET /orders/{orderID} --get orderID by userID
POST /orders/ -- user make an order.
with this define, when backend user want to list orders by user. Which method should I use?
GET /orders?user={userID} (user as query parameter) -- List order with userID
Or
GET /users/{userID}/orders
Pls advise me which one (users or orders resource) design is better, and why?
Tks,
Which design is better depends on the use cases.
For example, let's assume two users:
Alice (userID=1)
Bob (userID=2)
Let's also say Alice has already authenticated so the backend has userID=1 available somewhere.
If Alice wants to list her own orders, the shortest way would be
GET /orders
And have the backend user the available userID.
Let's say the request is suppose to retrieve Orders for the authenticated user. What if Alice tries /users/2/orders - is she allowed to see Bob's orders? What if Alice mistypes a lot and issues a query for /users/2/?
Final thing to consider - what if there are more attributes to search on in the future? What if userID is removed from Orders from the future (let's say there's a new relation in the future like User --> Cart --> Order)? Which URI scheme is easier to update?
So, there's no simple answer and it depends on your use cases. In the case where it's just retrieving Orders, I'd recommend the going with {GET|POST} /orders for the most flexibility and simplicity.

LDAP: How to search for a given uid across multiple organization units?

First off, let me start by saying that I am totally new to working with LDAP.
I am working on an application that shares an LDAP server with a few legacy applications.
All of the user accounts in the legacy application are organized into Organizational Units by IDs. Each entry has a uid that is the users email address.
I can find if a user with the email some#email.com exists in the organizational unit 12345 by using a dn something like this: ou=someGroup,ou=12345,uid=some#email.com
However, what I'd like to be able to do is check for the existence of a user across multiple organizational units. For example, I'd like to be able to check if an email is in use within with an arbitrary number of organizational units. (for example, check within 12345, 23452, and 34352).
After googling around, it seems that I should be able to find multiple entries with a single dn, but I haven't figured out how to check for this scenario.
Does anyone know how I can do a check like this? I am using Spring LDAP.
I believe you should be able to do this as follows:
As your search DN specify the domain components only:
BASE_DN = "DC=TEST,DC=COM"
As your filter, specify your CN or uid
FILTER = "UID=bob"
As your search be sure to specify "sub" or your Spring LDAP specific parameter to search the entire sub-tree below the base DN.
Depending on your setup, you may need to ask the search to Always Dereference links.

Categories

Resources