Meteor.loginWithSaml = function(options, callback) { options = options || {}; options.credentialToken = Meteor.default_connection._lastSessionId; Accounts.saml.initiateLogin(options, function(/* error, result*/) { Accounts.callLoginMethod({ methodArguments: [{ saml: true, }], userCallback: callback, }); }); };
_saml.validateResponse(req.body.SAMLResponse, req.body.RelayState, function(err, profile/* , loggedOut*/) { if (err) { throw new Error(`Unable to validate response url: ${ err }`); } const credentialToken = (profile.inResponseToId && profile.inResponseToId.value) || profile.inResponseToId || profile.InResponseTo || samlObject.credentialToken; const loginResult = { profile, }; if (!credentialToken) { // No credentialToken in IdP-initiated SSO const saml_idp_credentialToken = Random.id(); Accounts.saml.storeCredential(saml_idp_credentialToken, loginResult); const url = `${ Meteor.absoluteUrl('home') }?saml_idp_credentialToken=${ saml_idp_credentialToken }`; res.writeHead(302, { Location: url, }); res.end(); } else { Accounts.saml.storeCredential(credentialToken, loginResult); closePopup(res); } });
Accounts.registerLoginHandler(function(loginRequest) { if (!loginRequest.saml) { return undefined; } const loginResult = Accounts.saml.retrieveCredential(this.connection.id); if (Accounts.saml.settings.debug) { console.log(`RESULT :${ JSON.stringify(loginResult) }`); } if (loginResult === undefined) { return { type: 'saml', error: new Meteor.Error(Accounts.LoginCancelledError.numericError, 'No matching login attempt found'), }; } if (loginResult && loginResult.profile && loginResult.profile.email) { const emailList = Array.isArray(loginResult.profile.email) ? loginResult.profile.email : [loginResult.profile.email]; const emailRegex = new RegExp(emailList.map((email) => `^${ RegExp.escape(email) }$`).join('|'), 'i'); let user = Meteor.users.findOne({ 'emails.address': emailRegex, }); if (!user) { const newUser = { name: loginResult.profile.displayName || loginResult.profile.cn || loginResult.profile.username, active: true, globalRoles: ['user'], emails: emailList.map((email) => ({ address: email, verified: true, })), }; if (Accounts.saml.settings.generateUsername === true) { const username = generateUsernameSuggestion(newUser); if (username) { newUser.username = username; } } else if (loginResult.profile.username) { newUser.username = loginResult.profile.username; } const userId = Accounts.insertUserDoc({}, newUser); user = Meteor.users.findOne(userId); } // creating the token and adding to the user const stampedToken = Accounts._generateStampedLoginToken(); Meteor.users.update(user, { $push: { 'services.resume.loginTokens': stampedToken, }, }); const samlLogin = { provider: Accounts.saml.RelayState, idp: loginResult.profile.issuer, idpSession: loginResult.profile.sessionIndex, nameID: loginResult.profile.nameID, }; Meteor.users.update({ _id: user._id, }, { $set: { // TBD this should be pushed, otherwise we're only able to SSO into a single IDP at a time 'services.saml': samlLogin, }, }); // sending token along with the userId const result = { userId: user._id, token: stampedToken.token, }; return result; } else { throw new Error('SAML Profile did not contain an email address'); } });