11'use strict' ;
22const express = require ( 'express' ) ;
3- const basicAuth = require ( 'basic-auth' ) ;
43const path = require ( 'path' ) ;
54const packageJson = require ( 'package-json' ) ;
5+ const csrf = require ( 'csurf' ) ;
6+ const Authentication = require ( './Authentication.js' ) ;
67var fs = require ( 'fs' ) ;
78
89const currentVersionFeatures = require ( '../package.json' ) . parseDashboardFeatures ;
@@ -58,22 +59,27 @@ module.exports = function(config, allowInsecureHTTP) {
5859 app . enable ( 'trust proxy' ) ;
5960 }
6061
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+
6176 // Serve the configuration.
6277 app . get ( '/parse-dashboard-config.json' , function ( req , res ) {
6378 let response = {
6479 apps : config . apps ,
6580 newFeaturesInLatestVersion : newFeaturesInLatestVersion ,
6681 } ;
6782
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-
7783 //Based on advice from Doug Wilson here:
7884 //https://github.com/expressjs/express/issues/2518
7985 const requestIsLocal =
@@ -90,12 +96,10 @@ module.exports = function(config, allowInsecureHTTP) {
9096 return res . send ( { success : false , error : 'Configure a user to access Parse Dashboard remotely' } ) ;
9197 }
9298
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 ;
99103
100104 if ( successfulAuth ) {
101105 if ( appsUserHasAccess ) {
@@ -111,9 +115,8 @@ module.exports = function(config, allowInsecureHTTP) {
111115 return res . json ( response ) ;
112116 }
113117
114- if ( users || auth ) {
118+ if ( users ) {
115119 //They provided incorrect auth
116- res . set ( 'WWW-Authenticate' , 'Basic realm=Authorization Required' ) ;
117120 return res . sendStatus ( 401 ) ;
118121 }
119122
@@ -146,8 +149,42 @@ module.exports = function(config, allowInsecureHTTP) {
146149 }
147150 }
148151
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+
149183 // For every other request, go to index.html. Let client-side handle the rest.
150184 app . get ( '/*' , function ( req , res ) {
185+ if ( users && ( ! req . user || ! req . user . isAuthenticated ) ) {
186+ return res . redirect ( '/login' ) ;
187+ }
151188 let mountPath = getMount ( req ) ;
152189 res . send ( `<!DOCTYPE html>
153190 <head>
0 commit comments