2016-07-11 11:44:49 +00:00
|
|
|
/* global APP, config, JitsiMeetJS, Promise */
|
2015-12-17 15:31:11 +00:00
|
|
|
|
2016-01-06 22:39:13 +00:00
|
|
|
import LoginDialog from './LoginDialog';
|
|
|
|
import UIUtil from '../util/UIUtil';
|
|
|
|
import {openConnection} from '../../../connection';
|
2015-12-17 15:31:11 +00:00
|
|
|
|
|
|
|
const ConferenceEvents = JitsiMeetJS.events.conference;
|
2016-07-11 11:44:49 +00:00
|
|
|
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
2015-12-17 15:31:11 +00:00
|
|
|
|
|
|
|
let externalAuthWindow;
|
|
|
|
let authRequiredDialog;
|
|
|
|
|
2016-07-11 11:46:11 +00:00
|
|
|
let isTokenAuthEnabled
|
|
|
|
= typeof config.tokenAuthUrl === "string" && config.tokenAuthUrl.length;
|
|
|
|
let getTokenAuthUrl
|
|
|
|
= JitsiMeetJS.util.AuthUtil.getTokenAuthUrl.bind(null, config.tokenAuthUrl);
|
|
|
|
|
2016-01-15 14:59:35 +00:00
|
|
|
/**
|
|
|
|
* Authenticate using external service or just focus
|
|
|
|
* external auth window if there is one already.
|
|
|
|
*
|
|
|
|
* @param {JitsiConference} room
|
|
|
|
* @param {string} [lockPassword] password to use if the conference is locked
|
|
|
|
*/
|
2015-12-17 15:31:11 +00:00
|
|
|
function doExternalAuth (room, lockPassword) {
|
|
|
|
if (externalAuthWindow) {
|
|
|
|
externalAuthWindow.focus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (room.isJoined()) {
|
2016-07-11 11:46:11 +00:00
|
|
|
let getUrl;
|
|
|
|
if (isTokenAuthEnabled) {
|
|
|
|
getUrl = Promise.resolve(getTokenAuthUrl(room.getName(), true));
|
|
|
|
initJWTTokenListener(room);
|
|
|
|
} else {
|
|
|
|
getUrl = room.getExternalAuthUrl(true);
|
|
|
|
}
|
|
|
|
getUrl.then(function (url) {
|
2015-12-17 15:31:11 +00:00
|
|
|
externalAuthWindow = LoginDialog.showExternalAuthDialog(
|
|
|
|
url,
|
|
|
|
function () {
|
|
|
|
externalAuthWindow = null;
|
2016-07-11 11:46:11 +00:00
|
|
|
if (!isTokenAuthEnabled) {
|
|
|
|
room.join(lockPassword);
|
|
|
|
}
|
2015-12-17 15:31:11 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// If conference has not been started yet
|
|
|
|
// then redirect to login page
|
2016-07-11 11:46:11 +00:00
|
|
|
if (isTokenAuthEnabled) {
|
|
|
|
redirectToTokenAuthService(room.getName());
|
|
|
|
} else {
|
|
|
|
room.getExternalAuthUrl().then(UIUtil.redirect);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Redirect the user to the token authentication service for the login to be
|
|
|
|
* performed. Once complete it is expected that the service wil bring the user
|
|
|
|
* back with "?jwt={the JWT token}" query parameter added.
|
|
|
|
* @param {string} [roomName] the name of the conference room.
|
|
|
|
*/
|
|
|
|
function redirectToTokenAuthService(roomName) {
|
|
|
|
UIUtil.redirect(getTokenAuthUrl(roomName, false));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes 'message' listener that will wait for a JWT token to be received
|
|
|
|
* from the token authentication service opened in a popup window.
|
|
|
|
* @param room the name fo the conference room.
|
|
|
|
*/
|
|
|
|
function initJWTTokenListener(room) {
|
|
|
|
var self = this;
|
|
|
|
var listener = function (event) {
|
|
|
|
if (externalAuthWindow !== event.source) {
|
|
|
|
console.warn("Ignored message not coming " +
|
|
|
|
"from external authnetication window");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event.data && event.data.jwtToken) {
|
|
|
|
config.token = event.data.jwtToken;
|
|
|
|
console.info("Received JWT token:", config.token);
|
|
|
|
var roomName = room.getName();
|
|
|
|
openConnection({retry: false, roomName: roomName })
|
|
|
|
.then(function (connection) {
|
|
|
|
// Start new connection
|
|
|
|
let newRoom = connection.initJitsiConference(
|
|
|
|
roomName, APP.conference._getConferenceOptions());
|
|
|
|
// Authenticate from the new connection to get
|
|
|
|
// the session-ID from the focus, which wil then be used
|
|
|
|
// to upgrade current connection's user role
|
|
|
|
newRoom.room.moderator.authenticate().then(function () {
|
|
|
|
connection.disconnect();
|
|
|
|
// At this point we'll have session-ID stored in
|
|
|
|
// the settings. It wil be used in the call below
|
|
|
|
// to upgrade user's role
|
|
|
|
room.room.moderator.authenticate()
|
|
|
|
.then(function () {
|
|
|
|
console.info("User role upgrade done !");
|
|
|
|
unregister();
|
|
|
|
}).catch(function (err, errCode) {
|
|
|
|
console.error(
|
|
|
|
"Authentication failed: ", err, errCode);
|
|
|
|
unregister();
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}).catch(function (error, code) {
|
|
|
|
unregister();
|
|
|
|
connection.disconnect();
|
|
|
|
console.error(
|
|
|
|
'Authentication failed on the new connection',
|
|
|
|
error, code);
|
|
|
|
});
|
|
|
|
}, function (err) {
|
|
|
|
unregister();
|
|
|
|
console.error("Failed to open new connection", err);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
var unregister = function () {
|
|
|
|
window.removeEventListener("message", listener);
|
|
|
|
};
|
|
|
|
if (window.addEventListener) {
|
|
|
|
window.addEventListener("message", listener, false);
|
2015-12-17 15:31:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-15 14:59:35 +00:00
|
|
|
/**
|
|
|
|
* Authenticate on the server.
|
|
|
|
* @param {JitsiConference} room
|
|
|
|
* @param {string} [lockPassword] password to use if the conference is locked
|
|
|
|
*/
|
2015-12-17 15:31:11 +00:00
|
|
|
function doXmppAuth (room, lockPassword) {
|
|
|
|
let loginDialog = LoginDialog.showAuthDialog(function (id, password) {
|
|
|
|
// auth "on the fly":
|
|
|
|
// 1. open new connection with proper id and password
|
|
|
|
// 2. connect to the room
|
|
|
|
// (this will store sessionId in the localStorage)
|
|
|
|
// 3. close new connection
|
|
|
|
// 4. reallocate focus in current room
|
2016-06-28 16:21:37 +00:00
|
|
|
openConnection({id, password, roomName: room.getName()}).then(
|
|
|
|
function (connection) {
|
2015-12-17 15:31:11 +00:00
|
|
|
// open room
|
2016-02-16 15:42:28 +00:00
|
|
|
let newRoom = connection.initJitsiConference(
|
|
|
|
room.getName(), APP.conference._getConferenceOptions()
|
|
|
|
);
|
2015-12-17 15:31:11 +00:00
|
|
|
|
2015-12-29 14:41:24 +00:00
|
|
|
loginDialog.displayConnectionStatus(
|
|
|
|
APP.translation.translateString('connection.FETCH_SESSION_ID')
|
|
|
|
);
|
2015-12-21 13:02:07 +00:00
|
|
|
|
2015-12-29 14:41:24 +00:00
|
|
|
newRoom.room.moderator.authenticate().then(function () {
|
2015-12-17 15:31:11 +00:00
|
|
|
connection.disconnect();
|
2015-12-29 14:41:24 +00:00
|
|
|
|
|
|
|
loginDialog.displayConnectionStatus(
|
|
|
|
APP.translation.translateString('connection.GOT_SESSION_ID')
|
|
|
|
);
|
2015-12-21 13:02:07 +00:00
|
|
|
|
2016-02-25 13:52:15 +00:00
|
|
|
// authenticate conference on the fly
|
2016-02-25 12:32:34 +00:00
|
|
|
room.join(lockPassword);
|
2015-12-17 15:31:11 +00:00
|
|
|
|
2015-12-29 14:41:24 +00:00
|
|
|
loginDialog.close();
|
|
|
|
}).catch(function (error, code) {
|
|
|
|
connection.disconnect();
|
|
|
|
|
|
|
|
console.error('Auth on the fly failed', error);
|
|
|
|
|
|
|
|
let errorMsg = APP.translation.translateString(
|
|
|
|
'connection.GET_SESSION_ID_ERROR'
|
|
|
|
);
|
|
|
|
|
|
|
|
loginDialog.displayError(errorMsg + code);
|
|
|
|
});
|
2015-12-17 15:31:11 +00:00
|
|
|
}, function (err) {
|
|
|
|
loginDialog.displayError(err);
|
|
|
|
});
|
|
|
|
}, function () { // user canceled
|
|
|
|
loginDialog.close();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-01-15 14:59:35 +00:00
|
|
|
/**
|
|
|
|
* Authenticate for the conference.
|
|
|
|
* Uses external service for auth if conference supports that.
|
|
|
|
* @param {JitsiConference} room
|
|
|
|
* @param {string} [lockPassword] password to use if the conference is locked
|
|
|
|
*/
|
2015-12-17 15:31:11 +00:00
|
|
|
function authenticate (room, lockPassword) {
|
2016-07-11 11:46:11 +00:00
|
|
|
if (isTokenAuthEnabled || room.isExternalAuthEnabled()) {
|
2015-12-17 15:31:11 +00:00
|
|
|
doExternalAuth(room, lockPassword);
|
|
|
|
} else {
|
2016-02-16 15:42:28 +00:00
|
|
|
doXmppAuth(room, lockPassword);
|
2015-12-17 15:31:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-25 13:52:15 +00:00
|
|
|
/**
|
|
|
|
* De-authenticate local user.
|
|
|
|
*
|
|
|
|
* @param {JitsiConference} room
|
|
|
|
* @param {string} [lockPassword] password to use if the conference is locked
|
|
|
|
* @returns {Promise}
|
|
|
|
*/
|
|
|
|
function logout (room) {
|
|
|
|
return new Promise(function (resolve) {
|
|
|
|
room.room.moderator.logout(resolve);
|
|
|
|
}).then(function (url) {
|
|
|
|
// de-authenticate conference on the fly
|
|
|
|
if (room.isJoined()) {
|
|
|
|
room.join();
|
|
|
|
}
|
|
|
|
|
|
|
|
return url;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-01-15 14:59:35 +00:00
|
|
|
/**
|
|
|
|
* Notify user that authentication is required to create the conference.
|
2016-02-16 15:42:28 +00:00
|
|
|
* @param {JitsiConference} room
|
|
|
|
* @param {string} [lockPassword] password to use if the conference is locked
|
2016-01-15 14:59:35 +00:00
|
|
|
*/
|
2016-02-16 15:42:28 +00:00
|
|
|
function requireAuth(room, lockPassword) {
|
2015-12-17 15:31:11 +00:00
|
|
|
if (authRequiredDialog) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
authRequiredDialog = LoginDialog.showAuthRequiredDialog(
|
2016-02-16 15:42:28 +00:00
|
|
|
room.getName(), authenticate.bind(null, room, lockPassword)
|
2015-12-17 15:31:11 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-01-15 14:59:35 +00:00
|
|
|
/**
|
|
|
|
* Close auth-related dialogs if there are any.
|
|
|
|
*/
|
2015-12-17 15:31:11 +00:00
|
|
|
function closeAuth() {
|
|
|
|
if (externalAuthWindow) {
|
|
|
|
externalAuthWindow.close();
|
|
|
|
externalAuthWindow = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (authRequiredDialog) {
|
|
|
|
authRequiredDialog.close();
|
|
|
|
authRequiredDialog = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-11 11:44:49 +00:00
|
|
|
function showXmppPasswordPrompt(roomName, connect) {
|
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
let authDialog = LoginDialog.showAuthDialog(
|
|
|
|
function (id, password) {
|
|
|
|
connect(id, password, roomName).then(function (connection) {
|
|
|
|
authDialog.close();
|
|
|
|
resolve(connection);
|
|
|
|
}, function (err) {
|
|
|
|
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
|
|
|
authDialog.displayError(err);
|
|
|
|
} else {
|
|
|
|
authDialog.close();
|
|
|
|
reject(err);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Show Authentication Dialog and try to connect with new credentials.
|
|
|
|
* If failed to connect because of PASSWORD_REQUIRED error
|
|
|
|
* then ask for password again.
|
|
|
|
* @param {string} [roomName] name of the conference room
|
|
|
|
* @param {function(id, password, roomName)} [connect] function that returns
|
|
|
|
* a Promise which resolves with JitsiConnection or fails with one of
|
|
|
|
* ConnectionErrors.
|
|
|
|
* @returns {Promise<JitsiConnection>}
|
|
|
|
*/
|
|
|
|
function requestAuth(roomName, connect) {
|
2016-07-11 11:46:11 +00:00
|
|
|
if (isTokenAuthEnabled) {
|
|
|
|
// This Promise never resolves as user gets redirected to another URL
|
2016-07-15 18:14:10 +00:00
|
|
|
return new Promise(function (resolve, reject) {
|
2016-07-11 11:46:11 +00:00
|
|
|
redirectToTokenAuthService(roomName);
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
return showXmppPasswordPrompt(roomName, connect);
|
|
|
|
}
|
2016-07-11 11:44:49 +00:00
|
|
|
}
|
|
|
|
|
2015-12-17 15:31:11 +00:00
|
|
|
|
|
|
|
export default {
|
|
|
|
authenticate,
|
|
|
|
requireAuth,
|
2016-07-11 11:44:49 +00:00
|
|
|
requestAuth,
|
2016-02-25 13:52:15 +00:00
|
|
|
closeAuth,
|
|
|
|
logout
|
2015-12-17 15:31:11 +00:00
|
|
|
};
|