Skip to content

Commit b109183

Browse files
dvanwinkledrew-gross
authored andcommitted
Made the encrypted passwords an option (#510)
* Made the encrypted passwords an option * encrypted-passwords: Made Authentication into a module and added tests * encrypted-passwords: Added a couple more authentication tests
1 parent b84f953 commit b109183

File tree

4 files changed

+136
-23
lines changed

4 files changed

+136
-23
lines changed

Parse-Dashboard/Authentication.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
function Authentication(validUsers, useEncryptedPasswords) {
2+
this.validUsers = validUsers;
3+
this.useEncryptedPasswords = useEncryptedPasswords || false;
4+
}
5+
6+
Authentication.prototype.authenticate = function (userToTest) {
7+
let bcrypt = require('bcryptjs');
8+
9+
var appsUserHasAccessTo = null;
10+
11+
//they provided auth
12+
let isAuthenticated = userToTest &&
13+
//there are configured users
14+
this.validUsers &&
15+
//the provided auth matches one of the users
16+
this.validUsers.find(user => {
17+
let isAuthenticated = userToTest.name == user.user &&
18+
(this.useEncryptedPasswords ? bcrypt.compareSync(userToTest.pass, user.pass) : userToTest.pass == user.pass);
19+
if (isAuthenticated) {
20+
// User restricted apps
21+
appsUserHasAccessTo = user.apps || null;
22+
}
23+
24+
return isAuthenticated
25+
}) ? true : false;
26+
27+
return {
28+
isAuthenticated,
29+
appsUserHasAccessTo
30+
}
31+
}
32+
33+
module.exports = Authentication;

Parse-Dashboard/app.js

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module.exports = function(config, allowInsecureHTTP) {
6161
};
6262

6363
const users = config.users;
64+
const useEncryptedPasswords = config.useEncryptedPasswords ? true : false;
6465

6566
let auth = null;
6667
//If they provide auth when their config has no users, ignore the auth
@@ -84,29 +85,15 @@ module.exports = function(config, allowInsecureHTTP) {
8485
return res.send({ success: false, error: 'Configure a user to access Parse Dashboard remotely' });
8586
}
8687

87-
let appsUserHasAccess = null;
88-
let bcrypt = require('bcryptjs');
89-
90-
const successfulAuth =
91-
//they provided auth
92-
auth &&
93-
//there are configured users
94-
users &&
95-
//the provided auth matches one of the users
96-
users.find(user => {
97-
let isAuthorized = user.user == auth.name &&
98-
(user.pass == auth.pass ||
99-
bcrypt.compareSync(auth.pass, user.pass));
100-
if (isAuthorized) {
101-
// User restricted apps
102-
appsUserHasAccess = user.apps
103-
}
104-
105-
return isAuthorized
106-
});
88+
let Authentication = require('./Authentication');
89+
const authInstance = new Authentication(users, useEncryptedPasswords);
90+
const authentication = authInstance.authenticate(auth);
91+
92+
const successfulAuth = authentication.isAuthenticated;
93+
const appsUserHasAccess = authentication.appsUserHasAccessTo;
10794

10895
if (successfulAuth) {
109-
if(appsUserHasAccess) {
96+
if (appsUserHasAccess) {
11097
// Restric access to apps defined in user dictionary
11198
// If they didn't supply any app id, user will access all apps
11299
response.apps = response.apps.filter(function (app) {

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,13 @@ You can configure your dashboard for Basic Authentication by adding usernames an
230230
"user":"user2",
231231
"pass":"pass"
232232
}
233-
]
233+
],
234+
"useEncryptedPasswords": true | false
234235
}
235236
```
236237

237-
You can store the password in either `plain text` or `bcrypt` formats. You can encrypt the password using any online bcrypt tool e.g. [https://www.bcrypt-generator.com](https://www.bcrypt-generator.com).
238+
You can store the password in either `plain text` or `bcrypt` formats. To use the `bcrypt` format, you must set the config `useEncryptedPasswords` parameter to `true`.
239+
You can encrypt the password using any online bcrypt tool e.g. [https://www.bcrypt-generator.com](https://www.bcrypt-generator.com).
238240

239241
### Separating App Access Based on User Identity
240242
If you have configured your dashboard to manage multiple applications, you can restrict the management of apps based on user identity.
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) 2016-present, Parse, LLC
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the LICENSE file in
6+
* the root directory of this source tree.
7+
*/
8+
jest.dontMock('../../../Parse-Dashboard/Authentication.js');
9+
jest.dontMock('bcryptjs');
10+
11+
const Authentication = require('../../../Parse-Dashboard/Authentication');
12+
const apps = [{appId: 'test123'}, {appId: 'test789'}];
13+
const unencryptedUsers = [
14+
{
15+
user: 'parse.dashboard',
16+
pass: 'abc123'
17+
},
18+
{
19+
user: 'parse.apps',
20+
pass: 'xyz789',
21+
apps: apps
22+
}
23+
];
24+
const encryptedUsers = [
25+
{
26+
user: 'parse.dashboard',
27+
pass: '$2a$08$w92YfzwkhB3WGFTBjHwZLO2tSwNIS2rX0qQER.TF8izEzWF5M.U8S'
28+
},
29+
{
30+
user: 'parse.apps',
31+
pass: '$2a$08$B666bpJqE9v/R5KNbgfOMOjycvHzv6zWs0sGky/QuBZb4HY0M6LE2',
32+
apps: apps
33+
}
34+
]
35+
36+
function createAuthenticationResult(isAuthenticated, appsUserHasAccessTo) {
37+
return {
38+
isAuthenticated,
39+
appsUserHasAccessTo
40+
}
41+
}
42+
43+
describe('Authentication', () => {
44+
it('does not authenticate with no users', () => {
45+
let authentication = new Authentication(null, false);
46+
expect(authentication.authenticate({name: 'parse.dashboard', pass: 'abc123'}))
47+
.toEqual(createAuthenticationResult(false, null));
48+
});
49+
50+
it('does not authenticate with no auth', () => {
51+
let authentication = new Authentication(unencryptedUsers, false);
52+
expect(authentication.authenticate(null))
53+
.toEqual(createAuthenticationResult(false, null));
54+
});
55+
56+
it('does not authenticate invalid user', () => {
57+
let authentication = new Authentication(unencryptedUsers, false);
58+
expect(authentication.authenticate({name: 'parse.invalid', pass: 'abc123'}))
59+
.toEqual(createAuthenticationResult(false, null));
60+
});
61+
62+
it('does not authenticate valid user with invalid unencrypted password', () => {
63+
let authentication = new Authentication(unencryptedUsers, false);
64+
expect(authentication.authenticate({name: 'parse.dashboard', pass: 'xyz789'}))
65+
.toEqual(createAuthenticationResult(false, null));
66+
});
67+
68+
it('authenticates valid user with valid unencrypted password', () => {
69+
let authentication = new Authentication(unencryptedUsers, false);
70+
expect(authentication.authenticate({name: 'parse.dashboard', pass: 'abc123'}))
71+
.toEqual(createAuthenticationResult(true, null));
72+
});
73+
74+
it('returns apps if valid user', () => {
75+
let authentication = new Authentication(unencryptedUsers, false);
76+
expect(authentication.authenticate({name: 'parse.apps', pass: 'xyz789'}))
77+
.toEqual(createAuthenticationResult(true, apps));
78+
});
79+
80+
it('authenticates valid user with valid encrypted password', () => {
81+
let authentication = new Authentication(encryptedUsers, true);
82+
expect(authentication.authenticate({name: 'parse.dashboard', pass: 'abc123'}))
83+
.toEqual(createAuthenticationResult(true, null));
84+
});
85+
86+
it('does not authenticate valid user with invalid encrypted password', () => {
87+
let authentication = new Authentication(encryptedUsers, true);
88+
expect(authentication.authenticate({name: 'parse.dashboard', pass: 'xyz789'}))
89+
.toEqual(createAuthenticationResult(false, null));
90+
});
91+
});

0 commit comments

Comments
 (0)