using ldap credential and search in postgresql tables - java

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.

Related

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

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.

How to search for an unknown collection containing identifying document fields?

Is it possible to search for an unknown collection that contains a document with identifying fields like an email?
My structure is like this:
Each user gets their own collection based on a unique ID. Each collection contains a user doc and a accounts doc. User doc contains the information about the user that I would like to search for. Accounts doc contains a collection of bank accounts that I want to transfer money between users.
My problem is that I don't want users to type in the long unique id to enter the collection but to type the email of the user that is inside the collection\user document. The email is unique.
Have I just made a bad structure for my project or is there something I can do?
UPDATE
Thanks, Alex and Frank for the feedback.
I went on and changed my structure to as shown:
/users/$uid/accounts/$accountid.
Did a java Query collectionReference = db.collection("users").whereEqualTo("uEmail", userEmail); and saving the document.getId() as a String userId.
I Then use the UserId in a spinner to enable the user to pick an account from the userId accounts collection.
As Alex said, there is no way to load data from a collection (with the client-side SDKs) unless you know the collection name.
But in this case, it seems like your collections are named after the user's UID.
That means that if the user is signed in, you can know their collection by:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
CollectionReference userCollection = FirebaseFirestore.getInstance().collection(uid);
A few notes:
It is much more idiomatic to store your structure with a top-level collection of users, and then a document for each user under that, and then subcollections for the other data under that. So for example: /users/$uid/accounts/$accountid.
The server-side SDKs do have a method to get a list of collections, for example like this listCollections method in the Node.js SDK. But these SDKs are only to be used in a trusted environment, such as your development machine, a server you control, or Cloud Functions, and not directly on the client. Even with this SDK though, you'll have to iterate the list of collections and check each in turn, because as said before: you can only read data from a collection of which you know the name.
If you're trying to look up the collection/UID for another user than the one who's signed in to the app, you may need to way to map an email address to a UID. Such functionality is not available in the client-side SDKs. But similar as the point above, there is a method getUserByEmail in the Admin SDKs.
Is it possible to search for an unknown collection that contains a document with identifying fields like an email?
No, you should know the name of your collection in order to be able to use it in your reference. There are no wildcards in Cloud Firestore paths to collections/documents. You have to identify every collection and every document by their specific ids.

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.

How to avoid creating duplicate nodes when ID is not known

I am using Neo4J to save events from Git-lab web hooks.
An example of the data can be found here https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md#push-events
One of the nodes is an Author {name,email}
Here the email is the natural unique id.
In Hibernate(JPA) there is an annotation called #Id that i could set on the Author field email (ref to docs).
How can I make Neo4J OGM to persist/merge based on email instead of it's id?
One of the fastes/easiest solution would be to use constraints:
Create CONSTRAINT ON (a:Author) ASSERT a.email IS UNIQUE
This way, neo4j will ensure constraint is respected, and you don't have to implement uniqueness on server side, since database is doing it.
In an ETL tool you would reasonably expect to able to define your source keys/identities. Neo4j OGM is not really an ETL tool, but if you want to use it as a data importer, you have a couple of options.
The first is to manage the key-mappings yourself. Of course, this may be impractical, depending on volumes and other considerations. The second is always try to fetch a given object from the graph via its email address before saving any item from your event feed.
I have a couple of comments.
Administrator seems to be the value of the name property, not the email property. Are you sure the 3 Administrator nodes in you image actually have the same email property value? To make the neo4j Browser show the email values, set the caption for the Author nodes to email instead of name.
Aside from the above, it looks like you have already tried this Cypher query, but are getting what seem to be duplicates:
MERGE (n:Author {name: {name}, email: {email}})
RETURN n
That could be explained if it is possible for the input data to contain multiple names for the same email address. In that case, the following query should prevent "duplicate" Author nodes. If an Author with the parameterized email address already exists (regardless of its name value), it just returns the existing node (without changing its name); otherwise, it creates a new Author node with the parameterized email and name properties. This solution would mean that only the first name encountered for an email address will be stored in the DB.
MERGE (n:Author {email: {email}})
ON CREATE SET n.name = {name}
RETURN n

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