我是nodejs的初學者,試圖讓單點登錄工作。單一登錄對我的本地應用程序運行正常,使用OpenIdp進行身份驗證。但是,不是爲了我的應用程序運行在虛擬機上並集成到ADFS公司。我不確定這裏有什麼問題。使用OpenIDP單點登錄可以正常工作,但不能與ADFS一起使用
以下是與代碼相關的代碼。
app.js:
'use strict';
require('./appRequire');
var config = appRequire('/config-bootstrap').config;
var logger = appRequire('/lib/app-logger');
var isAuthenticated = appRequire('routes/is-authenticated');
var busboy = require('connect-busboy');
var express = require('express');
var morgan = require('morgan'); //express logger
var path = require('path');
var swig = require('swig');
var app = express();
// required for passport authentication
var passportRoutines = appRequire('/lib/passport-routines');
var bodyParser = require('body-parser');
var session = require('express-session');
var methodOverride = require('method-override');
var cookieParser = require('cookie-parser');
app.use(cookieParser());
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({
extended: true,
limit: '50mb'
}));
app.use(session({
secret: "this is not secret",
resave: true,
saveUninitialized: true
}));
var passport = passportRoutines.getPassport();
app.use(passport.initialize());
app.use(passport.session());
app.use(methodOverride());
app.use('/', express.static(__dirname + '/public'));
app.use('/public', express.static(__dirname + '/vendor/public'));
app.use(busboy());
app.use(morgan('combined', {
stream: logger.stream,
skip: function(req, res) {
return res.statusCode user object not available. Auth is not successful.")
return res.redirect(APP_ROOT + '/not-authorised');
}
req.logIn(user, function(err) {
if (err) {
return next(err);
}
res.redirect(APP_ROOT);
});
})(req, res, next);
});
var serv = require('./routes/serv');
app.use(APP_ROOT, serv);
var ROUTES = ['employees', 'accounts', 'activities', 'admin'];
ROUTES.forEach(function (route) {
app.all(APP_ROOT + '/' + route + '*', isAuthenticated);
var routeModule = require('./routes/' + route);
app.use(APP_ROOT + '/' + route, routeModule);
});
var errorHandler = require('./routes/errors');
app.use(APP_ROOT, errorHandler.router);
// 404 HANDLING
app.use(function(req, res, next) {
var notFoundError = new Error('Page ' + req.url + ' cannot be found');
notFoundError.status = 404;
next(notFoundError);
});
// ERROR HANDLING
app.use(errorHandler.errorHandler());
swig.setDefaults({
locals: {
appAssetPaths: {
'js': '/javascript',
'js_vendor': '/javascript/vendor',
'style': '/css/generated',
'style_vendor': '/css/vendor',
'static': '/icons'
}
}
});
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', __dirname + '/views');
if (!config.data_source === 'json') {
throw 'data source not implemented (' + config.data_source + ')';
}
module.exports = app;
護照routines.js:
'use strict';
var config = appRequire('/config-bootstrap').config;
var passport = require('passport');
var fs = require('fs');
var logger = appRequire('lib/app-logger').AppLoger;
function searchUser(username, passwordhash) {
return (require('fs').readFileSync(config.passport.basic.auth_file,'utf-8').split('\n').map(function(e){
return { name : e.split(':')[0], passwordhash : e.split(':')[1] };
}).filter(function(e){
return (e.name === username && e.passwordhash === passwordhash);
}).length == 1);
}
function getCertificate(){
if(config.passport.saml.cert){
logger.info("using the certficate file :", config.passport.saml.cert);
return fs.readFileSync(config.passport.saml.cert, 'utf-8')
}else{
logger.info("Cert property is not defnied");
return null;
}
}
function getPassportStrategy(){
switch(config.passport.strategy){
case "saml":
var saml = require('passport-saml').Strategy;
var saml_options = {
entryPoint : config.passport.saml.entryPoint,
issuer : config.passport.saml.issuer,
acceptedClockSkewMs : config.passport.saml.acceptedClockSkewMs,
callbackUrl : config.passport.saml.callbackUrl,
signatureAlgorithm : 'sha256',
cert: getCertificate(),
identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
};
if (config.passport.saml.cert) {
saml_options['cert'] = fs.readFileSync(config.passport.saml.cert, 'utf-8');
}
return new saml(saml_options, function(profile, done) {
logger.info(" profile retrieved from ADFS :", JSON.stringify(profile))
console.log(" --> profile retrieved from ADFS :", JSON.stringify(profile))
return done(null, {
id : profile.uid,
email : profile.email,
displayName : profile.cn,
firstName : profile.givenName,
lastName : profile.sn,
});
});
case "basic":
var httpbasic = require('passport-http').BasicStrategy;
return new httpbasic(function(username, password, done) {
return done(null, searchUser(username, require('md5')(password)));
});
case "noauth":
var noauth = appRequire("/lib/passport-noauth").Strategy;
return new noauth();
default:
throw "No known passport strategy configured!";
}
}
var isAuthorised = function(user){
var data, authUsers;
try{
logger.info('User returned from ADFS :', JSON.stringify(user))
console.log('--> User returned from ADFS :', JSON.stringify(user))
data = fs.readFileSync(config.passport.saml.auth_users_file,'utf-8');
authUsers = JSON.parse(data);
logger.info('Authorised users :', authUsers);
}catch(err){
logger.error("Either authorised-users.json file does not exist or it not in the right format")
logger.error(err);
}
return true;
}
var isUserAuthorised = function(user) {
logger.info('user in passport-routines. js :', JSON.stringify(user))
var DEFAULT_AUTH = function() {
return true;
};
switch(config.passport.strategy){
case "saml":
return function() {
var authorised = isAuthorised(user)
return authorised
};
case "basic":
return DEFAULT_AUTH;
case "noauth":
return DEFAULT_AUTH;
}
};
exports.getPassport = function() {
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
done(null, user);
});
passport.use(getPassportStrategy());
return passport;
}
exports.isUserAuthorised = isUserAuthorised;
我用於OpenIDP在配置有:
"passport" : {
"strategy" : "saml",
"saml" : {
"entryPoint" : "https://openidp.feide.no/simplesaml/saml2/idp/SSOService.php",
"issuer" : "http://myapp.com",
"acceptedClockSkewMs" : -1,
"callbackUrl" : "https://myapp.com:8081/authenticated/",
"auth_users_file":"/path/to/authorised-users.json"
},
}
配置用於VM和ADFS組合:
<pre><code>
"passport" : {
"strategy" : "saml",
"saml" : {
"path": "/",
"entryPoint": "https://adfs.mycomapny.com/adfs/ls/",
"cert": "/path/to/key.pem",
"issuer": "https://myapp.com",
"acceptedClockSkewMs": -1,
"authnContext": "http://schemas.microsoft.com/ws/2008/06/identity/authenticationmethod/windows",
"identifierFormat": null,
"callbackUrl": "https://myapp.com/authenticated/",
"auth_users_file":"/path/to/authorised-users.json"
},
}
在這種情況下本地+ OpenIDP,我能看到的日誌從OpenIDP返回console.log(" --> profile retrieved from ADFS :"
的價值觀。但是,logger.info(" profile retrieved from ADFS :"
不會打印任何內容。 我不知道爲什麼console.log工作,但不是logger.info爲2016-03-01T16:54:30.670Z - info: profile retrieved from ADFS :
爲空。 另外,console.log('--> User returned from ADFS :
記錄了用戶數據的JSON。
對於VM + ADFS,這兩個日誌都是空的。應用程序進入'/未授權'與此日誌記錄:「 - >用戶對象不可用。身份驗證不成功。」
在包含SAML選項identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'
中的identifierFormat後,我能夠將SAML響應作爲兩種情況的成功。但是,對於OpenIDP,我可以在saml:AttributeStatement
內看到像uid,givenName等的值,作爲saml:AttributeStatement
的一部分。但是,在VM + ADFS的情況下,我只看到EncryptedAssertion
。看起來我需要從IDP安裝一些密鑰,並將其用作SAML選項的一部分。
任何幫助在這裏將不勝感激。
編輯添加更多與identifierFormat:'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'相關的細節。 – Nikki