Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

functions.web.ts 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import base64js from 'base64-js';
  2. import { IConfig } from '../base/config/configType';
  3. import { browser } from '../base/lib-jitsi-meet';
  4. import { _getTokenAuthState } from './functions.any';
  5. export * from './functions.any';
  6. /**
  7. * Based on rfc7636 we need a random string for a code verifier.
  8. */
  9. const POSSIBLE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  10. /**
  11. * Crypto random, alternative of Math.random.
  12. *
  13. * @returns {float} A random value.
  14. */
  15. function _cryptoRandom() {
  16. const typedArray = new Uint8Array(1);
  17. const randomValue = crypto.getRandomValues(typedArray)[0];
  18. return randomValue / Math.pow(2, 8);
  19. }
  20. /**
  21. * Creates the URL pointing to JWT token authentication service. It is
  22. * formatted from the 'urlPattern' argument which can contain the following
  23. * constants:
  24. * '{room}' - name of the conference room passed as <tt>roomName</tt>
  25. * argument to this method.
  26. *
  27. * @param {Object} config - Configuration state object from store. A URL pattern pointing to the login service.
  28. * @param {URL} locationURL - The location URL.
  29. * @param {Object} options: - Config options {
  30. * audioMuted: boolean | undefined
  31. * audioOnlyEnabled: boolean | undefined,
  32. * skipPrejoin: boolean | undefined,
  33. * videoMuted: boolean | undefined
  34. * }.
  35. * @param {string?} roomName - The room name.
  36. * @param {string?} tenant - The tenant name if any.
  37. *
  38. * @returns {Promise<string|undefined>} - The URL pointing to JWT login service or
  39. * <tt>undefined</tt> if the pattern stored in config is not a string and the URL can not be
  40. * constructed.
  41. */
  42. export const getTokenAuthUrl = (
  43. config: IConfig,
  44. locationURL: URL,
  45. options: {
  46. audioMuted: boolean | undefined;
  47. audioOnlyEnabled: boolean | undefined;
  48. skipPrejoin: boolean | undefined;
  49. videoMuted: boolean | undefined;
  50. },
  51. roomName: string | undefined,
  52. // eslint-disable-next-line max-params
  53. tenant: string | undefined): Promise<string | undefined> => {
  54. const {
  55. audioMuted = false,
  56. audioOnlyEnabled = false,
  57. skipPrejoin = false,
  58. videoMuted = false
  59. } = options;
  60. let url = config.tokenAuthUrl;
  61. if (!url || !roomName) {
  62. return Promise.resolve(undefined);
  63. }
  64. if (url.indexOf('{state}')) {
  65. const state = _getTokenAuthState(
  66. locationURL,
  67. {
  68. audioMuted,
  69. audioOnlyEnabled,
  70. skipPrejoin,
  71. videoMuted
  72. },
  73. roomName,
  74. tenant
  75. );
  76. if (browser.isElectron()) {
  77. // @ts-ignore
  78. state.electron = true;
  79. }
  80. url = url.replace('{state}', encodeURIComponent(JSON.stringify(state)));
  81. }
  82. url = url.replace('{room}', roomName);
  83. if (url.indexOf('{code_challenge}')) {
  84. let codeVerifier = '';
  85. // random string
  86. for (let i = 0; i < 64; i++) {
  87. codeVerifier += POSSIBLE_CHARS.charAt(Math.floor(_cryptoRandom() * POSSIBLE_CHARS.length));
  88. }
  89. window.sessionStorage.setItem('code_verifier', codeVerifier);
  90. return window.crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier))
  91. .then(digest => {
  92. // prepare code challenge - base64 encoding without padding as described in:
  93. // https://datatracker.ietf.org/doc/html/rfc7636#appendix-A
  94. const codeChallenge = base64js.fromByteArray(new Uint8Array(digest))
  95. .replace(/=/g, '')
  96. .replace(/\+/g, '-')
  97. .replace(/\//g, '_');
  98. return url ? url.replace('{code_challenge}', codeChallenge) : undefined;
  99. });
  100. }
  101. return Promise.resolve(url);
  102. };