1
1
const express = require ( 'express' ) ;
2
2
const morgan = require ( 'morgan' ) ;
3
3
const cors = require ( 'cors' ) ;
4
+
4
5
const passport = require ( 'passport' ) ;
6
+ const passportAzureAd = require ( 'passport-azure-ad' ) ;
5
7
6
- const config = require ( './authConfig' ) ;
8
+ const authConfig = require ( './authConfig' ) ;
7
9
const router = require ( './routes/router' ) ;
10
+
8
11
const routeGuard = require ( './utils/guard' ) ;
9
12
10
- const BearerStrategy = require ( 'passport-azure-ad' ) . BearerStrategy ;
11
-
12
- const options = {
13
- identityMetadata : `https://${ config . metadata . authority } /${ config . credentials . tenantID } /${ config . metadata . version } /${ config . metadata . discovery } ` ,
14
- issuer : `https://${ config . metadata . authority } /${ config . credentials . tenantID } /${ config . metadata . version } ` ,
15
- clientID : config . credentials . clientID ,
16
- audience : config . credentials . clientID , // audience is this application
17
- validateIssuer : config . settings . validateIssuer ,
18
- passReqToCallback : config . settings . passReqToCallback ,
19
- loggingLevel : config . settings . loggingLevel ,
20
- } ;
21
-
22
- const bearerStrategy = new BearerStrategy ( options , ( token , done ) => {
23
- // Send user info using the second argument
24
- done ( null , { } , token ) ;
25
- } ) ;
13
+ const { requiredScopeOrAppPermission } = require ( './auth/permissionUtils' ) ;
26
14
27
15
const app = express ( ) ;
28
16
17
+ /**
18
+ * Enable CORS middleware. In production, modify as to allow only designated origins and methods.
19
+ * If you are using Azure App Service, we recommend removing the line below and configure CORS on the App Service itself.
20
+ */
21
+ app . use ( cors ( ) ) ;
22
+
29
23
app . use ( morgan ( 'dev' ) ) ;
24
+ app . use ( express . urlencoded ( { extended : false } ) ) ;
30
25
app . use ( express . json ( ) ) ;
31
- app . use ( cors ( ) ) ;
26
+
27
+ const bearerStrategy = new passportAzureAd . BearerStrategy (
28
+ {
29
+ identityMetadata : `https://${ authConfig . metadata . authority } /${ authConfig . credentials . tenantID } /${ authConfig . metadata . version } /${ authConfig . metadata . discovery } ` ,
30
+ issuer : `https://${ authConfig . metadata . authority } /${ authConfig . credentials . tenantID } /${ authConfig . metadata . version } ` ,
31
+ clientID : authConfig . credentials . clientID ,
32
+ audience : authConfig . credentials . clientID , // audience is this application
33
+ validateIssuer : authConfig . settings . validateIssuer ,
34
+ passReqToCallback : authConfig . settings . passReqToCallback ,
35
+ loggingLevel : authConfig . settings . loggingLevel ,
36
+ loggingNoPII : authConfig . settings . loggingNoPII ,
37
+ } ,
38
+ ( req , token , done ) => {
39
+ /**
40
+ * Below you can do extended token validation and check for additional claims, such as:
41
+ * - check if the caller's tenant is in the allowed tenants list via the 'tid' claim (for multi-tenant applications)
42
+ * - check if the caller's account is homed or guest via the 'acct' optional claim
43
+ * - check if the caller belongs to right roles or groups via the 'roles' or 'groups' claim, respectively
44
+ *
45
+ * Bear in mind that you can do any of the above checks within the individual routes and/or controllers as well.
46
+ * For more information, visit: https://docs.microsoft.com/azure/active-directory/develop/access-tokens#validate-the-user-has-permission-to-access-this-data
47
+ */
48
+ if (
49
+ requiredScopeOrAppPermission ( token , [
50
+ ...authConfig . protectedRoutes . todolist . delegatedPermissions . read ,
51
+ ...authConfig . protectedRoutes . todolist . delegatedPermissions . write ,
52
+ ...authConfig . protectedRoutes . todolist . applicationPermissions . read ,
53
+ ...authConfig . protectedRoutes . todolist . applicationPermissions . write ,
54
+ ] )
55
+ ) {
56
+ /**
57
+ * If needed, pass down additional user info to route using the second argument below.
58
+ * This information will be available in the req.user object.
59
+ */
60
+ return done ( null , { } , token ) ;
61
+ } else {
62
+ return done ( new Error ( 'Unauthorized' ) , { } , 'Unauthorized' ) ;
63
+ }
64
+ }
65
+ ) ;
32
66
33
67
app . use ( passport . initialize ( ) ) ;
34
68
35
69
passport . use ( bearerStrategy ) ;
36
70
37
71
// Validates token, checks for role and serve
38
- app . use ( '/api' ,
39
- passport . authenticate ( 'oauth-bearer' , { session : false } ) ,
40
- routeGuard ( config . accessMatrix ) ,
72
+ app . use (
73
+ '/api' ,
74
+ passport . authenticate ( 'oauth-bearer' , {
75
+ session : false ,
76
+ /**
77
+ * If you are building a multi-tenant application and you need supply the tenant ID or name dynamically, uncomment
78
+ * the line below and pass in the tenant information. For more information, see:
79
+ * https://github.com/AzureAD/passport-azure-ad#423-options-available-for-passportauthenticate
80
+ */
81
+
82
+ // tenantIdOrName: <some-tenant-id-or-name>
83
+ } ) ,
84
+ routeGuard ( authConfig . accessMatrix ) ,
41
85
router
42
86
) ;
43
87
@@ -47,4 +91,4 @@ app.listen(port, () => {
47
91
console . log ( 'Listening on port ' + port ) ;
48
92
} ) ;
49
93
50
- module . exports = app ;
94
+ module . exports = app ;
0 commit comments