您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

AuthHandler.js 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* global APP */
  2. import Logger from '@jitsi/logger';
  3. import { openConnection } from '../../../connection';
  4. import {
  5. openAuthDialog,
  6. openLoginDialog } from '../../../react/features/authentication/actions.web';
  7. import {
  8. LoginDialog,
  9. WaitForOwnerDialog
  10. } from '../../../react/features/authentication/components';
  11. import {
  12. getTokenAuthUrl,
  13. isTokenAuthEnabled
  14. } from '../../../react/features/authentication/functions';
  15. import { getReplaceParticipant } from '../../../react/features/base/config/functions';
  16. import { isDialogOpen } from '../../../react/features/base/dialog/functions';
  17. import { setJWT } from '../../../react/features/base/jwt/actions';
  18. import UIUtil from '../util/UIUtil';
  19. import ExternalLoginDialog from './LoginDialog';
  20. let externalAuthWindow;
  21. const logger = Logger.getLogger(__filename);
  22. /**
  23. * Authenticate using external service or just focus
  24. * external auth window if there is one already.
  25. *
  26. * @param {JitsiConference} room
  27. * @param {string} [lockPassword] password to use if the conference is locked
  28. */
  29. function doExternalAuth(room, lockPassword) {
  30. const config = APP.store.getState()['features/base/config'];
  31. if (externalAuthWindow) {
  32. externalAuthWindow.focus();
  33. return;
  34. }
  35. if (room.isJoined()) {
  36. let getUrl;
  37. if (isTokenAuthEnabled(config)) {
  38. getUrl = Promise.resolve(getTokenAuthUrl(config)(room.getName(), true));
  39. initJWTTokenListener(room);
  40. } else {
  41. getUrl = room.getExternalAuthUrl(true);
  42. }
  43. getUrl.then(url => {
  44. externalAuthWindow = ExternalLoginDialog.showExternalAuthDialog(
  45. url,
  46. () => {
  47. externalAuthWindow = null;
  48. if (!isTokenAuthEnabled(config)) {
  49. room.join(lockPassword);
  50. }
  51. }
  52. );
  53. });
  54. } else if (isTokenAuthEnabled(config)) {
  55. redirectToTokenAuthService(room.getName());
  56. } else {
  57. room.getExternalAuthUrl().then(UIUtil.redirect);
  58. }
  59. }
  60. /**
  61. * Redirect the user to the token authentication service for the login to be
  62. * performed. Once complete it is expected that the service will bring the user
  63. * back with "?jwt={the JWT token}" query parameter added.
  64. * @param {string} [roomName] the name of the conference room.
  65. */
  66. export function redirectToTokenAuthService(roomName) {
  67. const config = APP.store.getState()['features/base/config'];
  68. // FIXME: This method will not preserve the other URL params that were
  69. // originally passed.
  70. UIUtil.redirect(getTokenAuthUrl(config)(roomName, false));
  71. }
  72. /**
  73. * Initializes 'message' listener that will wait for a JWT token to be received
  74. * from the token authentication service opened in a popup window.
  75. * @param room the name of the conference room.
  76. */
  77. function initJWTTokenListener(room) {
  78. /**
  79. *
  80. */
  81. function listener({ data, source }) {
  82. if (externalAuthWindow !== source) {
  83. logger.warn('Ignored message not coming '
  84. + 'from external authnetication window');
  85. return;
  86. }
  87. let jwt;
  88. if (data && (jwt = data.jwtToken)) {
  89. logger.info('Received JSON Web Token (JWT):', jwt);
  90. APP.store.dispatch(setJWT(jwt));
  91. const roomName = room.getName();
  92. openConnection({
  93. retry: false,
  94. roomName
  95. }).then(connection => {
  96. // Start new connection
  97. const newRoom = connection.initJitsiConference(
  98. roomName, APP.conference._getConferenceOptions());
  99. // Authenticate from the new connection to get
  100. // the session-ID from the focus, which will then be used
  101. // to upgrade current connection's user role
  102. newRoom.room.moderator.authenticate()
  103. .then(() => {
  104. connection.disconnect();
  105. // At this point we'll have session-ID stored in
  106. // the settings. It will be used in the call below
  107. // to upgrade user's role
  108. room.room.moderator.authenticate()
  109. .then(() => {
  110. logger.info('User role upgrade done !');
  111. // eslint-disable-line no-use-before-define
  112. unregister();
  113. })
  114. .catch((err, errCode) => {
  115. logger.error('Authentication failed: ',
  116. err, errCode);
  117. unregister();
  118. });
  119. })
  120. .catch((error, code) => {
  121. unregister();
  122. connection.disconnect();
  123. logger.error(
  124. 'Authentication failed on the new connection',
  125. error, code);
  126. });
  127. }, err => {
  128. unregister();
  129. logger.error('Failed to open new connection', err);
  130. });
  131. }
  132. }
  133. /**
  134. *
  135. */
  136. function unregister() {
  137. window.removeEventListener('message', listener);
  138. }
  139. if (window.addEventListener) {
  140. window.addEventListener('message', listener, false);
  141. }
  142. }
  143. /**
  144. * Authenticate for the conference.
  145. * Uses external service for auth if conference supports that.
  146. * @param {JitsiConference} room
  147. * @param {string} [lockPassword] password to use if the conference is locked
  148. */
  149. function authenticate(room, lockPassword) {
  150. const config = APP.store.getState()['features/base/config'];
  151. if (isTokenAuthEnabled(config) || room.isExternalAuthEnabled()) {
  152. doExternalAuth(room, lockPassword);
  153. } else {
  154. APP.store.dispatch(openLoginDialog());
  155. }
  156. }
  157. /**
  158. * Notify user that authentication is required to create the conference.
  159. * @param {JitsiConference} room
  160. * @param {string} [lockPassword] password to use if the conference is locked
  161. */
  162. function requireAuth(room, lockPassword) {
  163. if (isDialogOpen(APP.store, WaitForOwnerDialog) || isDialogOpen(APP.store, LoginDialog)) {
  164. return;
  165. }
  166. APP.store.dispatch(
  167. openAuthDialog(
  168. room.getName(), authenticate.bind(null, room, lockPassword))
  169. );
  170. }
  171. /**
  172. * De-authenticate local user.
  173. *
  174. * @param {JitsiConference} room
  175. * @param {string} [lockPassword] password to use if the conference is locked
  176. * @returns {Promise}
  177. */
  178. function logout(room) {
  179. return new Promise(resolve => {
  180. room.room.moderator.logout(resolve);
  181. }).then(url => {
  182. // de-authenticate conference on the fly
  183. if (room.isJoined()) {
  184. const replaceParticipant = getReplaceParticipant(APP.store.getState());
  185. room.join(null, replaceParticipant);
  186. }
  187. return url;
  188. });
  189. }
  190. export default {
  191. authenticate,
  192. logout,
  193. requireAuth
  194. };