diff --git a/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js b/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js
index e13e7c5f2da353bd9835b1067186ad5c617d7c25..041b4ae23b01b0a45a80e917a7381d780e758cf2 100644
--- a/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js
+++ b/bigbluebutton-html5/imports/api/meetings/server/eventHandlers.js
@@ -4,6 +4,7 @@ import handleGetAllMeetings from './handlers/getAllMeetings';
 import handleMeetingEnd from './handlers/meetingEnd';
 import handleMeetingDestruction from './handlers/meetingDestruction';
 import handleMeetingLocksChange from './handlers/meetingLockChange';
+import handleGuestPolicyChanged from './handlers/guestPolicyChanged';
 import handleGuestLobbyMessageChanged from './handlers/guestLobbyMessageChanged';
 import handleUserLockChange from './handlers/userLockChange';
 import handleRecordingStatusChange from './handlers/recordingStatusChange';
@@ -22,6 +23,7 @@ RedisPubSub.on('RecordingStatusChangedEvtMsg', handleRecordingStatusChange);
 RedisPubSub.on('UpdateRecordingTimerEvtMsg', handleRecordingTimerChange);
 RedisPubSub.on('WebcamsOnlyForModeratorChangedEvtMsg', handleChangeWebcamOnlyModerator);
 RedisPubSub.on('GetLockSettingsRespMsg', handleMeetingLocksChange);
+RedisPubSub.on('GuestPolicyChangedEvtMsg', handleGuestPolicyChanged);
 RedisPubSub.on('GuestLobbyMessageChangedEvtMsg', handleGuestLobbyMessageChanged);
 RedisPubSub.on('MeetingTimeRemainingUpdateEvtMsg', handleTimeRemainingUpdate);
 RedisPubSub.on('SelectRandomViewerRespMsg', handleSelectRandomViewer);
diff --git a/bigbluebutton-html5/imports/api/meetings/server/handlers/guestPolicyChanged.js b/bigbluebutton-html5/imports/api/meetings/server/handlers/guestPolicyChanged.js
new file mode 100644
index 0000000000000000000000000000000000000000..b7e42aeb9ef03d5a780311a8476ec28c4e1d27e1
--- /dev/null
+++ b/bigbluebutton-html5/imports/api/meetings/server/handlers/guestPolicyChanged.js
@@ -0,0 +1,12 @@
+import setGuestPolicy from '../modifiers/setGuestPolicy';
+import { check } from 'meteor/check';
+
+export default function handleGuestPolicyChanged({ body }, meetingId) {
+  const { policy } = body;
+
+  check(meetingId, String);
+  check(policy, String);
+
+
+  return setGuestPolicy(meetingId, policy);
+}
diff --git a/bigbluebutton-html5/imports/api/meetings/server/modifiers/setGuestPolicy.js b/bigbluebutton-html5/imports/api/meetings/server/modifiers/setGuestPolicy.js
new file mode 100644
index 0000000000000000000000000000000000000000..3c1b3a247b964011be1292cb07ca6134a379903a
--- /dev/null
+++ b/bigbluebutton-html5/imports/api/meetings/server/modifiers/setGuestPolicy.js
@@ -0,0 +1,34 @@
+import Meetings from '/imports/api/meetings';
+import Logger from '/imports/startup/server/logger';
+import { check } from 'meteor/check';
+
+export default function setGuestPolicy(meetingId, guestPolicy) {
+  check(meetingId, String);
+  check(guestPolicy, String);
+
+  const selector = {
+    meetingId,
+  };
+
+  const modifier = {
+    $set: {
+      usersProp: {
+        guestPolicy,
+      }
+    },
+  };
+
+  const cb = (err, numChanged) => {
+    if (err) {
+      return Logger.error(`Changing meeting guest policy: ${err}`);
+    }
+
+    if (!numChanged) {
+      return Logger.info(`Meeting's ${meetingId} guest policy=${guestPolicy} wasn't updated`);
+    }
+
+    return Logger.info(`Meeting's ${meetingId} guest policy=${guestPolicy} updated`);
+  };
+
+  return Meetings.update(selector, modifier, cb);
+}
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx
index 0cf23728298e01d8780c27784e30353024bf6fc7..b5a6820b88ded6c68eb7e9a1595288830f8a26e4 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/component.jsx
@@ -11,6 +11,7 @@ import DropdownList from '/imports/ui/components/dropdown/list/component';
 import DropdownListItem from '/imports/ui/components/dropdown/list/item/component';
 import LockViewersContainer from '/imports/ui/components/lock-viewers/container';
 import ConnectionStatusContainer from '/imports/ui/components/connection-status/modal/container';
+import GuestPolicyContainer from '/imports/ui/components/waiting-users/guest-policy/container';
 import BreakoutRoom from '/imports/ui/components/actions-bar/create-breakout-room/container';
 import CaptionsService from '/imports/ui/components/captions/service';
 import ConnectionStatusService from '/imports/ui/components/connection-status/service';
@@ -29,6 +30,7 @@ const propTypes = {
   toggleStatus: PropTypes.func.isRequired,
   mountModal: PropTypes.func.isRequired,
   users: PropTypes.arrayOf(Object).isRequired,
+  guestPolicy: PropTypes.string.isRequired,
   meetingIsBreakout: PropTypes.bool.isRequired,
   hasBreakoutRoom: PropTypes.bool.isRequired,
   isBreakoutEnabled: PropTypes.bool.isRequired,
@@ -80,6 +82,14 @@ const intlMessages = defineMessages({
     id: 'app.userList.userOptions.connectionStatusDesc',
     description: 'Connection status description',
   },
+  guestPolicyLabel: {
+    id: 'app.userList.userOptions.guestPolicyLabel',
+    description: 'Guest policy label',
+  },
+  guestPolicyDesc: {
+    id: 'app.userList.userOptions.guestPolicyDesc',
+    description: 'Guest policy description',
+  },
   muteAllExceptPresenterLabel: {
     id: 'app.userList.userOptions.muteAllExceptPresenterLabel',
     description: 'Mute all except presenter label',
@@ -139,6 +149,7 @@ class UserOptions extends PureComponent {
     this.muteAllId = _.uniqueId('list-item-');
     this.lockId = _.uniqueId('list-item-');
     this.connectionStatusId = _.uniqueId('list-item-');
+    this.guestPolicyId = _.uniqueId('list-item-');
     this.createBreakoutId = _.uniqueId('list-item-');
     this.saveUsersNameId = _.uniqueId('list-item-');
     this.captionsId = _.uniqueId('list-item-');
@@ -296,6 +307,15 @@ class UserOptions extends PureComponent {
           onClick={() => mountModal(<ConnectionStatusContainer />)}
         />) : null
       ),
+      (isMeteorConnected ? (
+        <DropdownListItem
+          key={this.guestPolicyId}
+          icon="user"
+          label={intl.formatMessage(intlMessages.guestPolicyLabel)}
+          description={intl.formatMessage(intlMessages.guestPolicyDesc)}
+          onClick={() => mountModal(<GuestPolicyContainer />)}
+        />) : null
+      ),
       (isMeteorConnected ? <DropdownListSeparator key={_.uniqueId('list-separator-')} /> : null),
       (canCreateBreakout && isMeteorConnected ? (
         <DropdownListItem
diff --git a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx
index f24b76e177f05099e697b713e0f6a94bad863d2c..77ebcb3d053a1e6482f76ef631775c10cad8f2a2 100755
--- a/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/user-list/user-list-content/user-participants/user-options/container.jsx
@@ -4,6 +4,7 @@ import Auth from '/imports/ui/services/auth';
 import Meetings from '/imports/api/meetings';
 import ActionsBarService from '/imports/ui/components/actions-bar/service';
 import UserListService from '/imports/ui/components/user-list/service';
+import WaitingUsersService from '/imports/ui/components/waiting-users/service';
 import logger from '/imports/startup/client/logger';
 import { defineMessages, injectIntl } from 'react-intl';
 import { notify } from '/imports/ui/services/notification';
@@ -84,6 +85,7 @@ const UserOptionsContainer = withTracker((props) => {
     isBreakoutEnabled: ActionsBarService.isBreakoutEnabled(),
     isBreakoutRecordable: ActionsBarService.isBreakoutRecordable(),
     users: ActionsBarService.users(),
+    guestPolicy: WaitingUsersService.getGuestPolicy(),
     isMeteorConnected: Meteor.status().connected,
     meetingName: getMeetingName(),
   };
diff --git a/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/component.jsx b/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/component.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..f98183d5b4b6d23144cbfc93bc9d9eb7c4d3966d
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/component.jsx
@@ -0,0 +1,115 @@
+import React, { PureComponent } from 'react';
+import { defineMessages, injectIntl } from 'react-intl';
+import PropTypes from 'prop-types';
+import Modal from '/imports/ui/components/modal/simple/component';
+import Button from '/imports/ui/components/button/component';
+import { styles } from './styles';
+
+const ASK_MODERATOR = 'ASK_MODERATOR';
+const ALWAYS_ACCEPT = 'ALWAYS_ACCEPT';
+const ALWAYS_DENY = 'ALWAYS_DENY';
+
+const intlMessages = defineMessages({
+  ariaModalTitle: {
+    id: 'app.guest-policy.ariaTitle',
+    description: 'Guest policy aria title',
+  },
+  guestPolicyTitle: {
+    id: 'app.guest-policy.title',
+    description: 'Guest policy title',
+  },
+  guestPolicyDescription: {
+    id: 'app.guest-policy.description',
+    description: 'Guest policy description',
+  },
+  askModerator: {
+    id: 'app.guest-policy.button.askModerator',
+    description: 'Ask moderator button label',
+  },
+  alwaysAccept: {
+    id: 'app.guest-policy.button.alwaysAccept',
+    description: 'Always accept button label',
+  },
+  alwaysDeny: {
+    id: 'app.guest-policy.button.alwaysDeny',
+    description: 'Always deny button label',
+  },
+});
+
+const propTypes = {
+  closeModal: PropTypes.func.isRequired,
+  intl: PropTypes.shape({
+    formatMessage: PropTypes.func.isRequired,
+  }).isRequired,
+  guestPolicy: PropTypes.string.isRequired,
+  changeGuestPolicy: PropTypes.func.isRequired,
+};
+
+class GuestPolicyComponent extends PureComponent {
+  render() {
+    const {
+      closeModal,
+      intl,
+      guestPolicy,
+      changeGuestPolicy,
+    } = this.props;
+
+    return (
+      <Modal
+        overlayClassName={styles.overlay}
+        className={styles.modal}
+        onRequestClose={closeModal}
+        hideBorder
+        contentLabel={intl.formatMessage(intlMessages.ariaModalTitle)}
+      >
+        <div className={styles.container}>
+          <div className={styles.header}>
+            <h2 className={styles.title}>
+              {intl.formatMessage(intlMessages.guestPolicyTitle)}
+            </h2>
+          </div>
+          <div className={styles.description}>
+            {intl.formatMessage(intlMessages.guestPolicyDescription)}
+          </div>
+
+          <div className={styles.content}>
+            <Button
+              color="primary"
+              className={styles.button}
+              disabled={guestPolicy === ASK_MODERATOR}
+              label={intl.formatMessage(intlMessages.askModerator)}
+              onClick={() => {
+                changeGuestPolicy(ASK_MODERATOR);
+                closeModal();
+              }}
+            />
+            <Button
+              color="primary"
+              className={styles.button}
+              disabled={guestPolicy === ALWAYS_ACCEPT}
+              label={intl.formatMessage(intlMessages.alwaysAccept)}
+              onClick={() => {
+                changeGuestPolicy(ALWAYS_ACCEPT);
+                closeModal();
+              }}
+            />
+            <Button
+              color="primary"
+              className={styles.button}
+              disabled={guestPolicy === ALWAYS_DENY}
+              label={intl.formatMessage(intlMessages.alwaysDeny)}
+              onClick={() => {
+                changeGuestPolicy(ALWAYS_DENY);
+                closeModal();
+              }}
+            />
+          </div>
+        </div>
+      </Modal>
+    );
+  }
+}
+
+GuestPolicyComponent.propTypes = propTypes;
+
+export default injectIntl(GuestPolicyComponent);
diff --git a/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/container.jsx b/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/container.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..faf4466ca818f73e1dd2bdc6e75930b5721bffb8
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/container.jsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { withTracker } from 'meteor/react-meteor-data';
+import { withModalMounter } from '/imports/ui/components/modal/service';
+import GuestPolicyComponent from './component';
+import Service from '../service';
+
+const guestPolicyContainer = props => <GuestPolicyComponent {...props} />;
+
+export default withModalMounter(withTracker(({ mountModal }) => ({
+  closeModal: () => mountModal(null),
+  guestPolicy: Service.getGuestPolicy(),
+  changeGuestPolicy: Service.changeGuestPolicy,
+}))(guestPolicyContainer));
diff --git a/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/styles.scss b/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/styles.scss
new file mode 100644
index 0000000000000000000000000000000000000000..f38425fe1c105c1d2c5c173a24c96bdbd06b5551
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/waiting-users/guest-policy/styles.scss
@@ -0,0 +1,68 @@
+@import '/imports/ui/stylesheets/mixins/focus';
+@import '/imports/ui/stylesheets/variables/_all';
+@import "/imports/ui/components/modal/simple/styles";
+
+:root {
+  --modal-margin: 3rem;
+  --title-position-left: 2.2rem;
+  --closeBtn-position-left: 2.5rem;
+}
+
+.title {
+  left: var(--title-position-left);
+  right: auto;
+  color: var(--color-gray-dark);
+  font-weight: bold;
+  font-size: var(--font-size-large);
+  text-align: center;
+
+  [dir="rtl"] & {
+    left: auto;
+    right: var(--title-position-left);
+  }
+}
+
+.container {
+  margin: 0 var(--modal-margin) var(--lg-padding-x);
+}
+
+.modal {
+  @extend .modal;
+  padding: var(--jumbo-padding-y);
+}
+
+.overlay {
+  @extend .overlay;
+}
+
+.description {
+  text-align: center;
+  color: var(--color-gray);
+  margin-bottom: var(--jumbo-padding-y)
+}
+
+.label {
+  color: var(--color-gray-label);
+  font-size: var(--font-size-small);
+  margin-bottom: var(--lg-padding-y);
+}
+
+.header {
+  margin: 0;
+  padding: 0;
+  border: none;
+  line-height: var(--title-position-left);
+  margin-bottom: var(--lg-padding-y);
+}
+
+.content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+
+.button {
+  width: 200px;
+  box-sizing: border-box;
+  margin: 5px;
+}
diff --git a/bigbluebutton-html5/imports/ui/components/waiting-users/service.js b/bigbluebutton-html5/imports/ui/components/waiting-users/service.js
index 62d4165000c1d6912149c9a3f8f7310c14d79722..190d2fbf15dee94a59702e665544f48ebf0be731 100644
--- a/bigbluebutton-html5/imports/ui/components/waiting-users/service.js
+++ b/bigbluebutton-html5/imports/ui/components/waiting-users/service.js
@@ -6,6 +6,15 @@ const guestUsersCall = (guestsArray, status) => makeCall('allowPendingUsers', gu
 
 const changeGuestPolicy = policyRule => makeCall('changeGuestPolicy', policyRule);
 
+const getGuestPolicy = () => {
+  const meeting = Meetings.findOne(
+    { meetingId: Auth.meetingID },
+    { fields: { 'usersProp.guestPolicy': 1 } },
+  );
+
+  return meeting.usersProp.guestPolicy;
+};
+
 const isGuestLobbyMessageEnabled = Meteor.settings.public.app.enableGuestLobbyMessage;
 
 const getGuestLobbyMessage = () => {
@@ -24,6 +33,7 @@ const setGuestLobbyMessage = (message) => makeCall('setGuestLobbyMessage', messa
 export default {
   guestUsersCall,
   changeGuestPolicy,
+  getGuestPolicy,
   isGuestLobbyMessageEnabled,
   getGuestLobbyMessage,
   setGuestLobbyMessage,
diff --git a/bigbluebutton-html5/public/locales/en.json b/bigbluebutton-html5/public/locales/en.json
index 421fd097c7c4044f165e91a616dcb5f4d3490ac7..edac1b464d33e7ec5a36c477ab92a9564f1c7053 100755
--- a/bigbluebutton-html5/public/locales/en.json
+++ b/bigbluebutton-html5/public/locales/en.json
@@ -100,6 +100,8 @@
     "app.userList.userOptions.unmuteAllDesc": "Unmutes the meeting",
     "app.userList.userOptions.lockViewersLabel": "Lock viewers",
     "app.userList.userOptions.lockViewersDesc": "Lock certain functionalities for attendees of the meeting",
+    "app.userList.userOptions.guestPolicyLabel": "Guest policy",
+    "app.userList.userOptions.guestPolicyDesc": "Change meeting guest policy setting",
     "app.userList.userOptions.connectionStatusLabel": "Connection status",
     "app.userList.userOptions.connectionStatusDesc": "View users' connection status",
     "app.userList.userOptions.disableCam": "Viewers' webcams are disabled",
@@ -599,6 +601,12 @@
     "app.lock-viewers.button.cancel": "Cancel",
     "app.lock-viewers.locked": "Locked",
     "app.lock-viewers.unlocked": "Unlocked",
+    "app.guest-policy.ariaTitle": "Guest policy settings modal",
+    "app.guest-policy.title": "Guest policy",
+    "app.guest-policy.description": "Change meeting guest policy setting",
+    "app.guest-policy.button.askModerator": "Ask moderator",
+    "app.guest-policy.button.alwaysAccept": "Always accept",
+    "app.guest-policy.button.alwaysDeny": "Always deny",
     "app.connection-status.ariaTitle": "Connection status modal",
     "app.connection-status.title": "Connection status",
     "app.connection-status.description": "View users' connection status",