1
1
'use strict' ;
2
2
const express = require ( 'express' ) ;
3
- const basicAuth = require ( 'basic-auth' ) ;
4
3
const path = require ( 'path' ) ;
5
4
const packageJson = require ( 'package-json' ) ;
5
+ const csrf = require ( 'csurf' ) ;
6
+ const Authentication = require ( './Authentication.js' ) ;
6
7
var fs = require ( 'fs' ) ;
7
8
8
9
const currentVersionFeatures = require ( '../package.json' ) . parseDashboardFeatures ;
@@ -58,22 +59,27 @@ module.exports = function(config, allowInsecureHTTP) {
58
59
app . enable ( 'trust proxy' ) ;
59
60
}
60
61
62
+ const users = config . users ;
63
+ const useEncryptedPasswords = config . useEncryptedPasswords ? true : false ;
64
+ const authInstance = new Authentication ( users , useEncryptedPasswords ) ;
65
+ authInstance . initialize ( app ) ;
66
+
67
+ // CSRF error handler
68
+ app . use ( function ( err , req , res , next ) {
69
+ if ( err . code !== 'EBADCSRFTOKEN' ) return next ( err )
70
+
71
+ // handle CSRF token errors here
72
+ res . status ( 403 )
73
+ res . send ( 'form tampered with' )
74
+ } ) ;
75
+
61
76
// Serve the configuration.
62
77
app . get ( '/parse-dashboard-config.json' , function ( req , res ) {
63
78
let response = {
64
79
apps : config . apps ,
65
80
newFeaturesInLatestVersion : newFeaturesInLatestVersion ,
66
81
} ;
67
82
68
- const users = config . users ;
69
- const useEncryptedPasswords = config . useEncryptedPasswords ? true : false ;
70
-
71
- let auth = null ;
72
- //If they provide auth when their config has no users, ignore the auth
73
- if ( users ) {
74
- auth = basicAuth ( req ) ;
75
- }
76
-
77
83
//Based on advice from Doug Wilson here:
78
84
//https://github.com/expressjs/express/issues/2518
79
85
const requestIsLocal =
@@ -90,12 +96,10 @@ module.exports = function(config, allowInsecureHTTP) {
90
96
return res . send ( { success : false , error : 'Configure a user to access Parse Dashboard remotely' } ) ;
91
97
}
92
98
93
- let Authentication = require ( './Authentication' ) ;
94
- const authInstance = new Authentication ( users , useEncryptedPasswords ) ;
95
- const authentication = authInstance . authenticate ( auth ) ;
96
-
97
- const successfulAuth = authentication . isAuthenticated ;
98
- const appsUserHasAccess = authentication . appsUserHasAccessTo ;
99
+ const authentication = req . user ;
100
+
101
+ const successfulAuth = authentication && authentication . isAuthenticated ;
102
+ const appsUserHasAccess = authentication && authentication . appsUserHasAccessTo ;
99
103
100
104
if ( successfulAuth ) {
101
105
if ( appsUserHasAccess ) {
@@ -111,9 +115,8 @@ module.exports = function(config, allowInsecureHTTP) {
111
115
return res . json ( response ) ;
112
116
}
113
117
114
- if ( users || auth ) {
118
+ if ( users ) {
115
119
//They provided incorrect auth
116
- res . set ( 'WWW-Authenticate' , 'Basic realm=Authorization Required' ) ;
117
120
return res . sendStatus ( 401 ) ;
118
121
}
119
122
@@ -146,8 +149,42 @@ module.exports = function(config, allowInsecureHTTP) {
146
149
}
147
150
}
148
151
152
+ app . get ( '/login' , csrf ( ) , function ( req , res ) {
153
+ if ( ! users || ( req . user && req . user . isAuthenticated ) ) {
154
+ return res . redirect ( '/apps' ) ;
155
+ }
156
+ let mountPath = getMount ( req ) ;
157
+ let errors = req . flash ( 'error' ) ;
158
+ if ( errors && errors . length ) {
159
+ errors = `<div id="login_errors" style="display: none;">
160
+ ${ errors . join ( ' ' ) }
161
+ </div>`
162
+ }
163
+ res . send ( `<!DOCTYPE html>
164
+ <head>
165
+ <link rel="shortcut icon" type="image/x-icon" href="${ mountPath } favicon.ico" />
166
+ <base href="${ mountPath } "/>
167
+ <script>
168
+ PARSE_DASHBOARD_PATH = "${ mountPath } ";
169
+ </script>
170
+ </head>
171
+ <html>
172
+ <title>Parse Dashboard</title>
173
+ <body>
174
+ <div id="login_mount"></div>
175
+ ${ errors }
176
+ <script id="csrf" type="application/json">"${ req . csrfToken ( ) } "</script>
177
+ <script src="${ mountPath } bundles/login.bundle.js"></script>
178
+ </body>
179
+ </html>
180
+ ` ) ;
181
+ } ) ;
182
+
149
183
// For every other request, go to index.html. Let client-side handle the rest.
150
184
app . get ( '/*' , function ( req , res ) {
185
+ if ( users && ( ! req . user || ! req . user . isAuthenticated ) ) {
186
+ return res . redirect ( '/login' ) ;
187
+ }
151
188
let mountPath = getMount ( req ) ;
152
189
res . send ( `<!DOCTYPE html>
153
190
<head>
0 commit comments