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.

src/lib/tests/Authentication.test.js

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)