jitsi / jitsi-meet

Jitsi Meet - Secure, Simple and Scalable Video Conferences that you use as a standalone app or embed in your web application.
https://jitsi.org/meet
Apache License 2.0
22.1k stars 6.58k forks source link

Trying to use E2ee module in jitis meet utilizing externally managed key handler but not found option to add external key #14704

Open VeshRaazThapa opened 2 months ago

VeshRaazThapa commented 2 months ago

Issue: Setting Media Encryption Key and Activating Externally Managed Key Mechanism in Jitsi Meet

Description:

I've successfully activated end-to-end encryption (E2EE) in Jitsi Meet by toggling the option in the security settings. However, I encountered difficulties setting the media encryption key, which led me to hardcode my encryption key in jitsi-meet/react/features/e2ee/middleware.ts.

To ensure the encryption key is properly set when participants join, I've dispatched the toggle button from code using dispatch(toggleE2EE(false));.

Additionally, I tried activating the externally managed key mechanism by setting externallyManagedKey: true in config.js. However, this didn't work as expected, and I had to modify reducer.ts to include the line:

newValue.e2ee = newValue.e2ee || {
    externallyManagedKey: true,
};

I'm seeking guidance on a better approach to set the media encryption key in Jitsi Meet when using an externally managed key handler. Also, I'd like to resolve the issue with activating the externally managed key mechanism.

Steps to Reproduce:

  1. Activate end-to-end encryption in Jitsi Meet.
  2. Attempt to set the media encryption key programmatically.
  3. Set externallyManagedKey: true in config.js.
  4. Observe that the externally managed key mechanism is not activated.
  5. Modify reducer.ts as mentioned to activate the mechanism.

Expected Behavior:

  1. Ability to set the media encryption key programmatically without hardcoding.
  2. Successful activation of the externally managed key mechanism by setting externallyManagedKey: true in config.js.

Server information:

Client information:

Additional information:

damencho commented 2 months ago

Please, when you have questions or problems use the community forum before opening new issues, thank you.

saghul commented 2 months ago

The external key needs to be set using the iframe API, it's not designed for direct user access.

What problem did you have with the automatic key management?

damencho commented 2 months ago

Here is an example of setting the key via iframe API and toggling e2ee in the meeting:

https://github.com/jitsi/jitsi-meet/blob/62d0d253957a82c9986cad0c66e53188cc64549b/doc/jaas/index-jaas.html#L14

monidp9 commented 1 month ago

I follow the problem @VeshRaazThapa has reported. Specifically, it seems the config.js file is not considered at all. I decommented the e2ee section but when I access e2ee.externallyManagedKey it is undefined.

saghul commented 1 month ago

Can you share the full piece of code of what you're trying to do?

monidp9 commented 1 month ago

The app is running on local through make dev. I just modified the UI of E2EESection.tsx. The following is the code snippet.

const E2EESection = ({
    _descriptionResource,
    _enabled,
    _e2eeLabels,
    _everyoneSupportE2EE,
    _toggled,
    dispatch
}: IProps) => {
    const { classes } = useStyles();
    const { t } = useTranslation();
    const [ toggled, setToggled ] = useState(_toggled ?? false);

    useEffect(() => {
        setToggled(_toggled);
    }, [ _toggled ]);

    /**
     * Callback to be invoked when the user toggles E2EE on or off.
     *
     * @private
     * @returns {void}
     */
    const _onToggle = useCallback(() => {
        const newValue = !toggled;

        setToggled(newValue);

        sendAnalytics(createE2EEEvent(`enabled.${String(newValue)}`));
        dispatch(toggleE2EE(newValue));
    }, [ toggled ]);

    const description = _e2eeLabels?.description || t(_descriptionResource ?? '');
    const label = _e2eeLabels?.label || t('dialog.e2eeLabel');
    const warning = _e2eeLabels?.warning || t('dialog.e2eeWarning');

    return (
        <div
            className = { classes.e2eeSection }
            id = 'e2ee-section'>
            <p
                aria-live = 'polite'
                className = { classes.description }
                id = 'e2ee-section-description'>
                {description}
                {!_everyoneSupportE2EE && <br />}
                {!_everyoneSupportE2EE && warning}
            </p>
            <div className = { classes.controlRow }>
                <label htmlFor = 'e2ee-section-switch'>
                    {label}
                </label>
                <Switch
                    checked = { toggled }
                    disabled = { !_enabled }
                    id = 'e2ee-section-switch'
                    onChange = { _onToggle } />
            </div>
            <div className={classes.indicatorRow}>
                <div className={e2ee.externallyManagedKey ? classes.successIndicator : classes.errorIndicator}></div>
                <label>
                    {e2ee.externallyManagedKey ? 'Externally Enabled in config file' : 'Externally Disabled in config file'}
                </label>
            </div>
        </div>
    );
};

In config.js the e2ee section is uncommented.

e2ee: {
      labels: {
        description: 'Description',
        label: 'E2EE',
        tooltip: 'Tooltip',
        warning: 'Warning',
      },
      externallyManagedKey: false
    }

Nontheless the externallyManagedKey is undefined.

saghul commented 1 month ago

Nontheless the externallyManagedKey is undefined.

I don't understand. You are configuring externallyManagedKey: false which means the internal mode is going to be used, aka the default.

In addition, you can't just change config.js, since that file is served by the deployment. You should either have your own deployment or use the iframe API and use config overrides to change the settings you want.

monidp9 commented 1 month ago

Ok I got it. Where can I find an example of iframe API? Or maybe another way for reading a config file.

saghul commented 1 month ago

Check damencho's comment above.

monidp9 commented 1 month ago

I've tried to include iframe api has below (in my custom component QKDSection.ts)

import React, { useCallback, useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { IReduxState, IStore } from '../../app/types';
import Switch from '../../base/ui/components/web/Switch';
import { toggleQKD } from '../actions';
import JitsiMeetExternalAPI from '../../../../modules/API/external/external_api';

interface IProps {
    _enabled: boolean;

    _toggled: boolean;

    dispatch: IStore['dispatch'];
}

const useStyles = makeStyles()(theme => {
    return {
        qkdSection: {
            display: 'flex',
            flexDirection: 'column'
        },

        description: {
            fontSize: '13px',
            margin: '15px 0'
        },

        controlRow: {
            display: 'flex',
            justifyContent: 'space-between',
            marginTop: '15px',

            '& label': {
                fontSize: '14px',
                fontWeight: 'bold'
            }
        }
    };
});

const QKDSection = ({
    _enabled,
    _toggled,
    dispatch
}: IProps) => {
    const { classes } = useStyles();
    const [ toggled, setToggled ] = useState(_toggled ?? false);

    useEffect(() => {
        setToggled(_toggled);
    }, [_toggled]);

    useEffect(() => {
        const domain = "alpha.jitsi.net";
        const options = {
            configOverwrite: {
                e2ee: {
                    labels: {
                        description: 'End to End Encryption',
                        label: 'E2EE',
                        tooltip: '',
                        warning: 'All users must use E2EE',
                    },
                    externallyManagedKey: true,
                }
            }
        };
        console.log("DEBUG " + options.configOverwrite.e2ee.externallyManagedKey);
        const api = new JitsiMeetExternalAPI(domain, options);

        return () => api.dispose(); // Cleanup on unmount
    }, []);

    const _onToggle = useCallback(() => {
        const newValue = !toggled;

        setToggled(newValue);

        dispatch(toggleQKD(newValue));
    }, [ toggled ]);

    return (
        <div
            className = { classes.qkdSection }
            id = 'qkd-section'>
            <p
                aria-live = 'polite'
                className = { classes.description }
                id = 'qkd-section-description'>
                {"Implementazione di QKD"}
            </p>
            <div className = { classes.controlRow }>
                <label htmlFor = 'qkd-section-switch'>
                    {"QKD Toggle"}
                </label>
                <Switch
                    checked = { toggled }
                    disabled = { false }
                    id = 'qkd-section-switch'
                    onChange = { _onToggle } />
            </div>
        </div>
    ); 
};

/**
 * Maps (parts of) the Redux state to the associated props for this component.
 *
 * @param {Object} state - The Redux state.
 * @private
 * @returns {IProps}
 */
function mapStateToProps(state: IReduxState) {
    const { enabled: e2eeEnabled } = state['features/e2ee'];
    const { toggled: qkdToggled } = state['features/qkd'];
    const { e2ee = {} } = state['features/base/config'];

    console.log("DEBUG " + e2ee.externallyManagedKey);

    return {
        _enabled: e2eeEnabled,
        _toggled: e2ee.externallyManagedKey ?? qkdToggled
    };
}

export default connect(mapStateToProps)(QKDSection);

However, this create a new instance of the conference which is not what I need. Is there an alternative to iframe api?

saghul commented 1 month ago

Sorry, I have trouble understanding what exactly it is you are trying to do. How are you integrating Jitsi onto your app? Where does the external key come from?

monidp9 commented 1 month ago

Sorry I'll try to be more clear. We are not integrating jitsi onto our app, our app is jitsi. We only want to customize the encryption key. Thus, we're modifing jitsi itself. What we want for now is the possibility to read from a confing file the externallyManagedKey in order to activate something.

saghul commented 1 month ago

Ok, it's clearer now! Then you'll want to enable the external key, yes, and then dispatch this action:

/**
 * Dispatches an action to set media encryption key.
 *
 * @param {Object} keyInfo - Json containing key information.
 * @param {string} [keyInfo.encryptionKey] - The exported encryption key.
 * @param {number} [keyInfo.index] - The index of the encryption key.
 * @returns {{
 *     type: SET_MEDIA_ENCRYPTION_KEY,
 *     keyInfo: Object
 * }}
 */
export function setMediaEncryptionKey(keyInfo: Object) {
    return {
        type: SET_MEDIA_ENCRYPTION_KEY,
        keyInfo
    };
}
monidp9 commented 1 month ago

Yes but first thing we want to do at the starting of jitsi app is to read in some config file if externallyManagedKey is true or false. How can we do this?

saghul commented 1 month ago

The config is set to a global in window. Do you can read it from wherever you want.

monidp9 commented 1 month ago

immagine Here window.confing.e2ee.externallyManagedKey is undefined.

saghul commented 1 month ago

Is it set to something in your config.js ?

monidp9 commented 1 month ago

In config.js

immagine

EDIT: We are not in deploy mode. @saghul

saghul commented 1 month ago

I'm not sure what you mean by "deploy mode", but config.js is ONLY read when you deploy your code onto a server. It's not added to the JS bundle, it's included in the index.html by a server side include.

monidp9 commented 1 month ago

@saghul we are following this guide https://community.jitsi.org/t/how-to-how-to-build-jitsi-meet-from-source-a-developers-guide/75422 When we modify the ngix file as reported, we get 403 Forbidden. Any advice?

saghul commented 1 month ago

DId you make sure to use correct root folder for your changes? Alternatively you can keep the config as is, and just override the modified files in /usr/share/jitsi-meet