使用Azure AD,ReactJS和NodeJS对用户进行身份验证并使用Graph API

时间:2016-11-28 00:58:00

标签: node.js azure reactjs passport.js azure-ad-graph-api

我有一个使用NodeJS + ReactJS创建的项目应用程序,所有我想要的是使用Azure AD来验证用户并使用Azure中的Graph API获取他的数据,如名称,组,图片,职业等。

我已经在Azure门户上正确配置了Azure AD和应用程序。包括权限授权和所有这些人员。

我试图了解如何才能做到这一点,但没有成功。我一直试图在google,StackOverflow,Microsoft Documentations上找到,甚至是项目样本。

有些样本已经有效,但我没有其中任何一个可以理解并投入到我的项目中作为生产应用程序。

我已将此用于对用户进行身份验证,但返回的AccessToken无法调用图谱API:

passport.use(new OIDCStrategy({
    redirectUrl: 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,
    allowHttpForRedirectUrl: config.creds.allowHttpForRedirectUrl
  },
  function(iss, sub, profile, accessToken, refreshToken, done) {
    console.log(accessToken);
    profile = profile._json;
    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);
      });
    });
  }
));

这个给了我正确的AccessToken来使用Graph API,但我无法理解如何使用它而不是Passport:

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); 
    }); 
  });
});

如果有人可以帮我提供一些真正的应用示例,视频或其他内容,那将非常好。我想失去理智。

谢谢!

1 个答案:

答案 0 :(得分:4)

护照的OIDCStrategy跟随Authorize access to web applications using OpenID Connect and Azure Active Directory进行身份验证&amp;授权用户。如果您需要资源访问权限,则仍需要完成Use the authorization code to request an access token的步骤。

我根据openid connection sample添加了一些代码段:

返回路由功能将使用code获取访问令牌并保存到用户的seeion对象中。

app.post('/auth/openid/return',
  passport.authenticate('azuread-openidconnect', { failureRedirect: '/login' }),
  function (req, res) {
    let option = {
      method:'POST',
      uri:'https://login.microsoftonline.com/<tenant_id>/oauth2/token',
      headers:{
        'Content-Type':'application/x-www-form-urlencoded'
      },
      form:{
        grant_type:'authorization_code',
        client_id:'<client_id>',
        resource:'https://graph.windows.net',
        client_secret:'<secret_key>',
        code:req.body.code,
        redirect_uri:'http://localhost:3000/auth/openid/return'
      }
    }
    console.log(option);
    request(option,function(err,res,body){
      req.user.access_token = JSON.parse(body).access_token;
    })

    // log.info('We received a return from AzureAD.');
    res.redirect('/');
  });

路线&#39; / me&#39;是要使用访问令牌进行抽样以要求重新协商。

app.get('/me',ensureAuthenticated ,function(req,response){
  request.get("https://graph.windows.net/<tenant_id>/me?api-version=1.5", {
    'headers': {
      'Authorization': "Bearer " + req.user.access_token,
      'Content-Type': 'application/json'
    }
  }, function(err, res, body){
    if(err){
      console.log("err: " + err);
    }
    else{
      console.log("res: " + res);
      response.send(res);
    }
  });
});

如有任何疑问,请随时告诉我。