Node.js 使用Azure AD登录到Nodejs web应用程序
我试图弄清楚如何使用Azure AD验证用户。为了进行实验,我尝试了Microsoft的示例,可在中找到 我已经在Azure中设置了一个Active Directory,并添加了一个名为test的新应用程序,添加id uri: 现在,当我按照自述文件中的说明运行服务器时,我会被重定向到login.microsoftonline.com并被提示登录。但是当我提供username/pw时,我会再次被重定向回登录页面 我怀疑问题在于我没有正确设置config.json中的变量,但是我很难找到需要设置哪些值的文档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中的变量,但是我很难找到需要设置哪
有人对这个例子有经验吗?据我所知,我建议您可以按照以下两个文档作为参考开始
为了便于开发,您可以尝试使用节点包
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中做了两个更改
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
};