Java: Query Active Directory information with minimal user information - java

So, here's the situation. We'd like to be able to query active directory for a user's roles/group memberships, etc. Now, I can already do that using standard Java API (javax.naming), but I need a username, domain server name/address, and a password to do it. Users also have limited rights, so I can't use any external calls to fancy administrative tools.
In Java, is there a way that I can get that information with just the username and domain server name/address? I'm also open to 3rd party packages to do this. Alternatively, you could provide me with (or point me to) information on what to configure in AD to allow this.
Hopefully that makes sense. I'm not an AD guru, so the more info the better.

Your problem of needing to login first is because AD does not allow anonymous querying. Before you can query the database you must login ("bind" in LDAP terms) as a valid user with sufficient rights to issue the query.
If your AD admin is willing, you could have them create a special user (we call ours "ldapquery") that is permitted to bind and query the database. The userid and password for that user would become configuration values in your code.

Okay, so expounding on what others have told me and the vast research I had to do with the clues given here, it appears that I'd just use my "special user" as the login info in my code, transparent to the user, and then perform the query using their credentials. So: in the code, bind using the "special user", then perform the query with the current user as a query parameter (sAMAccountName=username).
Thanks all, for your input.

Related

Is a real user account required for Admin SDK impersonation?

In my application I am listing all the users in a Google Apps domain. I have a Service Account that I use to authenticate my application. So far so good.
Before listing the users, I need to provide a user account that my application can impersonate, like this:
new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(serviceAccountEmail)
.setServiceAccountScopes(asList(scopes))
.setServiceAccountUser(usernameToImpersonate)
.setServiceAccountPrivateKey(privateKey)
.build();
That works fine, but I have two issues:
I currently don't store the admin account username, so I need to jump through some hoops to get that in, and in some cases I will have to ask my customers.
The account given as an admin account (having access to the Admin SDK) might not have admin rights forever. If the customer decides that someone else should be admin, my application won't work anymore.
Is there a way around this? I have permissions to impersonate any user in the domain, which means I can just pick one of the admins, but the problem is that I don't know who's the admin until I have made this request. Catch 22.
I thought I could just use the Service Account Email instead of a real user email (which would be the ideal solution), but that just gives me weird NullPointerExceptions from the Google API.
EDIT sept 25, 2014:
Since a few days ago, Google now allows any user to list users in a domain (also including subdomains).
http://googleappsupdates.blogspot.se/2014/09/new-features-in-admin-sdk-custom-user.html
However, this has two limitations which mean that this is not something I can benefit from for my particular use case.
You still need a (active) username to make a request, and how are you going to get that username if you can't list the users? I might have a username from the signup, but that account may be deleted at any time. Still catch 22.
If you are using a non-admin account, you are forced to set viewType to "domain_public", which means you will only be able to see a subset of the available fields. The "suspended" field is not one of them, and you also won't get any suspended users in the response.
(documentation available here: https://developers.google.com/admin-sdk/directory/v1/reference/users/list)
I could live with the "suspended" limitation, but since I can't get a list of users without already having a user, this is not helping me.

encrypt database username and password in java?

Actually by type 4 db connection from java i am connecting to oracle database like this:
In dbconnection.java i have written below:
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:database host name","database user name", "database user password");
return con;
Is there any method how can i write these 3 fields(database host, database username, database user password) in encrypted form in java class dbconnection.java like below:
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#localhost:1521:wrtwtr#$%$_rfwrw","regfwerfgwf", "%%5frfr^&%$%4");
return con;
and during database connection, these encrypted fields will be decrypted and will be connected to oracle database in actual names
Then in servlet i am calling like:
dbconnection db= new dbconnection();
Any help please
I'm not aware of any way to do that.
But I also don't see what doing this would achieve. Sure, the username and password are not shown in clear, but a bad guy who had access to those encrypted strings would be able to use them the same way as your program does.
Rather than trying to hide your connection details, you should provide a secure way to allow externally controlled applications (or instances of applications) to access your database.
An API is basically a middle layer between your database and an application you do not have control over. For example, facebook, rather than allowing direct access to their database, allows developers to access their data through an API. This means that applications can be authenticated (thus meaning they can be held responsible), and you can control explicitly what applications can and cannot see and edit.
Basically, through an API, you can protect your database while simultaneously keeping track of who is doing what (though the protection aspect is usually the main draw).
I must say though that sometimes, if you trust the people using the application, it's just easier to not worry about it. For example, if you work at a small company of competent, well meaning people, then it would likely be safe to allow the application to connect directly to the database.
If you are distributing your program to the general public though, or a large set of people whom you do not completely and totally trust, then you should not allow direct access, no matter what kind of precautions are taken.
Assume that you do figure out how to encrypt your credentials. At some point, you must still make the connection. What happens now if a user grabs the decryption/connection code, has the connection made, then inserts his own code after it? Suddenly he has access to your database. With an API, worst case, he could steal the API key and have limited, traceable, easily revokable access.
And besides, if you're allowing access to an API, you only allow users to do what you want them to do. So worst case, if he does figure out how to use the API directly, all he can do is what the program allows him to do anyway.
Passing encrypted data to the DriverManager is not an option.
You should pass the decrypted string into DriverManager. So somewhere you would have the user name and password encrypted and then decrypt them before passing them to the DriverManager
Then you would have other issues e.g. where to store private key etc, but as a first defence it would be better than using plaintext since my understanding is that you have some security requirement.
You did not mention what OS you are using. If you are using Windows I would suggest to use Windows based authentication (the connection to the database is authenticated against the current windows user).So no need to provide user name and password in the connection string. Check if Oracle supports this (have tried only with MS-SQL server.Hopefully the link I provided is useful).
This is IMHO the best option. For Linux there must be something equivalent.

How do I prevent unauthorized users from deleting objects in my domain model?

I got similar domain model
1) User. Every user got many cities. #OneToMany(targetEntity=adv.domain.City.class...)
2) City. Every city got many districts #OneToMany(targetEntity=adv.domain.Distinct.class)
3) Distintc
My goal is to delete distinct when user press delete button in browser. After that controller get id of distinct and pass it to bussiness layer. Where method DistinctService.deleteDistinct(Long distinctId) should delegate deliting to
DAO layer.
So my question is where to put security restrictions and what is the best way to accomplish it. I want to be sure that i delete distinct of the real user, that is the real owner of city, and city is the real owner of distinct.
So nobody exept the owner can't delete ditinct using simple url like localhost/deleteDistinct/5.
I can get user from httpSession in my controller and pass it to bussiness layer.
After that i can get all cities of this user and itrate over them to be sure, that of the citie.id == distinct.city_id and then delete distinct.
But it's rather ridiculous in my opinion.
Also i can write sql query like this ...
delete from
t_distinct
where
t_distinct.city_id in (
select
t_city.id
from
t_city
left join t_user on t_user.id = t_city.owner_id
where
t_user.id = ?
)
and t_distinct.id = ?
So what is the best practice to add restrictions like this.
I'm using Hibernate, Spring, Spring MVC by the way..
Thank you
What you're asking for is not SQL Injection prevention. You need to ensure the user attempting the deletion is authorized.
As long as you check that the user accessing the page has the rights to delete the row your trying to delete (this would be checked in the Business layer), and ONLY allow the delete command if the user is authenticated and authorized to perform the action.
With hibernate you don't have to worry about sql injection. It always uses prepared statements, so you are safe.
As for your concrete case, this is not an sql injection. But to prevent it, make validation in the controller - whether the currently logged user owns the desired ID.
Depending on the size of the application, you can implement some general security scheme, with ownership settings, and apply it (using AOP).
I understand that i want to be sure, the the user is real owner of Book The question was how to accomplish it. And yes, i know that user is authenticated and authorized. But another authorized user can easy delete pages of another user.
This can be done like this...
User userFromHttpSession ...
Long bookId = load page, get bookId, load book, get bookId
List books = userFromHttpSession.getBooks();
... iterate over books and find out if one of the book.id == bookId
... then if book owner is owner of httpSession, then proceed Delete
It's like too many sql queries, and too many code, probably there are better solution. Anyway thank you for your answers
Just use your head, quote-escape* everything from an outside (or inside for that matter) source before it gets put in an SQL statement, and check data as it goes in. Or, use prepared statements.
*Edit: By "quote-escape" I meant functions like PHP's mysql_escape_string()

How do I keep a user logged into my site for months?

I'm using OpenID. How do I make it so that the user stays logged in for a long time even after closing the browser window?
How do I store and get access to the user's User object?
Basically, I guess I just don't really understand how sessions work in Java.
So you actually want like a "Remember me on this computer" option? This is actually unrelated to OpenID part. Here's a language-agnostic way how you can do it:
First create a DB table with at least cookie_id and user_id columns. If necessary also add a cookie_ttl and ip_lock. The column names speaks for itself I guess.
On first-time login (if necessary only with the "Remember me" option checked), generate a long, unique, hard-to-guess key (which is in no way related to the user) which represents the cookie_id and store this in the DB along with the user_id. Store the cookie_id as cookie value of a cookie with known cookie name, e.g. remember. Give the cookie a long lifetime, e.g. one year.
On every request, check if the user is logged in. If not, then check the cookie value cookie_id associated with the cookie name remember. If it is there and it is valid according the DB, then automagically login the user associated with the user_id and postpone the cookie age again and if any, also the cookie_ttl in DB.
In Java/JSP/Servlet terms, make use of HttpServletResponse#addCookie() to add a cookie and HttpServletRequest#getCookies() to get cookies. You can do all the first-time checking in a Filter which listens on the desired recources, e.g. /* or maybe a bit more restricted.
With regard to sessions, you don't need it here. It has a shorter lifetime than you need. Only use it to put the logged-in user or the "found" user when it has a valid remember cookie. This way the Filter can just check its presence in the session and then don't need to check the cookies everytime.
It's after all fairly straight forward. Good luck.
See also:
How to implement "Stay Logged In" when user login in to the web application
How do servlets work? Instantiation, sessions, shared variables and multithreading
Well, the original reason I chose OpenID was so someone else could handle as much of the implementation and security of authentication for me.
After looking into OpenID more, it appears there is something called an "Immediate Request" (http://openid.net/specs/openid-authentication-2_0.html#anchor28).
When requesting authentication, the Relying Party MAY request that the OP not interact with the end user. In this case the OP MUST respond immediately with either an assertion that authentication is successful, or a response indicating that the request cannot be completed without further user interaction.
Because of this I think I could just store the user's openID url in the cookie, and use an immediate request to see if the user is authenticated or not. This way I don't have to do anything with my database, or implement any logic for preventing session hijacking of the long-lived cookie.
This method of doing it seems to be the way OpenID suggests to do it with their Relying Party Best Practices document.

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