|
| 1 | +// Copyright (c) Microsoft Corporation. |
| 2 | +// Licensed under the MIT License. |
| 3 | + |
1 | 4 | var createError = require('http-errors'); |
2 | 5 | var express = require('express'); |
3 | 6 | var path = require('path'); |
4 | 7 | var cookieParser = require('cookie-parser'); |
5 | 8 | var logger = require('morgan'); |
6 | 9 | var session = require('express-session'); |
7 | 10 | var flash = require('connect-flash'); |
| 11 | +require('dotenv').config(); |
| 12 | + |
| 13 | +var passport = require('passport'); |
| 14 | +var OIDCStrategy = require('passport-azure-ad').OIDCStrategy; |
| 15 | + |
| 16 | +// Configure passport |
| 17 | + |
| 18 | +// In-memory storage of logged-in users |
| 19 | +// For demo purposes only, production apps should store |
| 20 | +// this in a reliable storage |
| 21 | +var users = {}; |
| 22 | + |
| 23 | +// Passport calls serializeUser and deserializeUser to |
| 24 | +// manage users |
| 25 | +passport.serializeUser(function(user, done) { |
| 26 | + // Use the OID property of the user as a key |
| 27 | + users[user.profile.oid] = user; |
| 28 | + done (null, user.profile.oid); |
| 29 | +}); |
| 30 | + |
| 31 | +passport.deserializeUser(function(id, done) { |
| 32 | + done(null, users[id]); |
| 33 | +}); |
| 34 | + |
| 35 | +// <ConfigureOAuth2Snippet> |
| 36 | +// Configure simple-oauth2 |
| 37 | +const oauth2 = require('simple-oauth2').create({ |
| 38 | + client: { |
| 39 | + id: process.env.OAUTH_APP_ID, |
| 40 | + secret: process.env.OAUTH_APP_PASSWORD |
| 41 | + }, |
| 42 | + auth: { |
| 43 | + tokenHost: process.env.OAUTH_AUTHORITY, |
| 44 | + authorizePath: process.env.OAUTH_AUTHORIZE_ENDPOINT, |
| 45 | + tokenPath: process.env.OAUTH_TOKEN_ENDPOINT |
| 46 | + } |
| 47 | +}); |
| 48 | +// </ConfigureOAuth2Snippet> |
| 49 | + |
| 50 | +// Callback function called once the sign-in is complete |
| 51 | +// and an access token has been obtained |
| 52 | +// <SignInCompleteSnippet> |
| 53 | +async function signInComplete(iss, sub, profile, accessToken, refreshToken, params, done) { |
| 54 | + if (!profile.oid) { |
| 55 | + return done(new Error("No OID found in user profile.")); |
| 56 | + } |
| 57 | + |
| 58 | + try{ |
| 59 | + const user = await graph.getUserDetails(accessToken); |
| 60 | + |
| 61 | + if (user) { |
| 62 | + // Add properties to profile |
| 63 | + profile['email'] = user.mail ? user.mail : user.userPrincipalName; |
| 64 | + } |
| 65 | + } catch (err) { |
| 66 | + return done(err); |
| 67 | + } |
| 68 | + |
| 69 | + // Create a simple-oauth2 token from raw tokens |
| 70 | + let oauthToken = oauth2.accessToken.create(params); |
| 71 | + |
| 72 | + // Save the profile and tokens in user storage |
| 73 | + users[profile.oid] = { profile, accessToken }; |
| 74 | + return done(null, users[profile.oid]); |
| 75 | +} |
| 76 | +// </SignInCompleteSnippet> |
| 77 | + |
| 78 | +// Configure OIDC strategy |
| 79 | +passport.use(new OIDCStrategy( |
| 80 | + { |
| 81 | + identityMetadata: `${process.env.OAUTH_AUTHORITY}${process.env.OAUTH_ID_METADATA}`, |
| 82 | + clientID: process.env.OAUTH_APP_ID, |
| 83 | + responseType: 'code id_token', |
| 84 | + responseMode: 'form_post', |
| 85 | + redirectUrl: process.env.OAUTH_REDIRECT_URI, |
| 86 | + allowHttpForRedirectUrl: true, |
| 87 | + clientSecret: process.env.OAUTH_APP_PASSWORD, |
| 88 | + validateIssuer: false, |
| 89 | + passReqToCallback: false, |
| 90 | + scope: process.env.OAUTH_SCOPES.split(' ') |
| 91 | + }, |
| 92 | + signInComplete |
| 93 | +)); |
8 | 94 |
|
9 | 95 | var indexRouter = require('./routes/index'); |
10 | 96 | var usersRouter = require('./routes/users'); |
| 97 | +var authRouter = require('./routes/auth'); |
| 98 | +var graph = require('./graph'); |
11 | 99 |
|
12 | 100 | var app = express(); |
13 | 101 |
|
@@ -52,7 +140,23 @@ app.use(express.urlencoded({ extended: false })); |
52 | 140 | app.use(cookieParser()); |
53 | 141 | app.use(express.static(path.join(__dirname, 'public'))); |
54 | 142 |
|
| 143 | +// Initialize passport |
| 144 | +app.use(passport.initialize()); |
| 145 | +app.use(passport.session()); |
| 146 | + |
| 147 | +// <AddProfileSnippet> |
| 148 | +app.use(function(req, res, next) { |
| 149 | + // Set the authenticated user in the |
| 150 | + // template locals |
| 151 | + if (req.user) { |
| 152 | + res.locals.user = req.user.profile; |
| 153 | + } |
| 154 | + next(); |
| 155 | +}); |
| 156 | +// </AddProfileSnippet> |
| 157 | + |
55 | 158 | app.use('/', indexRouter); |
| 159 | +app.use('/auth', authRouter); |
56 | 160 | app.use('/users', usersRouter); |
57 | 161 |
|
58 | 162 | // catch 404 and forward to error handler |
|
0 commit comments