Create New Loopback Project, Install Dependencies and Create Datasource
Create a new Loopback project by issuing the command¬†apic loopback¬†(optional:¬†include¬†–explorer to test out APIs without using API Editor) and wait until the process completes.
loopback-component-passport¬†is an additional module for 3rd Party Authentication.¬†It is based upon PassportJS, a populer 3rd Party Authentication module for NodeJS.
passport-ldapauth¬†is a PassportJS Strategy module which enables authentication by LDAP. To learn more about Passport Strategies, refer to¬†http://passportjs.org/docs
As a reference, these are the latest version of the modules installed as per the time of writing (can be found in¬†package.json file)
Create a new datasource. In this Recipe I will be using MongoDB, but feel free to use any other database.
Create a new model,¬†user, which has a base class of¬†User. It is better to extend the¬†built-in¬†User¬†model rather than using it directly as we can create custom remote methods and add new properties (Creating custom methods are out of this Recipe's scope)
In¬†server/model-config.json, add¬†../node_modules/loopback-component-passport/lib/models to the array of sources. Also add¬†UserIdentity, UserCredential, AccessToken¬†and¬†ACL¬†to the list of models.
Create a new file with name¬†providers.json¬†in the project root directory.¬†A couple of important points to note:
- Feel free to assign any name. In this case, ldap¬†is used
- authScheme should be set to¬†ldap
- module should be set to¬†passport-ldapauth
- authPath is the path for the authentication. i.e. the front-end will send a POST request to <server_hostname>/auth/ldap consisting of the username and password
- successRedirect¬†is the path to be redirected to if authentication succeeds. However, this is overrided by¬†“json”: true.¬†“json”:true¬†will mean that Loopback will return a JSON response consisting of the token and userId¬†instead of redirecting. I find this is more useful as I will leave the redirection to be performed by the front-end
- failureRedirect¬†is the path to be redirected to if authentication fails
- session¬†is set to¬†false¬†as we will not be using session
- ldap_attribute_for_login/username/mail will¬†need to be matched to the LDAP server
- server¬†consists of an object with the LDAP server properties
Create Boot Scripts
Create a boot script in¬†server/boot. In this case, it is named ldapAuth.js. This script will create an instance of passportConfigurator, which will load the settings in providers.json¬†and an additional function named¬†createAccessToken¬†(do not rename) which enables us to override the default Token Time to Live (TTL) value (The Default value is 2 weeks).
Note in the function passportConfigurator.setupModels, the userModel¬†is mapped to user,¬†which is a new model which is based on the built-in¬†User¬†model
Create¬†a boot script to handle authentication failure path¬†redirection. Note that this path matches the¬†failureRedirect¬†property in¬†providers.json. If authentication fails, HTTP status 401 will be returned to the requester
Create a boot script to enable the server to only allow invoking APIs with authentication.
In server/server.js,¬†inject the body-parser and loopback.token middleware
body-parser¬†is a Node.JS middleware to parse JSON requests
loopback.token¬†will check for tokens in HTTP requests.
Start the server by running¬†node .¬†or¬†node server/server.js
Test out the request using an API Tester. In this example, I'm using Postman to simulate a POST request.¬†
Correct credentials will result in a token that is returned to the requester, which then can be attached in headers when invoking other APIs.
Let's take a look at what happened in the database:
A new AccessToken record (or document in MongoDB terms) is created. Note the TTL is 3600 (1 hour), not the default 2 weeks. Also note the id of the token and userId matches the response from Loopback
A new¬†UserIdentity¬†record¬†is also created. Note the userId in AccessToken and UserIdentity matches with id of user
¬†A¬†user¬†is automatically created in¬†user¬†table/collection
And that's it!!
A strict disclaimer is that passport-ldapauth¬†has an issue in which there is no error-handling if the LDAP server is unreachable (https://github.com/vesse/passport-ldapauth/issues/29)