Closed giraffesyo closed 3 years ago
Hey there,
I was trying to do this a couple of days ago as well, I managed to get the following piece of code working (connecting to a local OpenLDAP server using LDAPJS) However I'm no longer working on that particular project, so can't guarantee this is long-term the best way of doing this. Hopefully this will get you started though:
const ldap = require("ldapjs");
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
const options = {
providers: [
Providers.Credentials({
name: "LDAP",
credentials: {
username: { label: "DN", type: "text", placeholder: "" },
password: { label: "Password", type: "password" },
},
authorize: async (credentials) => {
// You might want to pull this call out so we're not making a new LDAP client on every login attemp
const client = ldap.createClient({
url: process.env.LDAP_URI,
});
// Essentially promisify the LDAPJS client.bind function
return new Promise((resolve, reject) => {
client.bind(credentials.username, credentials.password, (error) => {
if (error) {
console.error("Failed");
reject();
} else {
console.log("Logged in");
resolve({
username: credentials.username,
password: credentials.password,
});
}
});
});
},
}),
],
callbacks: {
jwt: async (token, user, account, profile, isNewUser) => {
const isSignIn = user ? true : false;
if (isSignIn) {
token.username = user.username;
token.password = user.password;
}
return token;
},
session: async (session, user) => {
return { ...session, user: { username: user.username } };
},
},
secret: process.env.NEXT_AUTH_SECRET,
jwt: {
secret: process.env.NEXT_AUTH_SECRET,
encryption: true, // Very important to encrypt the JWT, otherwise you're leaking username+password into the browser
},
};
export default (req, res) => NextAuth(req, res, options);
The idea is that once we've authenticated with the LDAP server, we pass through both the username/DN and password to the JWT stored in the browser. This is then passed back to any API routes and retrieved as such:
// ./pages/api/doLDAPWork.js
token = await jwt.getToken({
req,
secret: process.env.NEXT_AUTH_SECRET,
});
const {username, password} = token;
And you can now use this username/password to talk to your LDAP server through LDAPJS.
Again, this may not be best practise, I didn't have loads of time to consider all the possible aspects of this - I'm leaving this here purely as a starting point that hopefully you can improve upon :)
@Winwardo Thank you for this! This exactly the intended approach (including encrypting the JWT if storing a password in it!).
I am glad it was at least clear to someone what the intention of the callbacks is! 😂
It would be great to have this as a tutorial for other folks if anyone fancies writing it up! :-)
Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep ot open. Thanks!
Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!
We are currently trying to implement LDAP and the example seems to be outdated, since some APIs have changed. Is there any plans to update the example in the docs?
I'm trying to implement LDAP authentication in Next.js. Is there an example out there of this? I only saw it mentioned but couldn't find anything concrete in the docs.