Мне нужно аутентифицировать пользователя с помощью passport-saml v2.0 и войти в систему после того, как аутентификационный обратный вызов успешно отвечает на почтовый запрос IDP.
Я использую React на входе с потоковым маршрутизатором, а Picker - обратно -end.
Я запускаю аутентификацию на стороне клиента, когда нажимаю кнопку, и это создает окно с запросом /auth/saml.
Код работает, и мой пользователь успешно добавлен в mongodb, но теперь, после того, как функция userHandler вернула userId и токен, я хочу использовать Meteor.loginWithToken для входа, но эта функция не работает на стороне сервера.
Основная проблема заключается в использовании информации пользователя, полученной IDP, в функции обратного вызова и входе в систему с использованием Meteor с этой информацией.
Сторона сервера: код для запуска аутентификации с использованием стратегии passport js и passport-saml
import { Picker} from 'meteor/meteorhacks:picker';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import passport from 'passport';
import saml from 'passport-saml';
import expressSession from 'express-session';
Picker.middleware(bodyParser.json());
Picker.middleware(bodyParser.urlencoded({extended:false}));
Picker.middleware(cookieParser());
Picker.middleware(expressSession({
secret: 'secret',
resave: false,
saveUninitialized: true,
}));
var samlStrategy = new saml.Strategy({
callbackUrl: process.env.ROOT_URL + '/login/callback', //call back in service provider to handle with the IDP response
entryPoint: 'http://localhost:8080/simplesaml/saml2/idp/SSOService.php', //link for IDP
issuer: 'saml-poc', //id da entidade provedora
identifierFormat: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', //formato requisitado pela entidade
decryptionPvk: process.env.CERTPVK,
privateCert: process.env.CERTPVK,
cert: process.env.IDPKEY,
validateInResponseTo: false,
disableRequestedAuthnContext: true,
}, function(profile, done) {
return done(null, profile);
});
passport.use('samlStrategy', samlStrategy);
Picker.middleware(passport.initialize({}));
Picker.middleware(passport.session({}));
//serialize the user
passport.serializeUser(function(user, done) {
console.log('-----------------------------');
console.log('serialize user');
console.log(user);
console.log('-----------------------------');
done(null, user);
});
//deserialize
passport.deserializeUser(function(user, done) {
console.log('-----------------------------');
console.log('deserialize user');
console.log(user);
console.log('-----------------------------');
done(null, user);
});
Picker.route('/auth/saml',
function(params, req, res, next) {
console.log('Start login handler');
passport.authenticate('samlStrategy', {
session: false,
},
function(err, user, info) {
if (err) {
console.log("Error1");
return next(err);
}
if (!user) {
console.log("Error2");
return res.json(401, {
error: 'Auth Error!'
});
}
}
)(req, res, next);
}
);
Picker.route('/auth/callback',
function (params, req, res, next) {
console.log('-----------------------------');
console.log('/Start login callback ');
passport.authenticate('samlStrategy', {
session: false,
},
async function (err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.json(401, {
error: 'Auth Error!'
});
}
const {userId, token} = await userHandler(user);
res.write("<script>window.close();</script>");
res.flushHeaders();
res.end('Sucess');
})(req, res, next);
});
const userHandler = (user) => new Promise((resolve, reject) => {
let usr = Accounts.findUserByEmail(user.email);
const company = "company";
const profile = { name: "Vinicius França" };
const stampedToken = Accounts._generateStampedLoginToken();
if(!usr){
Meteor.call('adminUser_addNewUser', user.email, null, profile, company, "user", undefined, undefined, true, (err,res) => {
if(!res){
SweetAlert('OPS...', 'Error', 'error');
}
Accounts.findUserByEmail(user.email).then((_usr) => {
Accounts._insertLoginToken(_usr._id, stampedToken);
resolve({userId: _usr._id, token: stampedToken});
})
});
} else {
Accounts._clearAllLoginTokens(usr._id);
Accounts._insertLoginToken(usr._id, stampedToken);
resolve({userId: usr._id, token: stampedToken});
}
});
Клиентская сторона:
logginSAML() {
this.setState({logginSSO: true});
let authWindow = window.open(
window.location.href + "/auth/saml",
"Window SSO",
"resizable=no,scrollbars=yes,status=yes",
"height=1000px",
"width=100px",
"_blank"
);
const _this = this;
window.onunload = window.onbeforeunload = (e) => {
//is not working
//call login with token here
_this.setState({logginSSO: false});
console.log('q loucura man');
e.returnValue = '';
delete e['returnValue'];
};
}