This is further work done based off of #7. The intent was to simplify the logic for the login api call by completely separating out the logic for the local auth from the ldap auth. This is definitely still WIP but outlines the approach I wanted to take. The original flow basically tried to do the ldap approach and then silently fail if that didn't work into the local flow. If that still failed, then the user was given the invalid login modal. The new flow is based off of 1) the user choosing which auth flow they want via tab, and 2) then the tabs changing the prop passed into the loginform (separated out into a component from where it was embedded within the page originally), which then 3) let's the form determine which api function to call.
Once I separated the auth flows, I made the local auth back to what it had originally been doing more or less. Work still remains on fixing up the ldap flow. Callbacks / event based programming makes it hard to deal with race conditions. The flow in #7 had a race condition where the connection to the ldap server occasionally closed before we were finished extracting all of the information we needed to do the auth.
I've run out of time, but I was going through and trying to more rigorously handle the callback stuff so that we would properly process errors and not have any race conditions. The key thing left is processing all the search entries probably by putting them into a data structure of some kind, and only choosing to do the user client bind -> tir user lookup/creation inside the res.on("end") callback. This'll also make it easier to determine if we run into an erroneous state (i.e. 2+ search entries means the provided ldap_searchfilter field didn't actually have unique results), the user doesn't exist on the ldap server, or if we discovered the one and only user which we then should try to log in.
https://github.com/rroemhild/docker-test-openldap/tree/master - the test ldap server that Heimdall uses in its own testing. I think it might be possible to make it work with LDAPS but didn't have the time to figure it out so I only tested it with normal LDAP.
https://github.com/mitre/heimdall2/blob/master/apps/backend/src/authn/ldap.strategy.ts - LDAP passport strategy we use in Heimdall. Passport doesn't seem to have an integration with nuxt3 as of yet. In fact, nuxt3 doesn't seem to have an official auth solution they support yet (https://auth.nuxtjs.org/) - they recommend some community libraries, but the first doesn't seem to support LDAP and the second looked like it was going to take a while to figure out how to make work with LDAP. We might want to transition to that one in the future as our replacement for Passport if the official auth doesn't come about soon / have a passport integration.
This was good for our initial LDAP start. To your point about a passport alternative, AuthJS Nuxt or even just using Auth.js looks like the best alternative.
This is further work done based off of #7. The intent was to simplify the logic for the login api call by completely separating out the logic for the local auth from the ldap auth. This is definitely still WIP but outlines the approach I wanted to take. The original flow basically tried to do the ldap approach and then silently fail if that didn't work into the local flow. If that still failed, then the user was given the invalid login modal. The new flow is based off of 1) the user choosing which auth flow they want via tab, and 2) then the tabs changing the prop passed into the loginform (separated out into a component from where it was embedded within the page originally), which then 3) let's the form determine which api function to call.
Once I separated the auth flows, I made the local auth back to what it had originally been doing more or less. Work still remains on fixing up the ldap flow. Callbacks / event based programming makes it hard to deal with race conditions. The flow in #7 had a race condition where the connection to the ldap server occasionally closed before we were finished extracting all of the information we needed to do the auth.
I've run out of time, but I was going through and trying to more rigorously handle the callback stuff so that we would properly process errors and not have any race conditions. The key thing left is processing all the search entries probably by putting them into a data structure of some kind, and only choosing to do the user client bind -> tir user lookup/creation inside the res.on("end") callback. This'll also make it easier to determine if we run into an erroneous state (i.e. 2+ search entries means the provided ldap_searchfilter field didn't actually have unique results), the user doesn't exist on the ldap server, or if we discovered the one and only user which we then should try to log in.
Useful links:
https://github.com/mitre/heimdall2/wiki/Environment-Variables-Configuration - explanation/use for all the ldap variables (straight copy paste from heimdall, but i put all the default values in the nuxt.config instead of at runtime like heimdall does)
https://github.com/rroemhild/docker-test-openldap/tree/master - the test ldap server that Heimdall uses in its own testing. I think it might be possible to make it work with LDAPS but didn't have the time to figure it out so I only tested it with normal LDAP.
https://github.com/mitre/heimdall2/blob/master/apps/backend/src/authn/ldap.strategy.ts - LDAP passport strategy we use in Heimdall. Passport doesn't seem to have an integration with nuxt3 as of yet. In fact, nuxt3 doesn't seem to have an official auth solution they support yet (https://auth.nuxtjs.org/) - they recommend some community libraries, but the first doesn't seem to support LDAP and the second looked like it was going to take a while to figure out how to make work with LDAP. We might want to transition to that one in the future as our replacement for Passport if the official auth doesn't come about soon / have a passport integration.
https://github.com/mitre/heimdall2/blob/6fd5fabbb052499aa10a372b3e66e9a3c4f0f93b/.github/workflows/e2e-ui-tests.yml - example of the docker-test-openldap lib being used. I want us to set up github CI similar to this so that we can start testing stuff. Ideally we try using Playwright instead of Cypress though.
http://ldapjs.org/client.html - ldapjs docs
https://github.com/ldapjs/node-ldapjs/tree/master - ldapjs repo
https://github.com/vesse/passport-ldapauth/blob/master/lib/passport-ldapauth/strategy.js - the logic for how the ldapjs passport strategy works. They use a wrapper library around ldapjs but the wrapper library doesn't seem to be maintained, and is using an old major version of ldapjs.
https://github.com/vesse/node-ldapauth-fork/blob/master/lib/ldapauth.js - the wrapper library, specifically all the code for dealing with ldapjs
https://tailwindui.com/components/application-ui/navigation/tabs - modified the tailwindui tabs component to change the variables around so that it would change the prop as opposed to navigate to a different page