ldap nodejs active directory authentication - node.js

I am currently working on a web application in node.js in which a user needs to log in to access the information. I want to check the user login and password with an external active directory server. I have tried using node-ldapauth, but I can't get it work (I don't know if it works for active directories, maybe just openLdap). Any suggestions?

I used an rubyldap library to solve the problem thanks!
Update: As requested this is the library I used to solve the problem https://github.com/ruby-ldap/ruby-net-ldap/
After installing the ruby library on your server, using gem install (look it up it's not too hard)
require 'rubygems'
require 'net/ldap'
ldap = Net::LDAP.new :host => server_ip_address,
:port => 389,
:auth => {
:method => :simple,
:username => "cn=manager, dc=example, dc=com",
:password => "opensesame"
}
filter = Net::LDAP::Filter.eq("cn", "George*")
treebase = "dc=example, dc=com"
ldap.search(:base => treebase, :filter => filter) do |entry|
puts "DN: #{entry.dn}"
entry.each do |attribute, values|
puts " #{attribute}:"
values.each do |value|
puts " --->#{value}"
end
end
end
p ldap.get_operation_result
Set up a ruby file as shown above.
You can run the ruby library by using
var ldap = 'ruby '+process.cwd()+'/src/ruby/ruby_file_name '+ user+' '+password;
To grab the user and password in ruby use ARGV[0] and ARGV1.
You can grab the ruby returned result in node.js by using a call back function
var result = exec(ldap, theCallBack);
in the theCallBack function you can grab the returned ruby library results by passing in stdout
ex:
function theCallBack(err,stdout) {
----your code here, stdout is what you PUT in the ruby library.
Hope this helps!

Could you post the snipet of your code and the error you get?
I am trying to do the similar and came across the ldapjs library. It allows you to implement a client ldap connection to an LDAP server and you can, in doing the connection validate the users username and password.
I tried setting it up on windows with 0.8.2 and ran in to some issues, which it sounds like the developer is looking in to. The nice aspect of this library is it doesn't rely on the OpenLDAP binding that the one you referenced does.

For having ldapjs installation working on Windows, I wrote the steps I followed here http://tochedev.blogspot.be/2012/07/i-wanted-to-add-ldapjs-to-my-windows.html
Hope this helps.

Related

Improve latency of findUsers query made by node js activedirectory module

I am expriencing high latency when fetching users from active directory in nodejs.
I am using the node library from npm 'activedirectry'. https://www.npmjs.com/package/activedirectory
The amount of users is relatively not big, About 1000 users...
The time of the query takes between 2 to 4 seconds.
The default query provided by the function findUsers of the 'activedirectory' library is (&(|(objectClass=user)(objectClass=person))(!(objectClass=computer))(!(objectClass=group))).
I added an additional filter on the sAMAccountName field. sAMAccountName=*somePartOfName*
In any case, with or without my addition the query time is still slow.
I don't have full configuration of the active directory server,
But it seems like other platforms on the same network work faster with the active directory but they work with other frameworks, in java and .NET.
What could be the reason for this high latency?
Thanks
// ad is configured only with user, password, base dn and url
function findUsers(partOfsAMAccountName) {
const additionalQuery = `sAMAccountName=*${partOfsAMAccountName}*`;
return new Promise(resolve => {
ad.findUsers(additionalQuery, false, (error, users) => {
if(error) {
console.error('%j', error);
}
resolve(users || []);
})
}
}
What I am tring to do is to create an autocomplete mechanism based on the usernames of the active directory.
On the same network we have bitbucket server connected to the same active directory server. It seems like from the bitbucket client the autocomplete is much faster. about 1 sec from the client side.
I had already searched for the open souce of bitbucket but didn't find any.
I have no idea about node.js, and have never programmed in the same. But, from the question I feel that default query provided for findUsers() might be the culprit.
As per Microsoft Docs, LDAP filter for
(&(objectClass=user)(objectCategory=person))
is sufficient for determining the users.
In the official documentation for function findUsers(opts, callback), I can see the argument opts description about Optional parameters to extend or override functionality.
So, I think you can override the LDAP filter query using the opts argument in findUsers function to keep the above advised LDAP filter, and additionally put your sAMAccountName condition in the search query. Please explore on how to override the opts argument, as I can't help you with that.
I am hopeful that the result would be comparatively faster after doing the search this way.

How to connect to Realm from aws lambda node

I am trying to connect to a Realm instance from an aws lambda (node) with the following code:
await Realm.Sync.User.login('https://server.realm.io', 'username', 'password')
.then((user) => {
let config = user.createConfiguration();
config.schema = [Schema];
Realm.open(config).then((realm) => {
//Do some cool stuff });
The problem is it tries to create a directory realm-object-server when it logins. As we know the lambdas file system is read-only except for the tmp folder. Is there a way to tell realm to write this realm-object-server to the tmp folder or is there a way to login that doenst create a direcotry at all?
Thanks in advance for the help
I ran into the same issue using Realm from a Google Cloud Function. None of the Realm configuration options like path or inMemory seemed to have any effect. After much digging, the solution I found was to call process.chdir('/tmp') prior to opening the Realm. This changes the current NodeJS process's working directory as explained in the NodeJS documentation. This allowed me to open the realm successfully.

How can I access the hapi plugin name?

I am working on node using hapi framework. New to this so I apologize if it comes out to be very basic.
I want to access a plugin name within the plugin files.
Use case is I want to access the plugin options from the server object.
So I can do server.registrations[plugin_name].options.
My workflow at that point (where I require the options) is not inside the register method ( I run an independent script that just needs to initialize the server, not start it; so no routes here) so not able to access the options from there, but I have the server object available.
Also, what is the correct way to expose the plugin options to other files within the plugin? If I need the options after a lot of nesting of files etc , it is very chaotic to keep passing the options object somehow from file to file, method to method.
Not really clear how to work this problem out.
Not a 100% sure what your question is but if you expose your options in a script (module) that can be required by both your plugin and any other files that you want to use the same options object that will allow you to access the same object in multiple places.
Please let me know if i understood correct, you can do like this.
const Plugins = require('./Plugins');
//Register All Plugins
server.register(Plugins, err => {
if (err){
server.error(`Error while loading plugins : ${err}`)
}else {
server.log('info', 'Plugins Loaded')
}
});

Electron Node.js node localstorage osx mkdir permission denied

I am working with Electron and Node.js. We have developed an application that works fine on windows and as a requirement had to package it for mac os. I packaged the application using electron-packager, the packaging process completes and package is generated. Double clicking it throws an error that permission denied for mkdir, as i am using node localstorage to maintain some settings on the user's local machine. somehow mac doesn't local storage to create folder in the root of the application. Any help in this matter will be great. Thanks
First off, is the code in question in the main process or in a renderer process? If it is the latter, you don't need to use 'node-localstorage', because you can use the renderer's native LocalStorage. If you are in the main process, then you need to provide your own storage strategy so using 'node-localstorage' is a viable option.
In any case, you need to carefully consider where to store the data; for starters, let's look at where Electron's renderer processes would store its LocalStorage data: this differs based on the OS, but you can get and set the paths using the app module -- the path in question is userData, which on OS X would default to ~/Library/Application Support/<App Name>. Electron uses that folder to persist cookies, caches, LocalStorage etc. so I would suggest using that folder as well. (Otherwise, refer to XDG defaults for good defaults)
What your example above was trying to do is store your 'errorLogDb' in the current working directory, which might depend on your OS, where your App is installed, how you executed it, etc.
Finally, it's a good idea to differentiate between your 'production' app and your app during development and testing, because you might not want to use the same storage folders for every environment. In any case, just writing to './errorLogDb' is likely to cause lots of headaches so I'd be thankful for the permission denied error.
this strategy worked for me:
const { LocalStorage } = require('node-localstorage');
let ls;
mb.on('ready', () => {
let prefsPath = mb.app.getPath('userData') + '/prefs';
ls = new LocalStorage(prefsPath);
loadPrefs();
});
mb.on('after-create-window', () => { /* ls... */ }
exports.togglePref = () => { /* ls... */ }

Java method is successfully executed inside a Java agent, but fails if executed in a Java class in the database's code

In my XPages application, I use the javax.mail library to read mail messages from IMAP accounts. The class I use to get and save messages works perfectly fine if I use it inside a Java agent. However, if I put the exact same class into "Code/Java" in my XPages project, the methods throw javax.mail.NoSuchProviderException: No provider for imaps when I try to get the session store:
Properties props = new Properties();
props.setProperty("mail.imaps.socketFactory.class", "AlwaysTrustSSLContextFactory");
props.setProperty("mail.imaps.socketFactory.port", "993");
props.setProperty("mail.imap.ssl.enable", "true");
props.setProperty("mail.imaps.ssl.trust", "*");
URLName url = new URLName("imaps", server, 993, "", username, password);
Session session = Session.getInstance(props, null);
Store store = session.getStore(url); //THE ERROR OCCURS HERE
store.connect();
The javax.mail library that I added to the project's build path is exactly the same that I use in the Java agent.
Some posts I found for the mentioned type of exception suggest that it might be caused by multiple versions of javax.mail being included in the build path. However, this does not seem to be the case because removing javax.mail from the build path causes the class to not be built.
Does anybody know what's the problem here?
Please check the versions and providers of javax.mail used. You can do this by adding
props.setProperty("mail.debug", "true" );
to your properties.
On the console (Client's Java Console or Server console you can see the result, something like this:
DEBUG: JavaMail version 1.4ea
and
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc]
Alternativly, you can get the list of available providers programmatically (when you have no console access):
Session session = Session.getInstance(props, null);
Provider[] providers = session.getProviders();
for( Provider p:providers ){
if( ! ("".equals(tmpStr)) )
tmpStr = tmpStr + ",";
tmpStr = tmpStr + p.getProtocol();
}
[You will see that the list of providers does not contain imaps on the server (8.5.3)]
Was going to comment, but rep isn't high enough yet....
Is the java agent in the same db?
If it is, can you cut it and try the xpage when the agent isn't there? Probably a long shot, but may be worth checking that the agent isn't interfering in any way.
You want to check out my article with a code sample how to read IMAP from Notes. I didn't run that code as agent, but from the command line. Chances are, that it will work better for you. Main difference (possibly?): I used the Google enhanced IMAP classes.
Check it out and let us know if that worked for you!

Resources