├── .editorconfig ├── .github └── stale.yml ├── .gitignore ├── .istanbul.yml ├── .npmignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example ├── README.md └── app.js ├── lib ├── index.js └── verifier.js ├── mocha.opts ├── package-lock.json ├── package.json └── test └── index.test.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 84 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - greenkeeper 8 | - bug 9 | - security 10 | - enhancement 11 | # Label to use when marking an issue as stale 12 | staleLabel: wontfix 13 | # Comment to post when marking an issue as stale. Set to `false` to disable 14 | markComment: > 15 | This issue has been automatically marked as stale because it has not had 16 | recent activity. It will be closed if no further activity occurs. 17 | Apologies if the issue could not be resolved. FeathersJS ecosystem 18 | modules are community maintained so there may be a chance that there isn't anybody 19 | available to address the issue at the moment. 20 | For other ways to get help [see here](https://docs.feathersjs.com/help/readme.html). 21 | # Comment to post when closing a stale issue. Set to `false` to disable 22 | closeComment: false 23 | # Only close stale issues 24 | only: issues 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | # Commenting this out is preferred by some people, see 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 27 | node_modules 28 | 29 | # Users Environment Variables 30 | .lock-wscript 31 | 32 | # IDE 33 | .idea 34 | 35 | temp 36 | -------------------------------------------------------------------------------- /.istanbul.yml: -------------------------------------------------------------------------------- 1 | verbose: false 2 | instrumentation: 3 | root: ./lib/ 4 | include-all-sources: true 5 | reporting: 6 | print: summary 7 | reports: 8 | - html 9 | - text 10 | - lcov 11 | watermarks: 12 | statements: [50, 80] 13 | lines: [50, 80] 14 | functions: [50, 80] 15 | branches: [50, 80] 16 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .editorconfig 2 | .jshintrc 3 | .travis.yml 4 | .istanbul.yml 5 | .babelrc 6 | .idea/ 7 | .vscode/ 8 | test/ 9 | coverage/ 10 | .github/ 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 'node' 4 | - '6' 5 | install: npm install 6 | addons: 7 | code_climate: 8 | repo_token: 'your repo token' 9 | notifications: 10 | slack: feathersjs:T4tvpJFt27wJZABjLSg5OqMv 11 | email: false 12 | before_script: 13 | - npm install -g codeclimate-test-reporter 14 | after_script: 15 | - codeclimate-test-reporter < coverage/lcov.info 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [v0.2.3](https://github.com/feathersjs/feathers-authentication-ldap/tree/v0.2.3) (2017-03-28) 4 | [Full Changelog](https://github.com/feathersjs/feathers-authentication-ldap/compare/v0.2.2...v0.2.3) 5 | 6 | ## [v0.2.2](https://github.com/feathersjs/feathers-authentication-ldap/tree/v0.2.2) (2017-03-28) 7 | [Full Changelog](https://github.com/feathersjs/feathers-authentication-ldap/compare/v0.2.1...v0.2.2) 8 | 9 | **Closed issues:** 10 | 11 | - No ldap provider when used with feathers-cli generate [\#4](https://github.com/feathersjs/feathers-authentication-ldap/issues/4) 12 | 13 | **Merged pull requests:** 14 | 15 | - Update all dependencies 🌴 [\#7](https://github.com/feathersjs/feathers-authentication-ldap/pull/7) ([greenkeeperio-bot](https://github.com/greenkeeperio-bot)) 16 | - Updated deps [\#6](https://github.com/feathersjs/feathers-authentication-ldap/pull/6) ([psi-4ward](https://github.com/psi-4ward)) 17 | 18 | ## [v0.2.1](https://github.com/feathersjs/feathers-authentication-ldap/tree/v0.2.1) (2016-12-14) 19 | [Full Changelog](https://github.com/feathersjs/feathers-authentication-ldap/compare/v0.2.0...v0.2.1) 20 | 21 | ## [v0.2.0](https://github.com/feathersjs/feathers-authentication-ldap/tree/v0.2.0) (2016-12-14) 22 | [Full Changelog](https://github.com/feathersjs/feathers-authentication-ldap/compare/v0.1.0...v0.2.0) 23 | 24 | ## [v0.1.0](https://github.com/feathersjs/feathers-authentication-ldap/tree/v0.1.0) (2016-12-14) 25 | **Merged pull requests:** 26 | 27 | - Consistency touchups [\#3](https://github.com/feathersjs/feathers-authentication-ldap/pull/3) ([ekryski](https://github.com/ekryski)) 28 | - init [\#1](https://github.com/feathersjs/feathers-authentication-ldap/pull/1) ([psi-4ward](https://github.com/psi-4ward)) 29 | 30 | 31 | 32 | \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Feathers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # feathers-authentication-ldap 2 | 3 | [![Greenkeeper badge](https://badges.greenkeeper.io/feathersjs/feathers-authentication-ldap.svg)](https://greenkeeper.io/) 4 | 5 | [![Build Status](https://travis-ci.org/feathersjs/feathers-authentication-ldap.png?branch=master)](https://travis-ci.org/feathersjs/feathers-authentication-ldap) 6 | [![Code Climate](https://codeclimate.com/github/feathersjs/feathers-authentication-ldap/badges/gpa.svg)](https://codeclimate.com/github/feathersjs/feathers-authentication-ldap) 7 | [![Test Coverage](https://codeclimate.com/github/feathersjs/feathers-authentication-ldap/badges/coverage.svg)](https://codeclimate.com/github/feathersjs/feathers-authentication-ldap/coverage) 8 | [![Dependency Status](https://img.shields.io/david/feathersjs/feathers-authentication-ldap.svg?style=flat-square)](https://david-dm.org/feathersjs/feathers-authentication-ldap) 9 | [![Download Status](https://img.shields.io/npm/dm/feathers-authentication-ldap.svg?style=flat-square)](https://www.npmjs.com/package/feathers-authentication-ldap) 10 | 11 | > LDAP authentication strategy for feathers-authentication using Passport 12 | 13 | 14 | ## Installation 15 | 16 | ``` 17 | npm install feathers-authentication-ldap --save 18 | ``` 19 | 20 | ## Documentation 21 | 22 | ### Usage 23 | 24 | In most cases initializing the `feathers-authentication-ldap` module is as simple as doing this: 25 | 26 | ```js 27 | app.configure(authentication(settings)); 28 | app.configure(ldap()); 29 | ``` 30 | 31 | This will pull from your global `auth` object in your config file. 32 | It will also mix in the following defaults, which should be customized. 33 | 34 | #### Default Options 35 | 36 | ```js 37 | { 38 | name: 'ldap', 39 | server: { 40 | url: 'ldap://localhost:389', 41 | bindDn: 'cn=anonymous', 42 | bindCredentials: '', // bindpw 43 | searchBase: 'dc=de', 44 | searchFilter: '(uid={{username}})', 45 | searchAttributes: null // optional array of props to fetch from ldap 46 | }, 47 | passReqToCallback: true 48 | } 49 | ``` 50 | 51 | ### LDAP Verifier class 52 | 53 | The `Verifier` class has a `verify` function that is the passport verify callback. In this module it gets called after LDAP authentication succeeds. By default it does nothing but you can overwrite it to make furthers validation 54 | checks. See [examples/app.js](examples/app.js#L56). 55 | 56 | ### Usage with `feathers-authentication-jwt` 57 | 58 | To authenticate following requests using the jwt use `feathers-authentication-jwt`. This plugin depends on the `users` Service to populate the user entity. 59 | 60 | To get rid of this dependency and store necessary data in the JWT payload see 61 | [examples/app.js](examples/app.js#L47) and [examples/app.js](examples/app.js#L79). 62 | 63 | 64 | ### Asynchronous LDAP Strategy configuration 65 | 66 | Per request configuration of the LDAP strategy is supported by taking advantage of 67 | the passport-ldapauth [asynchronous configuration retrieval](https://github.com/vesse/passport-ldapauth#asynchronous-configuration-retrieval) 68 | feature. 69 | 70 | This makes it possible to adjust the LDAP settings based on the authentication 71 | request. I.E. An Active Directory server that uses the user's authentication 72 | credentials for binding in place of an anonymous user can leverage this feature 73 | by setting the server bind credentials to the credentials provided in the 74 | authentication request. 75 | 76 | To use the asynchronous settings method you include the _asyncOptions_ parameter 77 | when configuring the ldap strategy in the authentication service. The _asyncOptions_ 78 | parameter should be set to a function that accepts the authentication request object 79 | and returns a new object with settings that should be merged into the ldap 80 | settings. 81 | 82 | #### Example asyncOptions implementation in authentication service 83 | 84 | ```javascript 85 | /* 86 | Given the following authentication strategy configuration... 87 | 88 | "authentication": { 89 | "ldap": { 90 | "name": "ldap", 91 | "server": { 92 | "url": "ldap:///", 93 | "searchBase": "cn=users,dc=,dc=local", 94 | "searchFilter": "(|(userPrincipalName={{username}})(sAMAccountName={{username}}))", 95 | "searchAttributes": null 96 | }, 97 | "passRequestToCallback": true 98 | } 99 | }, 100 | */ 101 | 102 | const authentication = require('@feathersjs/authentication') 103 | const jwt = require('@feathersjs/authentication-jwt') 104 | const local = require('@feathersjs/authentication-local') 105 | const ldap = require('feathers-authentication-ldap') 106 | 107 | module.exports = (app) => { 108 | app 109 | .configure(authentication(app.get('authentication'))) 110 | .configure(jwt()) 111 | .configure(local()) 112 | // user credentials in authentication request used as the server bind credentials in ldap 113 | .configure(ldap({ 114 | asyncOptions: req => ({ server: { bindDn: req.body.username, bindCredentials: req.body.password } }) 115 | })) 116 | 117 | app.service('authentication').hooks({ 118 | before: { 119 | create: [ 120 | authentication.hooks.authenticate(['ldap', 'local', 'jwt']) 121 | ] 122 | } 123 | }); 124 | 125 | app.hooks({ 126 | before: { 127 | all: [authentication.hooks.authenticate('jwt')] 128 | } 129 | }); 130 | 131 | } 132 | ``` 133 | 134 | 135 | ## Simple Example 136 | 137 | Here's an example of a Feathers server that uses `feathers-authentication-ldap`. 138 | 139 | ```js 140 | const feathers = require('feathers'); 141 | const rest = require('feathers-rest'); 142 | const hooks = require('feathers-hooks'); 143 | const bodyParser = require('body-parser'); 144 | const errorHandler = require('feathers-errors/handler'); 145 | const errors = require('feathers-errors'); 146 | const auth = require('feathers-authentication'); 147 | const ldap = require('feathers-authentication-ldap'); 148 | 149 | // Initialize the application 150 | const app = feathers(); 151 | 152 | // Load configuration, usually done by feathers-configuration 153 | app.set('auth', { 154 | secret: "super secret", 155 | ldap: { 156 | name: 'ldap', 157 | server: { 158 | url: 'ldap://localhost:389', 159 | bindDn: 'cn=anonymous', 160 | bindCredentials: '', // bindpw 161 | searchBase: 'dc=de', 162 | searchFilter: '(uid={{username}})' 163 | }, 164 | passRequestToCallback: true 165 | } 166 | }); 167 | 168 | app.configure(rest()) 169 | .configure(hooks()) 170 | .use(bodyParser.json()) 171 | .use(bodyParser.urlencoded({ extended: true })) 172 | 173 | // Configure feathers-authentication with ldap 174 | .configure(auth(app.get('auth'))) 175 | .configure(ldap()) 176 | 177 | .use(errorHandler()); 178 | 179 | // Authenticate the user using the LDAP strategy 180 | // and if successful return a JWT. 181 | app.service('authentication').hooks({ 182 | before: { 183 | create: [ 184 | auth.hooks.authenticate('ldap') 185 | ] 186 | } 187 | }); 188 | 189 | app.listen(3030); 190 | console.log('Feathers authentication with LDAP auth started on 127.0.0.1:3030'); 191 | ``` 192 | 193 | ```shell 194 | # Request a token 195 | curl -H "Content-Type: application/json" \ 196 | -X POST \ 197 | -d '{"username":"ldap-user@example.com","password":"admin"}' \ 198 | http://localhost:3030/authentication 199 | ``` 200 | 201 | ## License 202 | 203 | Copyright (c) 2016 204 | 205 | Licensed under the [MIT license](LICENSE). 206 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # feathers-authentication-ldap Example 2 | 3 | This provides an example on how to use `feathers-authentication-ldap` to provide ldap authentication 4 | and get a JWT access token in return. 5 | 6 | 1. Configure your LDAP settings in `app.js` 7 | 2. Start the app by running `npm start` 8 | 3. Make a request using the authenticated user. 9 | 10 | ```bash 11 | curl -H "Content-Type: application/json" -X POST -d '{"username":"ldap-user@example.com","password":"admin"}' http://localhost:3030/authentication 12 | ``` 13 | -------------------------------------------------------------------------------- /example/app.js: -------------------------------------------------------------------------------- 1 | const feathers = require('feathers'); 2 | const rest = require('feathers-rest'); 3 | const hooks = require('feathers-hooks'); 4 | const bodyParser = require('body-parser'); 5 | const errorHandler = require('feathers-errors/handler'); 6 | const errors = require('feathers-errors'); 7 | const auth = require('feathers-authentication'); 8 | const jwt = require('feathers-authentication-jwt'); 9 | const ldap = require('../lib/index'); 10 | 11 | // Initialize the application 12 | const app = feathers(); 13 | 14 | // Load configuration, usually done by feathers-configuration 15 | app.set('auth', { 16 | secret: 'super secret', 17 | ldap: { 18 | server: { 19 | url: 'ldap://localhost:389', 20 | bindDn: 'cn=anonymous', 21 | bindCredentials: '', // bindpw 22 | searchBase: 'dc=de', 23 | searchFilter: '(uid={{username}})', 24 | searchAttributes: null // set an array of props to fetch from ldap 25 | } 26 | } 27 | }); 28 | 29 | class CustomVerifier { 30 | verify(req, user, done) { 31 | // ldap auth was successful 32 | console.log('LDAP User:', user); 33 | 34 | // add custom verification logic 35 | let valid = true; 36 | if (valid) { 37 | return done(null, user, {username: req.body.username}); 38 | } else { 39 | const err = new errors.Forbidden('Youre are not allowed'); 40 | return done(err); 41 | } 42 | } 43 | } 44 | 45 | app.configure(rest()) 46 | .configure(hooks()) 47 | // Needed for parsing bodies (login) 48 | .use(bodyParser.json()) 49 | .use(bodyParser.urlencoded({ extended: true })) 50 | 51 | // Configure feathers-authentication 52 | .configure(auth(app.get('auth'))) 53 | 54 | // Enable JWT auth 55 | .configure(jwt({ 56 | // Optional: Overwrite the JWT Verifier to disable 57 | // population from user service 58 | Verifier: ldap.JWTVerifier 59 | })) 60 | 61 | // Enable LDAP auth 62 | .configure(ldap({ 63 | // Optional: overwrite Verifier function 64 | Verifier: CustomVerifier 65 | })) 66 | 67 | .use(errorHandler()); 68 | 69 | 70 | // Authenticate the user using the LDAP strategy 71 | // and if successful return a JWT. 72 | app.service('authentication').hooks({ 73 | before: { 74 | create: [ 75 | auth.hooks.authenticate('ldap'), 76 | function(hook) { 77 | // store some user data in JWT payload 78 | hook.data.payload = { 79 | uid: hook.params.user.uid, 80 | name: hook.params.user.cn, 81 | mail: hook.params.user.mail 82 | }; 83 | return Promise.resolve(hook); 84 | } 85 | ] 86 | } 87 | }); 88 | 89 | app.listen(3030); 90 | console.log('Feathers authentication with LDAP auth started on 127.0.0.1:3030'); 91 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | const Debug = require('debug'); 2 | const merge = require('lodash.merge'); 3 | const omit = require('lodash.omit'); 4 | const DefaultVerifier = require('./verifier'); 5 | 6 | const passportLdap = require('passport-ldapauth'); 7 | 8 | const debug = Debug('feathers-authentication-ldap'); 9 | const defaults = { 10 | name: 'ldap', 11 | server: { 12 | url: 'ldap://localhost:389', 13 | bindDn: 'cn=anonymous', 14 | bindCredentials: '', 15 | searchBase: 'dc=de', 16 | searchFilter: '(uid={{username}})', 17 | searchAttributes: null 18 | }, 19 | passReqToCallback: true 20 | }; 21 | 22 | class JWTVerifier { 23 | // JWT Verifier replacement 24 | // to disable population from user service 25 | verify (req, payload, done) { 26 | done(null, { payload }); 27 | } 28 | } 29 | 30 | function init (options = {}) { 31 | return function ldapAuth () { 32 | const app = this; 33 | const _super = app.setup; 34 | 35 | if (!app.passport) { 36 | throw new Error(`Can not find app.passport. Did you initialize feathers-authentication before @feathersjs/authentication-ldap?`); 37 | } 38 | 39 | let name = options.name || defaults.name; 40 | let authOptions = app.get('authentication') || app.get('auth') || {}; 41 | let ldapOptions = authOptions[name] || {}; 42 | const ldapSettings = merge({}, defaults, ldapOptions, omit(options, ['Verifier, AsyncOptions'])); 43 | const asyncOptions = options.asyncOptions || null; 44 | let Verifier = DefaultVerifier; 45 | 46 | if (options.Verifier) { 47 | Verifier = options.Verifier; 48 | } 49 | 50 | // function to get dynamic settings when using asyncOptions in strategy 51 | const getLdapSettings = (req, passportCallback) => { 52 | passportCallback(null, merge({}, ldapSettings, asyncOptions(req))); 53 | }; 54 | 55 | app.setup = function () { 56 | let result = _super.apply(this, arguments); 57 | let verifier = new Verifier(app, ldapSettings); 58 | 59 | if (!verifier.verify) { 60 | throw new Error(`Your verifier must implement a 'verify' function. It should have the same signature as function(request, user, done)`); 61 | } 62 | 63 | debug('Registering ldap authentication strategy with options:', ldapSettings); 64 | app.passport.use(ldapSettings.name, new passportLdap.Strategy((asyncOptions ? getLdapSettings : ldapSettings), verifier.verify.bind(verifier))); 65 | app.passport.options(ldapSettings.name, ldapSettings); // do we need this ?? 66 | 67 | return result; 68 | }; 69 | }; 70 | } 71 | 72 | module.exports = init; 73 | 74 | // Exposed Modules 75 | Object.assign(module.exports, { 76 | default: init, 77 | defaults, 78 | Verifier: DefaultVerifier, 79 | JWTVerifier 80 | }); 81 | -------------------------------------------------------------------------------- /lib/verifier.js: -------------------------------------------------------------------------------- 1 | const Debug = require('debug'); 2 | 3 | const debug = Debug('feathers-authentication-ldap:verify'); 4 | 5 | class LdapVerifier { 6 | constructor (app, options = {}) { 7 | this.app = app; 8 | this.options = options; 9 | 10 | this.verify = this.verify.bind(this); 11 | } 12 | 13 | verify (req, user, done) { 14 | // no further validation, LDAP Account is valid 15 | debug('Received ldap user:', user); 16 | const payload = { username: req.body.username }; 17 | done(null, user, payload); 18 | } 19 | } 20 | 21 | module.exports = LdapVerifier; 22 | 23 | /* 24 | import Debug from 'debug'; 25 | 26 | const debug = Debug('feathers-authentication-ldap:verify'); 27 | 28 | class LDAPVerifier { 29 | constructor (app, options = {}) { 30 | this.app = app; 31 | this.options = options; 32 | 33 | this.verify = this.verify.bind(this); 34 | } 35 | 36 | verify (req, user, done) { 37 | // no further validation, LDAP Account is valid 38 | debug('Received ldap user:', user); 39 | const payload = { username: req.body.username }; 40 | done(null, user, payload); 41 | } 42 | } 43 | 44 | export default LDAPVerifier; 45 | */ 46 | -------------------------------------------------------------------------------- /mocha.opts: -------------------------------------------------------------------------------- 1 | --recursive test/ 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feathers-authentication-ldap", 3 | "description": "LDAP authentication strategy for feathers-authentication using Passport", 4 | "version": "0.3.0", 5 | "homepage": "https://github.com/feathersjs/feathers-authentication-ldap", 6 | "main": "lib/", 7 | "keywords": [ 8 | "feathers", 9 | "feathers-plugin", 10 | "feathers-authentication", 11 | "feathers-authentication-ldap", 12 | "ldap" 13 | ], 14 | "license": "MIT", 15 | "repository": { 16 | "type": "git", 17 | "url": "git://github.com/feathersjs/feathers-authentication-ldap.git" 18 | }, 19 | "author": { 20 | "name": "Christoph Wiechert", 21 | "email": "wio@psitrax.de" 22 | }, 23 | "contributors": [], 24 | "bugs": { 25 | "url": "https://github.com/feathersjs/feathers-authentication-ldap/issues" 26 | }, 27 | "engines": { 28 | "node": ">= 4.6.0" 29 | }, 30 | "scripts": { 31 | "publish": "git push origin --tags && npm run changelog && git push origin", 32 | "release:patch": "npm version patch && npm publish", 33 | "release:minor": "npm version minor && npm publish", 34 | "release:major": "npm version major && npm publish", 35 | "changelog": "github_changelog_generator && git add CHANGELOG.md && git commit -am \"Updating changelog\"", 36 | "lint": "semistandard --fix", 37 | "mocha": "mocha --opts mocha.opts", 38 | "coverage": "istanbul cover node_modules/mocha/bin/_mocha -- --opts mocha.opts", 39 | "test": "npm run lint && npm run coverage", 40 | "start": "node example/app" 41 | }, 42 | "semistandard": { 43 | "sourceType": "module", 44 | "env": [ 45 | "mocha" 46 | ] 47 | }, 48 | "directories": { 49 | "lib": "lib" 50 | }, 51 | "dependencies": { 52 | "debug": "^4.0.0", 53 | "lodash.merge": "^4.6.0", 54 | "lodash.omit": "^4.5.0", 55 | "passport-ldapauth": "^2.0.0" 56 | }, 57 | "devDependencies": { 58 | "body-parser": "^1.15.2", 59 | "chai": "^4.1.0", 60 | "feathers-authentication": "^1.0.0", 61 | "feathers-authentication-jwt": "^0.3.0", 62 | "feathers-memory": "^4.0.0", 63 | "feathers-rest": "^1.5.2", 64 | "feathers-hooks": "^2.0.0", 65 | "feathers": "^2.0.2", 66 | "istanbul": "^1.1.0-alpha.1", 67 | "sinon": "^9.0.0", 68 | "mocha": "^6.0.0", 69 | "semistandard": "^13.0.0", 70 | "sinon-chai": "^3.0.0" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-expressions */ 2 | 3 | const chai = require('chai'); 4 | const sinon = require('sinon'); 5 | const sinonChai = require('sinon-chai'); 6 | const ldapAuth = require('../lib'); 7 | const feathers = require('feathers'); 8 | const authentication = require('feathers-authentication'); 9 | const passportLdap = require('passport-ldapauth'); 10 | 11 | const expect = chai.expect; 12 | 13 | chai.use(sinonChai); 14 | 15 | describe('feathers-authentication-ldap', () => { 16 | it('is CommonJS compatible', () => { 17 | expect(typeof require('../lib')).to.equal('function'); 18 | }); 19 | 20 | it('basic functionality', () => { 21 | expect(typeof ldapAuth).to.equal('function'); 22 | expect(typeof ldapAuth()).to.equal('function'); 23 | }); 24 | 25 | it('exposes the default Verifier fn', () => { 26 | expect(typeof ldapAuth.Verifier).to.equal('function'); 27 | }); 28 | 29 | it('exposes the defaults obj', () => { 30 | expect(typeof ldapAuth.defaults).to.equal('object'); 31 | }); 32 | 33 | describe('defaultVerifier fn', () => { 34 | it('should cb without error', function (done) { 35 | let verifier = new ldapAuth.Verifier(); 36 | verifier.verify({body: {username: 'test'}}, {name: 'test'}, done); 37 | }); 38 | }); 39 | 40 | describe('jwtVerifier fn', () => { 41 | it('should cb without error', function (done) { 42 | let jwtVerifier = new ldapAuth.JWTVerifier(); 43 | jwtVerifier.verify({body: {username: 'test'}}, {name: 'test'}, done); 44 | }); 45 | }); 46 | 47 | describe('initialization', () => { 48 | let app; 49 | 50 | beforeEach(() => { 51 | app = feathers(); 52 | app.configure(authentication({secret: 'supersecret'})); 53 | }); 54 | 55 | it('throws an error if passport has not been registered', () => { 56 | expect(() => { 57 | feathers().configure(ldapAuth()); 58 | }).to.throw(); 59 | }); 60 | 61 | it('registers the ldap passport strategy', () => { 62 | sinon.spy(app.passport, 'use'); 63 | sinon.spy(passportLdap, 'Strategy'); 64 | app.configure(ldapAuth()); 65 | app.setup(); 66 | 67 | expect(passportLdap.Strategy).to.have.been.calledOnce; 68 | expect(app.passport.use).to.have.been.calledWith('ldap'); 69 | 70 | app.passport.use.restore(); 71 | passportLdap.Strategy.restore(); 72 | }); 73 | 74 | it('registers the strategy options', () => { 75 | sinon.spy(app.passport, 'options'); 76 | app.configure(ldapAuth()); 77 | app.setup(); 78 | 79 | expect(app.passport.options).to.have.been.calledOnce; 80 | 81 | app.passport.options.restore(); 82 | }); 83 | }); 84 | }); 85 | --------------------------------------------------------------------------------