123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- /* global APP, config, JitsiMeetJS, Promise */
-
- import Logger from 'jitsi-meet-logger';
-
- import { openConnection } from '../../../connection';
- import { setJWT } from '../../../react/features/base/jwt';
- import {
- JitsiConnectionErrors
- } from '../../../react/features/base/lib-jitsi-meet';
- import UIUtil from '../util/UIUtil';
-
- import LoginDialog from './LoginDialog';
-
- const logger = Logger.getLogger(__filename);
-
- let externalAuthWindow;
- let authRequiredDialog;
-
- const isTokenAuthEnabled
- = typeof config.tokenAuthUrl === 'string' && config.tokenAuthUrl.length;
- const getTokenAuthUrl
- = JitsiMeetJS.util.AuthUtil.getTokenAuthUrl.bind(null, config.tokenAuthUrl);
-
- /**
- * 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
- */
- function doExternalAuth(room, lockPassword) {
- if (externalAuthWindow) {
- externalAuthWindow.focus();
-
- return;
- }
- if (room.isJoined()) {
- let getUrl;
-
- if (isTokenAuthEnabled) {
- getUrl = Promise.resolve(getTokenAuthUrl(room.getName(), true));
- initJWTTokenListener(room);
- } else {
- getUrl = room.getExternalAuthUrl(true);
- }
- getUrl.then(url => {
- externalAuthWindow = LoginDialog.showExternalAuthDialog(
- url,
- () => {
- externalAuthWindow = null;
- if (!isTokenAuthEnabled) {
- room.join(lockPassword);
- }
- }
- );
- });
- } else 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 will bring the user
- * back with "?jwt={the JWT token}" query parameter added.
- * @param {string} [roomName] the name of the conference room.
- */
- function redirectToTokenAuthService(roomName) {
- // FIXME: This method will not preserve the other URL params that were
- // originally passed.
- 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 of the conference room.
- */
- function initJWTTokenListener(room) {
- /**
- *
- */
- function listener({ data, source }) {
- if (externalAuthWindow !== source) {
- logger.warn('Ignored message not coming '
- + 'from external authnetication window');
-
- return;
- }
-
- let jwt;
-
- if (data && (jwt = data.jwtToken)) {
- logger.info('Received JSON Web Token (JWT):', jwt);
-
- APP.store.dispatch(setJWT(jwt));
-
- const roomName = room.getName();
-
- openConnection({
- retry: false,
- roomName
- }).then(connection => {
- // Start new connection
- const newRoom = connection.initJitsiConference(
- roomName, APP.conference._getConferenceOptions());
-
- // Authenticate from the new connection to get
- // the session-ID from the focus, which will then be used
- // to upgrade current connection's user role
-
- newRoom.room.moderator.authenticate()
- .then(() => {
- connection.disconnect();
-
- // At this point we'll have session-ID stored in
- // the settings. It will be used in the call below
- // to upgrade user's role
- room.room.moderator.authenticate()
- .then(() => {
- logger.info('User role upgrade done !');
- // eslint-disable-line no-use-before-define
- unregister();
- })
- .catch((err, errCode) => {
- logger.error('Authentication failed: ',
- err, errCode);
- unregister();
- });
- })
- .catch((error, code) => {
- unregister();
- connection.disconnect();
- logger.error(
- 'Authentication failed on the new connection',
- error, code);
- });
- }, err => {
- unregister();
- logger.error('Failed to open new connection', err);
- });
- }
- }
-
- /**
- *
- */
- function unregister() {
- window.removeEventListener('message', listener);
- }
-
- if (window.addEventListener) {
- window.addEventListener('message', listener, false);
- }
- }
-
- /**
- * Authenticate on the server.
- * @param {JitsiConference} room
- * @param {string} [lockPassword] password to use if the conference is locked
- */
- function doXmppAuth(room, lockPassword) {
- const loginDialog = LoginDialog.showAuthDialog(
- /* successCallback */ (id, password) => {
- room.authenticateAndUpgradeRole({
- id,
- password,
- roomPassword: lockPassword,
-
- /** Called when the XMPP login succeeds. */
- onLoginSuccessful() {
- loginDialog.displayConnectionStatus(
- 'connection.FETCH_SESSION_ID');
- }
- })
- .then(
- /* onFulfilled */ () => {
- loginDialog.displayConnectionStatus(
- 'connection.GOT_SESSION_ID');
- loginDialog.close();
- },
- /* onRejected */ error => {
- logger.error('authenticateAndUpgradeRole failed', error);
-
- const { authenticationError, connectionError } = error;
-
- if (authenticationError) {
- loginDialog.displayError(
- 'connection.GET_SESSION_ID_ERROR',
- { msg: authenticationError });
- } else if (connectionError) {
- loginDialog.displayError(connectionError);
- }
- });
- },
- /* cancelCallback */ () => loginDialog.close());
- }
-
- /**
- * 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
- */
- function authenticate(room, lockPassword) {
- if (isTokenAuthEnabled || room.isExternalAuthEnabled()) {
- doExternalAuth(room, lockPassword);
- } else {
- doXmppAuth(room, lockPassword);
- }
- }
-
- /**
- * 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(resolve => {
- room.room.moderator.logout(resolve);
- }).then(url => {
- // de-authenticate conference on the fly
- if (room.isJoined()) {
- room.join();
- }
-
- return url;
- });
- }
-
- /**
- * Notify user that authentication is required to create the conference.
- * @param {JitsiConference} room
- * @param {string} [lockPassword] password to use if the conference is locked
- */
- function requireAuth(room, lockPassword) {
- if (authRequiredDialog) {
- return;
- }
-
- authRequiredDialog = LoginDialog.showAuthRequiredDialog(
- room.getName(), authenticate.bind(null, room, lockPassword)
- );
- }
-
- /**
- * Close auth-related dialogs if there are any.
- */
- function closeAuth() {
- if (externalAuthWindow) {
- externalAuthWindow.close();
- externalAuthWindow = null;
- }
-
- if (authRequiredDialog) {
- authRequiredDialog.close();
- authRequiredDialog = null;
- }
- }
-
- /**
- *
- */
- function showXmppPasswordPrompt(roomName, connect) {
- return new Promise((resolve, reject) => {
- const authDialog = LoginDialog.showAuthDialog(
- (id, password) => {
- connect(id, password, roomName).then(connection => {
- authDialog.close();
- resolve(connection);
- }, err => {
- if (err === JitsiConnectionErrors.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
- * JitsiConnectionErrors.
- * @returns {Promise<JitsiConnection>}
- */
- function requestAuth(roomName, connect) {
- if (isTokenAuthEnabled) {
- // This Promise never resolves as user gets redirected to another URL
- return new Promise(() => redirectToTokenAuthService(roomName));
- }
-
- return showXmppPasswordPrompt(roomName, connect);
-
- }
-
- export default {
- authenticate,
- requireAuth,
- requestAuth,
- closeAuth,
- logout
- };
|