3 var passport
= require('passport'),
4 path
= require('path'),
5 safe
= require('safetydance'),
7 bcrypt
= require('bcryptjs'),
8 uuid
= require('uuid/v4'),
9 BearerStrategy
= require('passport-http-bearer').Strategy
,
10 ldapjs
= require('ldapjs'),
11 HttpError
= require('connect-lastmile').HttpError
,
12 HttpSuccess
= require('connect-lastmile').HttpSuccess
,
13 webdavErrors
= require('webdav-server').v2
.Errors
;
15 const LDAP_URL
= process
.env
.CLOUDRON_LDAP_URL
;
16 const LDAP_USERS_BASE_DN
= process
.env
.CLOUDRON_LDAP_USERS_BASE_DN
;
17 const LOCAL_AUTH_FILE
= path
.resolve(process
.env
.LOCAL_AUTH_FILE
|| './.users.json');
18 const TOKENSTORE_FILE
= path
.resolve(process
.env
.TOKENSTORE_FILE
|| './.tokens.json');
19 const AUTH_METHOD
= (LDAP_URL
&& LDAP_USERS_BASE_DN
) ? 'ldap' : 'local';
21 if (AUTH_METHOD
=== 'ldap') {
22 console
.log('Use ldap auth');
24 console
.log(`Use local auth file ${LOCAL_AUTH_FILE}`);
31 fs
.writeFileSync(TOKENSTORE_FILE
, JSON
.stringify(tokenStore
.data
), 'utf-8');
33 console
.error(`Unable to save tokenstore file at ${TOKENSTORE_FILE}`, e
);
36 get: function (token
, callback
) {
37 callback(tokenStore
.data
[token
] ? null : 'not found', tokenStore
.data
[token
]);
39 set: function (token
, data
, callback
) {
40 tokenStore
.data
[token
] = data
;
44 del: function (token
, callback
) {
45 delete tokenStore
.data
[token
];
51 // load token store data if any
53 console
.log(`Using tokenstore file: ${TOKENSTORE_FILE}`);
54 tokenStore
.data
= JSON
.parse(fs
.readFileSync(TOKENSTORE_FILE
, 'utf-8'));
56 // start with empty token store
59 function issueAccessToken() {
60 return function (req
, res
, next
) {
61 var accessToken
= uuid();
63 tokenStore
.set(accessToken
, req
.user
, function (error
) {
64 if (error
) return next(new HttpError(500, error
));
65 next(new HttpSuccess(201, { accessToken: accessToken
, user: req
.user
}));
70 passport
.serializeUser(function (user
, done
) {
71 console
.log('serializeUser', user
);
75 passport
.deserializeUser(function (id
, done
) {
76 console
.log('deserializeUser', id
);
77 done(null, { uid: id
});
80 function verifyUser(username
, password
, callback
) {
81 if (AUTH_METHOD
=== 'ldap') {
82 var ldapClient
= ldapjs
.createClient({ url: process
.env
.CLOUDRON_LDAP_URL
});
83 ldapClient
.on('error', function (error
) {
84 console
.error('LDAP error', error
);
87 ldapClient
.bind(process
.env
.CLOUDRON_LDAP_BIND_DN
, process
.env
.CLOUDRON_LDAP_BIND_PASSWORD
, function (error
) {
88 if (error
) return callback(error
);
90 var filter
= `(|(uid=${username})(mail=${username})(username=${username})(sAMAccountName=${username}))`;
91 ldapClient
.search(process
.env
.CLOUDRON_LDAP_USERS_BASE_DN
, { filter: filter
}, function (error
, result
) {
92 if (error
) return callback(error
);
96 result
.on('searchEntry', function(entry
) { items
.push(entry
.object
); });
97 result
.on('error', callback
);
98 result
.on('end', function (result
) {
99 if (result
.status
!== 0 || items
.length
=== 0) return callback('Invalid credentials');
101 // pick the first found
104 ldapClient
.bind(user
.dn
, password
, function (error
) {
105 if (error
) return callback('Invalid credentials');
107 callback(null, { username: username
});
113 var users
= safe
.JSON
.parse(safe
.fs
.readFileSync(LOCAL_AUTH_FILE
));
114 if (!users
|| !users
[username
]) return callback('Invalid credentials');
116 bcrypt
.compare(password
, users
[username
].passwordHash
, function (error
, valid
) {
117 if (error
|| !valid
) return callback('Invalid credentials');
119 callback(null, { username: username
});
125 function (req
, res
, next
) {
126 verifyUser(req
.body
.username
, req
.body
.password
, function (error
, user
) {
127 if (error
) return next(new HttpError(401, 'Invalid credentials'));
137 exports
.verify
= passport
.authenticate('bearer', { session: false });
139 passport
.use(new BearerStrategy(function (token
, done
) {
140 tokenStore
.get(token
, function (error
, result
) {
142 console
.error(error
);
143 return done(null, false);
146 done(null, result
, { accessToken: token
});
150 exports
.logout = function (req
, res
, next
) {
151 tokenStore
.del(req
.authInfo
.accessToken
, function (error
) {
152 if (error
) console
.error(error
);
154 next(new HttpSuccess(200, {}));
158 exports
.getProfile = function (req
, res
, next
) {
159 next(new HttpSuccess(200, { username: req
.user
.username
}));
162 // webdav usermanager
163 exports
.WebdavUserManager
= WebdavUserManager
;
165 // This implements the required interface only for the Basic Authentication for webdav-server
166 function WebdavUserManager() {};
168 WebdavUserManager
.prototype.getDefaultUser = function (callback
) {
169 // this is only a dummy user, since we always require authentication
171 username: 'DefaultUser',
173 isAdministrator: false,
181 WebdavUserManager
.prototype.getUserByNamePassword = function (username
, password
, callback
) {
182 verifyUser(username
, password
, function (error
, user
) {
183 if (error
) return callback(webdavErrors
.UserNotFound
);
186 username: user
.username
,
187 isAdministrator: true,
188 isDefaultUser: false,