App di web AD Node.js Azure Guida introduttivaAzure AD Node.js web app getting started

Passport viene usato per:Here we use Passport to:

  • Far accedere l'utente all'app con Azure Active Directory (Azure AD).Sign the user in to the app with Azure Active Directory (Azure AD).
  • Visualizzare informazioni relative all'utente.Display information about the user.
  • Disconnettere l'utente dall'app.Sign the user out of the app.

Passport è il middleware di autenticazione per Node.js.Passport is authentication middleware for Node.js. Passport, flessibile e modulare, può essere rilasciato in modo non invadente in qualsiasi applicazione Web basata su Express o restify.Flexible and modular, Passport can be unobtrusively dropped in to any Express-based or restify web application. Una gamma completa di strategie supporta l'autenticazione mediante nome utente e password, Facebook, Twitter e altro ancora.A comprehensive set of strategies support authentication that uses a username and password, Facebook, Twitter, and more. È stata sviluppata una strategia per Microsoft Azure Active Directory.We have developed a strategy for Microsoft Azure Active Directory. Dopo l'installazione di questo modulo, verrà aggiunto il plug-in passport-azure-ad di Microsoft Azure Active Directory.We install this module and then add the Microsoft Azure Active Directory passport-azure-ad plug-in.

Per effettuare questa operazione, eseguire i passaggi seguenti:To do this, take the following steps:

  1. Registrare un'app.Register an app.
  2. Configurare l'app in modo che usi la strategia passport-azure-ad.Set up your app to use the passport-azure-ad strategy.
  3. Usare Passport per inviare le richieste di accesso e disconnessione ad Azure AD.Use Passport to issue sign-in and sign-out requests to Azure AD.
  4. Stampare dati relativi all'utente.Print data about the user.

Il codice per questa esercitazione è salvato su GitHub.The code for this tutorial is maintained on GitHub. Per seguire la procedura, è possibile scaricare la struttura dell'app come file .zip o clonare la struttura:To follow along, you can download the app's skeleton as a .zip file or clone the skeleton:

git clone --branch skeleton https://github.com/AzureADQuickStarts/WebApp-OpenIDConnect-NodeJS.git

Al termine dell'esercitazione, verrà fornita anche l'applicazione completata.The completed application is provided at the end of this tutorial as well.

Passaggio 1: Registrare un'appStep 1: Register an app

  1. Accedere al portale di Azure.Sign in to the Azure portal.

  2. Dal menu nella parte superiore della pagina selezionare il proprio account.In the menu at the top of the page, select your account. Nell'elenco Directory scegliere il tenant di Active Directory in cui si vuole registrare l'applicazione.Under the Directory list, choose the Active Directory tenant where you want to register your application.

  3. Selezionare More services (Altri servizi) nel menu a sinistra della schermata, quindi scegliere Azure Active Directory.Select More Services in the menu on the left side of the screen, and then select Azure Active Directory.

  4. Selezionare Registrazioni per l'app, quindi scegliere Aggiungi.Select App registrations, and then select Add.

  5. Seguire le istruzioni e creare una nuova applicazione Web e/o API Web.Follow the prompts to create a Web Application and/or WebAPI.

    • Il nome dell'applicazione descrive l'applicazione agli utenti.The name of the application describes your application to users.

    • L' URL accesso è l'URL di base dell'app.The Sign-On URL is the base URL of your app. Il valore predefinito della struttura è http://localhost:3000/auth/openid/return`.The skeleton's default is http://localhost:3000/auth/openid/return`.

  6. Dopo la registrazione, Azure AD assegna all'app un ID applicazione univoco.After you register, Azure AD assigns your app a unique application ID. Poiché questo valore sarà necessario nelle sezioni successive, è necessario copiarlo dalla pagina dell'applicazione.You need this value in the following sections, so copy it from the application page.

  7. Dalla pagina Impostazioni -> Proprietà dell'applicazione aggiornare l'URI dell'ID app.From the Settings -> Properties page for your application, update the App ID URI. L' URI ID app è un identificatore univoco dell'applicazione.The App ID URI is a unique identifier for your application. La convenzione consiste nell'usare il formato https://<tenant-domain>/<app-name>, ad esempio: https://contoso.onmicrosoft.com/my-first-aad-app.The convention is to use the format https://<tenant-domain>/<app-name>, for example: https://contoso.onmicrosoft.com/my-first-aad-app.

Passaggio 2: Aggiungere prerequisiti alla directoryStep 2: Add prerequisites to your directory

  1. Dalla riga di comando passare dalle directory alla cartella radice, se non è già stato fatto, ed eseguire i comandi seguenti:From the command line, change directories to your root folder if you're not already there, and then run the following commands:

    • npm install express
    • npm install ejs
    • npm install ejs-locals
    • npm install restify
    • npm install mongoose
    • npm install bunyan
    • npm install assert-plus
    • npm install passport
  2. Inoltre, è necessario passport-azure-ad:In addition, you need passport-azure-ad:

    • npm install passport-azure-ad

Verranno installate le librerie da cui dipende passport-azure-ad.This installs the libraries that passport-azure-ad depends on.

Passaggio 3: Configurare l'app in modo che usi la strategia passport-node-jsStep 3: Set up your app to use the passport-node-js strategy

In questo caso, verrà configurato Express in modo che usi il protocollo di autenticazione OpenID Connect.Here, we configure Express to use the OpenID Connect authentication protocol. Passport verrà usato, tra le altre cose, per inviare richieste di accesso e disconnessione, gestire la sessione dell'utente e ottenere informazioni sull'utente.Passport is used to do various things, including issue sign-in and sign-out requests, manage the user's session, and get information about the user.

  1. Per iniziare, aprire il file config.js nella radice del progetto e immettere i valori di configurazione dell'app nella sezione exports.creds.To begin, open the config.js file at the root of the project, and then enter your app's configuration values in the exports.creds section.

    • clientID rappresenta l'ID applicazione assegnato all'app nel portale di registrazione.The clientID is the Application Id that's assigned to your app in the registration portal.

    • returnURL rappresenta l'URI di reindirizzamento immesso nel portale.The returnURL is the Redirect Uri that you entered in the portal.

    • clientSecret rappresenta il segreto generato nel portale.The clientSecret is the secret that you generated in the portal.

  2. In seguito, aprire il file app.js nella radice del progetto.Next, open the app.js file in the root of the project. Quindi, aggiungere la chiamata seguente per richiamare la strategia OIDCStrategy fornita con passport-azure-ad.Then add the following call to invoke the OIDCStrategy strategy that comes with passport-azure-ad.

    var OIDCStrategy = require('passport-azure-ad').OIDCStrategy;
    
    // add a logger
    
    var log = bunyan.createLogger({
        name: 'Microsoft OIDC Example Web Application'
    });
    
  3. Successivamente, usare la strategia a cui è stato fatto riferimento per gestire le richieste di accesso.After that, use the strategy we just referenced to handle our sign-in requests.

    // Use the OIDCStrategy within Passport. (Section 2)
    //
    //   Strategies in passport require a `validate` function that accepts
    //   credentials (in this case, an OpenID identifier), and invokes a callback
    //   with a user object.
    passport.use(new OIDCStrategy({
        callbackURL: config.creds.returnURL,
        realm: config.creds.realm,
        clientID: config.creds.clientID,
        clientSecret: config.creds.clientSecret,
        oidcIssuer: config.creds.issuer,
        identityMetadata: config.creds.identityMetadata,
        skipUserProfile: config.creds.skipUserProfile,
        responseType: config.creds.responseType,
        responseMode: config.creds.responseMode
    },
    function(iss, sub, profile, accessToken, refreshToken, done) {
        if (!profile.email) {
        return done(new Error("No email found"), null);
        }
        // asynchronous verification, for effect...
        process.nextTick(function () {
        findByEmail(profile.email, function(err, user) {
            if (err) {
            return done(err);
            }
            if (!user) {
            // "Auto-registration"
            users.push(profile);
            return done(null, profile);
            }
            return done(null, user);
        });
        });
    }
    ));
    

    Passport usa un modello simile per tutte le strategie (Twitter, Facebook e così via) seguite dagli scrittori della strategia.Passport uses a similar pattern for all its strategies (Twitter, Facebook, and so on) that all strategy writers adhere to. Osservando la strategia, è possibile notare che a quest'ultima è stata passata una funzione con parametri token e done.Looking at the strategy, you see that we pass it a function that has a token and a done as the parameters. La strategia torna indietro dopo eseguito il suo lavoro.The strategy comes back to us after it does its work. A questo punto è necessario archiviare l'utente e accantonare il token in modo che non sia necessario richiederlo nuovamente.Then we want to store the user and stash the token so we don't need to ask for it again.

Importante

Il codice precedente accetta qualsiasi utente che esegue l'autenticazione al server.The previous code takes any user that happens to authenticate to our server. Questa operazione è nota come registrazione automatica.This is known as auto-registration. Si consiglia di non consentire agli utenti di eseguire l'autenticazione per un server di produzione senza prima prevedere un processo di registrazione.We recommend that you don't let anyone authenticate to a production server without first having them register via a process that you decide on. Questo è il criterio usato in genere per le app consumer, che consentono di eseguire la registrazione con Facebook ma poi chiedono di immettere informazioni aggiuntive.This is usually the pattern you see in consumer apps, which allow you to register with Facebook but then ask you to provide additional information. Se non si trattasse di un'applicazione di esempio, sarebbe stato possibile estrarre l'indirizzo e-mail dell'utente dall'oggetto token restituito e chiedere all'utente di immettere le informazioni aggiuntive.If this weren't a sample application, we could have extracted the user's email address from the token object that is returned and then asked the user to fill out additional information. Poiché si tratta di un server di test, le informazioni vengono aggiunte al database in memoria.Because this is a test server, we add them to the in-memory database.

  1. Successivamente, aggiungere i metodi che consentiranno di tenere traccia degli utenti connessi come richiesto da Passport.Next, let's add the methods that enable us to track the signed-in users as required by Passport. Questi metodi includono la serializzazione e deserializzazione delle informazioni dell'utente.These methods include serializing and deserializing the user's information.

    
            // Passport session setup. (Section 2)
    
            //   To support persistent sign-in sessions, Passport needs to be able to
            //   serialize users into the session and deserialize them out of the session. Typically,
            //   this is done simply by storing the user ID when serializing and finding
            //   the user by ID when deserializing.
            passport.serializeUser(function(user, done) {
                done(null, user.email);
            });
    
            passport.deserializeUser(function(id, done) {
                findByEmail(id, function (err, user) {
                    done(err, user);
                });
            });
    
            // array to hold signed-in users
            var users = [];
    
            var findByEmail = function(email, fn) {
                for (var i = 0, len = users.length; i < len; i++) {
                    var user = users[i];
                    log.info('we are using user: ', user);
                    if (user.email === email) {
                        return fn(null, user);
                    }
                }
                return fn(null, null);
            };
    
  2. Quindi aggiungere il codice per caricare il motore Express.Next, let's add the code to load the Express engine. Qui usiamo i modelli /views e /routes predefiniti forniti da Express.Here we use the default /views and /routes pattern that Express provides.

    
        // configure Express (section 2)
    
            var app = express();
            app.configure(function() {
          app.set('views', __dirname + '/views');
          app.set('view engine', 'ejs');
          app.use(express.logger());
          app.use(express.methodOverride());
          app.use(cookieParser());
          app.use(expressSession({ secret: 'keyboard cat', resave: true, saveUninitialized: false }));
          app.use(bodyParser.urlencoded({ extended : true }));
          // Initialize Passport!  Also use passport.session() middleware, to support
          // persistent login sessions (recommended).
          app.use(passport.initialize());
          app.use(passport.session());
          app.use(app.router);
          app.use(express.static(__dirname + '/../../public'));
        });
    
  3. Infine aggiungere le route che trasferiscono le richieste di accesso effettive al motore passport-azure-ad:Finally, let's add the routes that hand off the actual sign-in requests to the passport-azure-ad engine:

    
        // Our Auth routes (section 3)
    
        // GET /auth/openid
        //   Use passport.authenticate() as route middleware to authenticate the
        //   request. The first step in OpenID authentication involves redirecting
        //   the user to their OpenID provider. After authenticating, the OpenID
        //   provider redirects the user back to this application at
        //   /auth/openid/return.
        app.get('/auth/openid',
        passport.authenticate('azuread-openidconnect', { failureRedirect: '/login' }),
        function(req, res) {
            log.info('Authentication was called in the Sample');
            res.redirect('/');
        });
    
        // GET /auth/openid/return
        //   Use passport.authenticate() as route middleware to authenticate the
        //   request. If authentication fails, the user is redirected back to the
        //   sign-in page. Otherwise, the primary route function is called,
        //   which, in this example, redirects the user to the home page.
        app.get('/auth/openid/return',
          passport.authenticate('azuread-openidconnect', { failureRedirect: '/login' }),
          function(req, res) {
            log.info('We received a return from AzureAD.');
            res.redirect('/');
          });
    
        // POST /auth/openid/return
        //   Use passport.authenticate() as route middleware to authenticate the
        //   request. If authentication fails, the user is redirected back to the
        //   sign-in page. Otherwise, the primary route function is called,
        //   which, in this example, redirects the user to the home page.
        app.post('/auth/openid/return',
          passport.authenticate('azuread-openidconnect', { failureRedirect: '/login' }),
          function(req, res) {
            log.info('We received a return from AzureAD.');
            res.redirect('/');
          });
    

Passaggio 4: Usare Passport per inviare le richieste di accesso e disconnessione ad Azure ADStep 4: Use Passport to issue sign-in and sign-out requests to Azure AD

L'app ora è configurata correttamente per comunicare con l'endpoint mediante il protocollo di autenticazione OpenID Connect.Your app is now properly configured to communicate with the endpoint by using the OpenID Connect authentication protocol. passport-azure-ad ha gestito tutti i dettagli relativi alla creazione dei messaggi di autenticazione, alla convalida dei token da Azure AD e alla gestione delle sessioni utente.passport-azure-ad has taken care of all the details of crafting authentication messages, validating tokens from Azure AD, and maintaining user sessions. A questo punto è sufficiente offrire agli utenti un modo per accedere e disconnettersi e per raccogliere informazioni aggiuntive sugli utenti connessi.All that remains is giving your users a way to sign in and sign out, and gathering additional information about the signed-in users.

  1. Aggiungere prima di tutto i metodi predefinito, di accesso, account e disconnessione al file app.js:First, let's add the default, sign-in, account, and sign-out methods to our app.js file:

    
        //Routes (section 4)
    
        app.get('/', function(req, res){
          res.render('index', { user: req.user });
        });
    
        app.get('/account', ensureAuthenticated, function(req, res){
          res.render('account', { user: req.user });
        });
    
        app.get('/login',
          passport.authenticate('azuread-openidconnect', { failureRedirect: '/login' }),
          function(req, res) {
            log.info('Login was called in the Sample');
            res.redirect('/');
        });
    
        app.get('/logout', function(req, res){
          req.logout();
          res.redirect('/');
        });
    
  2. Esaminare nel dettaglio questi aspetti:Let's review these in detail:

    • Il percorso / reindirizza alla vista index.ejs passando l'utente nella richiesta (se presente).The /route redirects to the index.ejs view, passing the user in the request (if it exists).
    • Il percorso /account prima di tutto verifica che l'autenticazione sia stata eseguita (l'implementazione nell'esempio di seguito), quindi passa l'utente nella richiesta in modo da ottenere informazioni aggiuntive su quest'ultimo.The /account route first ensures we are authenticated (we implement that in the following example), and then passes the user in the request so that we can get additional information about the user.
    • Il percorso /login richiama l'autenticatore azuread-openidconnect da passport-azuread.The /login route calls our azuread-openidconnect authenticator from passport-azuread. Se l'operazione ha esito negativo, il percorso reindirizza di nuovo l'utente a /login.If that doesn't succeed, it redirects the user back to /login.
    • Il percorso /logout chiama logout.ejs (e il percorso), consentendo di cancellare i cookie e riportando quindi l'utente a index.ejs.The /logout route simply calls the logout.ejs (and route), which clears cookies and then returns the user back to index.ejs.
  3. Per l'ultima parte di app.js, aggiungere il metodo EnsureAuthenticated usato in /account, come illustrato in precedenza.For the last part of app.js, let's add the EnsureAuthenticated method that is used in /account, as shown earlier.

    
        // Simple route middleware to ensure user is authenticated. (section 4)
    
        //   Use this route middleware on any resource that needs to be protected. If
        //   the request is authenticated (typically via a persistent sign-in session),
        //   the request proceeds. Otherwise, the user is redirected to the
        //   sign-in page.
        function ensureAuthenticated(req, res, next) {
          if (req.isAuthenticated()) { return next(); }
          res.redirect('/login')
        }
    
  4. Infine, creare il server stesso in app.js:Finally, let's create the server itself in app.js:


        app.listen(3000);

Passaggio 5: Creare le viste e i percorsi in Express per visualizzare l'utente nel sito WebStep 5: To display our user in the website, create the views and routes in Express

Ora il file app.js è completo.Now app.js is complete. È sufficiente aggiungere i percorsi e le viste che mostrano all'utente le informazioni ottenute e gestire i percorsi /logout e /login creati.We simply need to add the routes and views that show the information we get to the user, as well as handle the /logout and /login routes that we created.

  1. Creare la route /routes/index.js nella directory radice.Create the /routes/index.js route under the root directory.

                /*
                 * GET home page.
                 */
    
                exports.index = function(req, res){
                  res.render('index', { title: 'Express' });
                };
    
  2. Creare la route /routes/user.js nella directory radice.Create the /routes/user.js route under the root directory.

             ```JavaScript
             /*
              * GET users listing.
              */
    
             exports.list = function(req, res){
               res.send("respond with a resource");
             };
             ```
    

    Queste passeranno la richiesta alle viste, incluso l'utente se presente.These pass along the request to our views, including the user if present.

  3. Creare la vista /views/index.ejs nella directory radice.Create the /views/index.ejs view under the root directory. Si tratta di una pagina semplice che chiama i metodi di accesso e disconnessione e consente di ottenere informazioni sull'account.This is a simple page that calls our login and logout methods and enables us to grab account information. Si noti che è possibile usare il parametro condizionale if (!user) in quanto l'utente passato nella richiesta dimostra che c'è un utente che ha eseguito l'accesso.Notice that we can use the conditional if (!user) as the user being passed through in the request is evidence we have a signed-in user.

    <% if (!user) { %>
        <h2>Welcome! Please log in.</h2>
        <a href="/login">Log In</a>
    <% } else { %>
        <h2>Hello, <%= user.displayName %>.</h2>
        <a href="/account">Account Info</a></br>
        <a href="/logout">Log Out</a>
    <% } %>
    
  4. Creare la vista /views/account.ejs nella directory radice affinché sia possibile visualizzare informazioni aggiuntive che passport-azuread ha inserito nella richiesta dell'utente.Create the /views/account.ejs view under the root directory so that we can view additional information that passport-azuread has put in the user request.

    <% if (!user) { %>
        <h2>Welcome! Please log in.</h2>
        <a href="/login">Log In</a>
    <% } else { %>
    <p>displayName: <%= user.displayName %></p>
    <p>givenName: <%= user.name.givenName %></p>
    <p>familyName: <%= user.name.familyName %></p>
    <p>UPN: <%= user._json.upn %></p>
    <p>Profile ID: <%= user.id %></p>
    ##Next steps  <p>Full Claimes</p>
    <%- JSON.stringify(user) %>
    <p></p>
    <a href="/logout">Log Out</a>
    <% } %>
    
  5. Ora viene aggiunto un layout per modificare l'aspetto.Let's make this look good by adding a layout. Creare la vista '/views/layout.ejs' nella directory radice.Create the '/views/layout.ejs' view under the root directory.

    
    <!DOCTYPE html>
    <html>
        <head>
            <title>Passport-OpenID Example</title>
        </head>
        <body>
            <% if (!user) { %>
                <p>
                <a href="/">Home</a> |
                <a href="/login">Log In</a>
                </p>
            <% } else { %>
                <p>
                <a href="/">Home</a> |
                <a href="/account">Account</a> |
                <a href="/logout">Log Out</a>
                </p>
            <% } %>
            <%- body %>
        </body>
    </html>
    

Passaggi successiviNext steps

Per finire, compilare ed eseguire l'app.Finally, build and run your app. Eseguire node app.js, quindi passare a http://localhost:3000.Run node app.js, and then go to http://localhost:3000.

Accedere con un account Microsoft personale, aziendale o dell'istituto di istruzione e osservare come l'identità dell'utente è indicata nell'elenco /account.Sign in with either a personal Microsoft account or a work or school account, and notice how the user's identity is reflected in the /account list. È ora disponibile un'app Web protetta con protocolli standard del settore in grado di autenticare gli utenti con account personali, aziendali e dell'istituto di istruzione.You now have a web app that's secured with industry standard protocols that can authenticate users with both their personal and work/school accounts.

Come riferimento viene fornito l'esempio completato, senza i valori di configurazione, come file con estensione zip.For reference, the completed sample (without your configuration values) is provided as a .zip file. In alternativa, è possibile eseguire la clonazione da GitHub:Alternatively, you can clone it from GitHub:

git clone --branch complete https://github.com/AzureADQuickStarts/WebApp-OpenIDConnect-NodeJS.git

Ora è possibile passare ad argomenti più avanzati.You can now move onto more advanced topics. È consigliabile provare:You might want to try:

Proteggere un'API Web con Azure ADSecure a Web API with Azure AD

Risorse aggiuntiveAdditional resources

Ottenere aggiornamenti della sicurezza per i prodottiGet security updates for our products

È consigliabile ricevere notifiche in caso di problemi di sicurezza. A tale scopo, visitare la pagina del TechCenter per le notifiche sulla sicurezza tecnica per Microsoft e sottoscrivere gli avvisi di sicurezza.We encourage you to get notifications of when security incidents occur by visiting the TechCenter page for Microsoft technical security notifications and subscribing to security advisory alerts.