Node.js 使用Azure AD登录到Nodejs web应用程序

Node.js 使用Azure AD登录到Nodejs web应用程序,node.js,azure,login,Node.js,Azure,Login,我试图弄清楚如何使用Azure AD验证用户。为了进行实验,我尝试了Microsoft的示例,可在中找到 我已经在Azure中设置了一个Active Directory,并添加了一个名为test的新应用程序,添加id uri: 现在,当我按照自述文件中的说明运行服务器时,我会被重定向到login.microsoftonline.com并被提示登录。但是当我提供username/pw时,我会再次被重定向回登录页面 我怀疑问题在于我没有正确设置config.json中的变量,但是我很难找到需要设置哪

我试图弄清楚如何使用Azure AD验证用户。为了进行实验,我尝试了Microsoft的示例,可在中找到

我已经在Azure中设置了一个Active Directory,并添加了一个名为test的新应用程序,添加id uri:

现在,当我按照自述文件中的说明运行服务器时,我会被重定向到login.microsoftonline.com并被提示登录。但是当我提供username/pw时,我会再次被重定向回登录页面

我怀疑问题在于我没有正确设置config.json中的变量,但是我很难找到需要设置哪些值的文档


有人对这个例子有经验吗?

据我所知,我建议您可以按照以下两个文档作为参考开始

  • 使用Azure广告登录和注销Web应用
  • 将Azure AD集成到NodeJS web应用程序中

  • 为了便于开发,您可以尝试使用节点包
    passport azure ad
    (),这是NodeJS实现您的需求的
    passport
    ()策略之一。

    首先您必须将应用程序添加到active directory,然后使用

    参考azure AD应用程序注册值准备应用程序进行身份验证

    var AuthenticationContext = require('adal-node').AuthenticationContext;
    
    var clientId = 'yourClientIdHere';
    var clientSecret = 'yourAADIssuedClientSecretHere'
    var redirectUri = 'yourRedirectUriHere';
    var authorityHostUrl = 'https://login.windows.net';
    var tenant = 'myTenant';
    var authorityUrl = authorityHostUrl + '/' + tenant;
    var redirectUri = 'http://localhost:3000/getAToken';
    var resource = '00000002-0000-0000-c000-000000000000';
    var templateAuthzUrl = 'https://login.windows.net/' + 
                            tenant + 
                            '/oauth2/authorize?response_type=code&client_id=' +
                            clientId + 
                            '&redirect_uri=' + 
                            redirectUri + '
                            &state=<state>&resource=' + 
                            resource;
    
    您可以在ADAL for nodeJS存储库中找到完整示例以及更多内容:

    这是一个取自GitHub ADAL存储库的文档

    website-sample.js
    “严格使用”;
    var express=需要(“express”);
    var记录器=需要('connect-logger');
    var cookieParser=require('cookie-parser');
    var session=require('cookie-session');
    var fs=需要('fs');
    var crypto=require('crypto');
    var AuthenticationContext=require('adal-node')。AuthenticationContext;
    var-app=express();
    app.use(logger());
    app.use(cookieParser(“一个深秘密”);
    使用(会话({secret:'1234567890QWERTY'}));
    app.get('/',函数(req,res){
    res.redirect('login');
    });
    /*
    *您可以通过提供JSON文件覆盖默认帐户信息
    *使用与下面的sampleParameters变量相同的参数。任何一个
    *通过命令行参数“node sample.js parameters.json”,或
    *在环境变量中指定。
    * {
    *“承租人”:“rrandalaad1.onmicrosoft.com”,
    *“authorityHostUrl”:https://login.windows.net",
    *“客户ID”:“624ac9bd-4c1c-4686-aec8-e56a8991cfb3”,
    *“客户机密”:“verySecret=”
    * }
    */
    var parametersFile=process.argv[2]| | process.env['ADAL_SAMPLE_PARAMETERS_FILE'];
    var样本参数;
    如果(参数文件){
    var jsonFile=fs.readFileSync(参数文件);
    if(jsonFile){
    sampleParameters=JSON.parse(jsonFile);
    }否则{
    log('未找到文件,返回默认值:'+参数文件);
    }
    }
    如果(!参数文件){
    样本参数={
    租户:“rrandalaad1.onmicrosoft.com”,
    authorityHostUrl:'https://login.windows.net',
    客户ID:'624ac9bd-4c1c-4686-aec8-b56a8991cfb3',
    用户名:'frizzo@naturalcauses.com',
    密码:“”
    };
    }
    var authorityUrl=sampleParameters.authorityHostUrl+'/'+sampleParameters.tenant;
    var重定向URI=http://localhost:3000/getAToken';
    var资源='00000002-0000-0000-c000-000000000000';
    var templateAuthzUrl='0https://login.windows.net/“+sampleParameters.tenant+”/oauth2/authorize?响应类型=代码和客户端\u id=&重定向\u uri=&状态=&资源=”;
    app.get('/',函数(req,res){
    res.redirect('/login');
    });
    app.get('/login',函数(req,res){
    控制台日志(请求cookie);
    res.cookie(“acookie”,“这是一块cookie”);
    res.send('\
    \
    福巴\
    \
    \
    \
    \
    ');
    });
    函数createAuthorizationUrl(状态){
    var authorizationUrl=templateAuthzUrl.replace(“”,sampleParameters.clientId);
    authorizationUrl=authorizationUrl.replace(“”,重定向URI);
    authorizationUrl=authorizationUrl.replace(“”,state);
    authorizationUrl=authorizationUrl.replace(“”,资源);
    返回授权URL;
    }
    //客户端在这里被重定向,以便创建OAuth授权url并将其重定向到AAD。
    //在那里,他们将验证并同意允许此应用访问
    //他们拥有的一些资源。
    app.get('/auth',函数(req,res){
    加密随机字节(48,函数(ex,buf){
    var-token=buf.toString('base64').replace(//\//g,''''''''.replace(//\+/g,'-');
    res.cookie('authstate',令牌);
    var authorizationUrl=createAuthorizationUrl(令牌);
    res.redirect(授权URL);
    });
    });
    //获得同意后,AAD将在此处重定向。ADAL库是通过
    //AuthenticationContext并检索可用于访问的访问令牌
    //用户拥有的资源。
    app.get('/getAToken',函数(req,res){
    if(req.cookies.authstate!==req.query.state){
    res.send('错误:状态不匹配');
    }
    var authenticationContext=新的authenticationContext(authorityUrl);
    authenticationContext.acquireTokenWithAuthorizationCode(req.query.code、redirectUri、resource、sampleParameters.clientId、sampleParameters.clientSecret、函数(err、response){
    var消息=“”;
    如果(错误){
    消息='错误:'+err.message+'\n';
    }
    message+=“response:”+JSON.stringify(response);
    如果(错误){
    res.send(消息);
    返回;
    }
    //稍后,如果访问令牌过期,则可以刷新它。
    authenticationContext.acquireTokenWithRefreshToken(response.refreshToken、sampleParameters.clientId、sampleParameters.clientSecret、资源、函数(refreshErr、refreshResponse){
    如果(刷新错误){
    message+='refreshError:'+refreshError.message+'\n';
    }
    message+='refreshResponse:'+JSON.stringify(refreshResponse);
    res.send(消息);
    }); 
    });
    });
    app.listen(3000);
    console.log(“监听3000”);
    

    我也有类似的问题,并且能够解决它。谷歌搜索之后,我在config.js中做了两个更改

  • issuer值设置为false
  • responseMode值已从查询更改为表单\u post。
    var AuthenticationContext = require('adal-node').AuthenticationContext;
    
    var clientId = 'yourClientIdHere';
    var clientSecret = 'yourAADIssuedClientSecretHere'
    var redirectUri = 'yourRedirectUriHere';
    var authorityHostUrl = 'https://login.windows.net';
    var tenant = 'myTenant';
    var authorityUrl = authorityHostUrl + '/' + tenant;
    var redirectUri = 'http://localhost:3000/getAToken';
    var resource = '00000002-0000-0000-c000-000000000000';
    var templateAuthzUrl = 'https://login.windows.net/' + 
                            tenant + 
                            '/oauth2/authorize?response_type=code&client_id=' +
                            clientId + 
                            '&redirect_uri=' + 
                            redirectUri + '
                            &state=<state>&resource=' + 
                            resource;
    
    function createAuthorizationUrl(state) {
      return templateAuthzUrl.replace('<state>', state);
    }
    
    // Clients get redirected here in order to create an OAuth authorize url and redirect them to AAD.
    // There they will authenticate and give their consent to allow this app access to
    // some resource they own.
    app.get('/auth', function(req, res) {
      crypto.randomBytes(48, function(ex, buf) {
        var token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
    
        res.cookie('authstate', token);
        var authorizationUrl = createAuthorizationUrl(token);
    
        res.redirect(authorizationUrl);
      });
    });
    
    // After consent is granted AAD redirects here.  The ADAL library is invoked via the
    // AuthenticationContext and retrieves an access token that can be used to access the
    // user owned resource.
    app.get('/getAToken', function(req, res) {
      if (req.cookies.authstate !== req.query.state) {
        res.send('error: state does not match');
      }
    
      var authenticationContext = new AuthenticationContext(authorityUrl);
    
      authenticationContext.acquireTokenWithAuthorizationCode(
        req.query.code,
        redirectUri,
        resource,
        clientId, 
        clientSecret,
        function(err, response) {
          var errorMessage = '';
          if (err) {
            errorMessage = 'error: ' + err.message + '\n';
          }
          errorMessage += 'response: ' + JSON.stringify(response);
          res.send(errorMessage);
        }
      );
    });
    
    'use strict';
    
    var express = require('express');
    var logger = require('connect-logger');
    var cookieParser = require('cookie-parser');
    var session = require('cookie-session');
    var fs = require('fs');
    var crypto = require('crypto');
    
    var AuthenticationContext = require('adal-node').AuthenticationContext;
    
    var app = express();
    app.use(logger());
    app.use(cookieParser('a deep secret'));
    app.use(session({secret: '1234567890QWERTY'}));
    
    app.get('/', function(req, res) {
      res.redirect('login');
    });
    
    /*
     * You can override the default account information by providing a JSON file
     * with the same parameters as the sampleParameters variable below.  Either
     * through a command line argument, 'node sample.js parameters.json', or
     * specifying in an environment variable.
     * {
     *   "tenant" : "rrandallaad1.onmicrosoft.com",
     *   "authorityHostUrl" : "https://login.windows.net",
     *   "clientId" : "624ac9bd-4c1c-4686-aec8-e56a8991cfb3",
     *   "clientSecret" : "verySecret="
     * }
     */
    var parametersFile = process.argv[2] || process.env['ADAL_SAMPLE_PARAMETERS_FILE'];
    
    var sampleParameters;
    if (parametersFile) {
      var jsonFile = fs.readFileSync(parametersFile);
      if (jsonFile) {
        sampleParameters = JSON.parse(jsonFile);
      } else {
        console.log('File not found, falling back to defaults: ' + parametersFile);
      }
    }
    
    if (!parametersFile) {
      sampleParameters = {
        tenant : 'rrandallaad1.onmicrosoft.com',
        authorityHostUrl : 'https://login.windows.net',
        clientId : '624ac9bd-4c1c-4686-aec8-b56a8991cfb3',
        username : 'frizzo@naturalcauses.com',
        password : ''
      };
    }
    
    var authorityUrl = sampleParameters.authorityHostUrl + '/' + sampleParameters.tenant;
    var redirectUri = 'http://localhost:3000/getAToken';
    var resource = '00000002-0000-0000-c000-000000000000';
    
    var templateAuthzUrl = 'https://login.windows.net/' + sampleParameters.tenant + '/oauth2/authorize?response_type=code&client_id=<client_id>&redirect_uri=<redirect_uri>&state=<state>&resource=<resource>';
    
    
    app.get('/', function(req, res) {
      res.redirect('/login');
    });
    
    app.get('/login', function(req, res) {
      console.log(req.cookies);
    
      res.cookie('acookie', 'this is a cookie');
    
      res.send('\
    <head>\
      <title>FooBar</title>\
    </head>\
    <body>\
      <a href="./auth">Login</a>\
    </body>\
        ');
    });
    
    function createAuthorizationUrl(state) {
      var authorizationUrl = templateAuthzUrl.replace('<client_id>', sampleParameters.clientId);
      authorizationUrl = authorizationUrl.replace('<redirect_uri>',redirectUri);
      authorizationUrl = authorizationUrl.replace('<state>', state);
      authorizationUrl = authorizationUrl.replace('<resource>', resource);
      return authorizationUrl;
    }
    
    // Clients get redirected here in order to create an OAuth authorize url and redirect them to AAD.
    // There they will authenticate and give their consent to allow this app access to
    // some resource they own.
    app.get('/auth', function(req, res) {
      crypto.randomBytes(48, function(ex, buf) {
        var token = buf.toString('base64').replace(/\//g,'_').replace(/\+/g,'-');
    
        res.cookie('authstate', token);
        var authorizationUrl = createAuthorizationUrl(token);
    
        res.redirect(authorizationUrl);
      });
    });
    
    // After consent is granted AAD redirects here.  The ADAL library is invoked via the
    // AuthenticationContext and retrieves an access token that can be used to access the
    // user owned resource.
    app.get('/getAToken', function(req, res) {
      if (req.cookies.authstate !== req.query.state) {
        res.send('error: state does not match');
      }
      var authenticationContext = new AuthenticationContext(authorityUrl);
      authenticationContext.acquireTokenWithAuthorizationCode(req.query.code, redirectUri, resource, sampleParameters.clientId, sampleParameters.clientSecret, function(err, response) {
        var message = '';
        if (err) {
          message = 'error: ' + err.message + '\n';
        }
        message += 'response: ' + JSON.stringify(response);
    
        if (err) {
          res.send(message);
          return;
        }
    
        // Later, if the access token is expired it can be refreshed.
        authenticationContext.acquireTokenWithRefreshToken(response.refreshToken, sampleParameters.clientId, sampleParameters.clientSecret, resource, function(refreshErr, refreshResponse) {
          if (refreshErr) {
            message += 'refreshError: ' + refreshErr.message + '\n';
          }
          message += 'refreshResponse: ' + JSON.stringify(refreshResponse);
    
          res.send(message); 
        }); 
      });
    });
    
    app.listen(3000);
    console.log('listening on 3000');
    
    exports.creds = {
        issuer : false,  
        realm : "<TENANT>",
        returnURL: 'http://localhost:3000/auth/openid/return',
        identityMetadata: 'https://login.microsoftonline.com/common/.well-known/openid-configuration', // For using Microsoft you should never need to change this.
        clientID: '<CLIENT_ID>',
        clientSecret: '<CLIENT_SECRET>', // if you are doing code or id_token code
        skipUserProfile: true, // for AzureAD should be set to true.
        responseType: 'id_token code', // for login only flows use id_token. For accessing resources use `id_token code`
        responseMode: 'form_post', // For login only flows we should have token passed back to us in a POST
     };