-
Notifications
You must be signed in to change notification settings - Fork 6.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Introduces passing state to the token authUrl.
- Loading branch information
Showing
9 changed files
with
240 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { IConfig } from '../base/config/configType'; | ||
import { getBackendSafeRoomName } from '../base/util/uri'; | ||
|
||
/** | ||
* Checks if the token for authentication is available. | ||
* | ||
* @param {Object} config - Configuration state object from store. | ||
* @returns {boolean} | ||
*/ | ||
export const isTokenAuthEnabled = (config: IConfig): boolean => | ||
typeof config.tokenAuthUrl === 'string' && config.tokenAuthUrl.length > 0; | ||
|
||
/** | ||
* Returns the state that we can add as a parameter to the tokenAuthUrl. | ||
* | ||
* @param {string?} roomName - The room name. | ||
* @param {string?} tenant - The tenant name if any. | ||
* @param {boolean} skipPrejoin - Whether to skip pre-join page. | ||
* @returns {Object} The state object. | ||
*/ | ||
export const _getTokenAuthState = ( | ||
roomName: string | undefined, | ||
tenant: string | undefined, | ||
skipPrejoin: boolean | undefined = false): object => { | ||
const state = { | ||
room: roomName, | ||
roomSafe: getBackendSafeRoomName(roomName), | ||
tenant | ||
}; | ||
|
||
if (skipPrejoin) { | ||
// We have already shown the prejoin screen, no need to show it again after obtaining the token. | ||
// @ts-ignore | ||
state['config.prejoinConfig.enabled'] = false; | ||
} | ||
|
||
const params = new URLSearchParams(window.location.search); | ||
|
||
for (const [ key, value ] of params) { | ||
// we allow only config and interfaceConfig overrides in the state | ||
if (key.startsWith('config.') || key.startsWith('interfaceConfig.')) { | ||
// @ts-ignore | ||
state[key] = value; | ||
} | ||
} | ||
|
||
return state; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Platform } from 'react-native'; | ||
|
||
import { IConfig } from '../base/config/configType'; | ||
|
||
import { _getTokenAuthState } from './functions.any'; | ||
|
||
export * from './functions.any'; | ||
|
||
/** | ||
* Creates the URL pointing to JWT token authentication service. It is | ||
* formatted from the 'urlPattern' argument which can contain the following | ||
* constants: | ||
* '{room}' - name of the conference room passed as <tt>roomName</tt> | ||
* argument to this method. | ||
* | ||
* @param {Object} config - Configuration state object from store. A URL pattern pointing to the login service. | ||
* @param {string} roomName - The name of the conference room for which the user will be authenticated. | ||
* @param {string} tenant - The name of the conference tenant. | ||
* @param {string} skipPrejoin - The name of the conference room for which the user will be authenticated. | ||
* | ||
* @returns {Promise<string|undefined>} - The URL pointing to JWT login service or | ||
* <tt>undefined</tt> if the pattern stored in config is not a string and the URL can not be | ||
* constructed. | ||
*/ | ||
export const getTokenAuthUrl = ( | ||
config: IConfig, | ||
roomName: string | undefined, | ||
tenant: string | undefined, | ||
skipPrejoin: boolean | undefined = false): Promise<string | undefined> => { | ||
|
||
let url = config.tokenAuthUrl; | ||
|
||
if (!url || !roomName) { | ||
return Promise.resolve(undefined); | ||
} | ||
|
||
if (url.indexOf('{state}')) { | ||
const state = _getTokenAuthState(roomName, tenant, skipPrejoin); | ||
|
||
// Append ios=true or android=true to the token URL. | ||
// @ts-ignore | ||
state[Platform.OS] = true; | ||
|
||
url = url.replace('{state}', encodeURIComponent(JSON.stringify(state))); | ||
} | ||
|
||
return Promise.resolve(url.replace('{room}', roomName)); | ||
}; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
import base64js from 'base64-js'; | ||
|
||
import { IConfig } from '../base/config/configType'; | ||
import { browser } from '../base/lib-jitsi-meet'; | ||
|
||
import { _getTokenAuthState } from './functions.any'; | ||
|
||
export * from './functions.any'; | ||
|
||
/** | ||
* Based on rfc7636 we need a random string for a code verifier. | ||
*/ | ||
const POSSIBLE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | ||
|
||
/** | ||
* Crypto random, alternative of Math.random. | ||
* | ||
* @returns {float} A random value. | ||
*/ | ||
function _cryptoRandom() { | ||
const typedArray = new Uint8Array(1); | ||
const randomValue = crypto.getRandomValues(typedArray)[0]; | ||
|
||
return randomValue / Math.pow(2, 8); | ||
} | ||
|
||
/** | ||
* Creates the URL pointing to JWT token authentication service. It is | ||
* formatted from the 'urlPattern' argument which can contain the following | ||
* constants: | ||
* '{room}' - name of the conference room passed as <tt>roomName</tt> | ||
* argument to this method. | ||
* | ||
* @param {Object} config - Configuration state object from store. A URL pattern pointing to the login service. | ||
* @param {string} roomName - The name of the conference room for which the user will be authenticated. | ||
* @param {string} tenant - The name of the conference tenant. | ||
* @param {string} skipPrejoin - The name of the conference room for which the user will be authenticated. | ||
* | ||
* @returns {Promise<string|undefined>} - The URL pointing to JWT login service or | ||
* <tt>undefined</tt> if the pattern stored in config is not a string and the URL can not be | ||
* constructed. | ||
*/ | ||
export const getTokenAuthUrl = ( | ||
config: IConfig, | ||
roomName: string | undefined, | ||
tenant: string | undefined, | ||
skipPrejoin: boolean | undefined = false): Promise<string | undefined> => { | ||
|
||
let url = config.tokenAuthUrl; | ||
|
||
if (!url || !roomName) { | ||
return Promise.resolve(undefined); | ||
} | ||
|
||
if (url.indexOf('{state}')) { | ||
const state = _getTokenAuthState(roomName, tenant, skipPrejoin); | ||
|
||
if (browser.isElectron()) { | ||
// @ts-ignore | ||
state.electron = true; | ||
} | ||
|
||
url = url.replace('{state}', encodeURIComponent(JSON.stringify(state))); | ||
} | ||
|
||
url = url.replace('{room}', roomName); | ||
|
||
if (url.indexOf('{code_challenge}')) { | ||
let codeVerifier = ''; | ||
|
||
// random string | ||
for (let i = 0; i < 64; i++) { | ||
codeVerifier += POSSIBLE_CHARS.charAt(Math.floor(_cryptoRandom() * POSSIBLE_CHARS.length)); | ||
} | ||
|
||
window.sessionStorage.setItem('code_verifier', codeVerifier); | ||
|
||
return window.crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier)) | ||
.then(digest => { | ||
// prepare code challenge - base64 encoding without padding as described in: | ||
// https://datatracker.ietf.org/doc/html/rfc7636#appendix-A | ||
const codeChallenge = base64js.fromByteArray(new Uint8Array(digest)) | ||
.replace(/=/g, '') | ||
.replace(/\+/g, '-') | ||
.replace(/\//g, '_'); | ||
|
||
return url ? url.replace('{code_challenge}', codeChallenge) : undefined; | ||
}); | ||
} | ||
|
||
return Promise.resolve(url); | ||
}; |
Oops, something went wrong.