{"id":34657,"date":"2016-05-23T15:23:45","date_gmt":"2016-05-23T09:53:45","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=34657"},"modified":"2016-05-25T11:36:15","modified_gmt":"2016-05-25T06:06:15","slug":"authorizing-creationentrance-of-a-conference-in-jitsi","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/authorizing-creationentrance-of-a-conference-in-jitsi\/","title":{"rendered":"Authorizing Creation\/Entrance of a Conference in Jitsi"},"content":{"rendered":"<p class=\"western\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">In this blog, we are going to discuss how we can provide authorization for creating or entering a room in Jitsi. While using Jitsi at organisation level there must be some security so that conferences are created or entered after an authorization. <\/span><\/span><\/p>\n<p class=\"western\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><b>About Jitsi :<\/b><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">Jitsi is a free &amp; open source video conferencing application which allow user to create there room and other user can enter the room with hitting same url with same room name.<\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">Jitsi consist of different module like <\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">Lib-jitsi-meet: The Module works on mainly UI part of Jitsi.<\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">Jicofo(<\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\"><b>Ji<\/b><\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">tsi <\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\"><b>Co<\/b><\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">nference <\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\"><b>Fo<\/b><\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">cus) : The Module Works on Mainly Room &amp; Member Management in Jitsi <\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">JVB(<strong>J<\/strong>itsi-<strong>V<\/strong>ideo<strong>b<\/strong>ridge: The Module Works on relaying the video in conferences.<\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">Jicoco(<\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\"><b>Ji<\/b><\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">tsi <\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\"><b>Co<\/b><\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">mmon <\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\"><b>Co<\/b><\/span><\/span><\/span><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">mponent): The Module works on common component of Jitsi.<\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"color: #252525;\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><span style=\"font-size: medium;\">All Module Work together to make Jitsi working .<\/span><\/span><\/span><\/p>\n<p class=\"western\"><span style=\"font-family: 'Liberation Serif', 'Times New Roman', serif;\"><b>Why authorization is required in Jitsi: <\/b><\/span><\/p>\n<p class=\"western\">We know that Jitsi is video conferencing application so whenever you create a room in Jitsi other user can only join this room if he\/she has the url of that room. but it may also possible that un-authorized user can hit the same url and join in the same room, to overcome this kind of behaviour we are adding a key in the url to check whether the user accessing the url is an authorized user or user has an access to that room or not ,if user is not a authorized user then they will not be allowed to enter the room till they access url with an authorized key.<\/p>\n<p class=\"western\"><b>So lets start working on how to add Authorization while entering a room in Jitsi <\/b><\/p>\n<p class=\"western\">Will be achieving this by prefixing a key to the room name &amp; separating it with &#8220;=&#8221; .<\/p>\n<p class=\"western\">For Example<\/p>\n<p class=\"western\">Url Before Key: http:\/\/Domain\/roomname<\/p>\n<p class=\"western\">Url After Key: http:\/\/Domain\/key=roomname<\/p>\n<div id=\"attachment_34658\" style=\"width: 806px\" class=\"wp-caption alignnone\"><img aria-describedby=\"caption-attachment-34658\" decoding=\"async\" loading=\"lazy\" class=\"wp-image-34658 size-full\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/05\/Jitsi-home.png\" alt=\"Jitsi-homePage\" width=\"796\" height=\"214\" \/><p id=\"caption-attachment-34658\" class=\"wp-caption-text\">Where admin123 is key &amp; TTND is roomName.<\/p><\/div>\n<p class=\"western\"><b>Step 1 :<\/b>Let&#8217;s find out where the call is going in Jitsi when you enter room name in Jitsi homepage &amp; click &#8220;Go&#8221; Button with help of which you can create\/enter a room.<\/p>\n<p class=\"western\">So when you hit &#8220;Go&#8221; Button the Call is internally going to one of the module of Jitsi that is &#8220;lib-jitsi-meet&#8221; and create a XMPP Packet(org.xmpp.packet.IQ) and send it to JICOFO.<\/p>\n<p class=\"western\">In &#8220;lib-jitsi-meet&#8221; we have a JS File named as moderator.js at \/lib-jitsi-meet\/modules\/xmpp\/moderator.js which has a function called moderator which has one parameter named roomName,so this roomName is what we have given in text area on home page.<\/p>\n<p class=\"western\">Now In this roomName, Key is attached to it so we can split on &#8220;=&#8221; and get the key from the room name. Once we get the key in moderator function we can add that key in property map which will be send to JICOFO in the form of XMPP Packet(org.xmpp.packet.IQ) &amp; if Client Key is Not Passed it will prompt an alert saying <span style=\"color: #ff3333;\">\u201cPlease enter the Client Key &amp; Room Name in the format &lt;clientKey&gt;=&lt;roomName&gt;\u201d<\/span><\/p>\n<div style=\"width: 800px; height: 250px; overflow: auto;\">\n<p>[sourcecode language=&#8221;java&#8221;] function Moderator(roomName, xmpp, emitter, settings, options) {<\/p>\n<p>    if (roomName.split(&quot;=&quot;).length == 2) {<br \/>\n        var clientKey = roomName.split(&quot;=&quot;)[0];<br \/>\n        this.roomName = roomName;<br \/>\n        this.clientKey = clientKey;<br \/>\n        this.xmppService = xmpp;<br \/>\n        this.getNextTimeout = createExpBackoffTimer(1000);<br \/>\n        this.getNextErrorTimeout = createExpBackoffTimer(1000);<br \/>\n        \/\/ External authentication stuff<br \/>\n        this.externalAuthEnabled = false;<br \/>\n        this.settings = settings;<br \/>\n        this.options = options;<\/p>\n<p>        \/\/ Sip gateway can be enabled by configuring Jigasi host in config.js or<br \/>\n        \/\/ it will be enabled automatically if focus detects the component through<br \/>\n        \/\/ service discovery.<br \/>\n        this.sipGatewayEnabled = this.options.connection.hosts &amp; amp; &amp; amp;<br \/>\n        this.options.connection.hosts.call_control !== undefined;<\/p>\n<p>        this.eventEmitter = emitter;<\/p>\n<p>        this.connection = this.xmppService.connection;<br \/>\n        this.focusUserJid;<br \/>\n        \/\/FIXME:<br \/>\n        \/\/ Message listener that talks to POPUP window<br \/>\n        function listener(event) {<br \/>\n            if (event.data &amp; amp; &amp; amp; event.data.sessionId) {<br \/>\n                if (event.origin !== window.location.origin) {<br \/>\n                    logger.warn(&quot;Ignoring sessionId from different origin: &quot; +<br \/>\n                        event.origin);<br \/>\n                    return;<br \/>\n                }<br \/>\n                settings.setSessionId(event.data.sessionId);<br \/>\n                \/\/ After popup is closed we will authenticate<br \/>\n            }<br \/>\n        }<br \/>\n        \/\/ Register<br \/>\n        if (window.addEventListener) {<br \/>\n            window.addEventListener(&quot;message&quot;, listener, false);<br \/>\n        } else {<br \/>\n            window.attachEvent(&quot;onmessage&quot;, listener);<br \/>\n        }<br \/>\n    } else {<br \/>\n        alert(&#8216;Please enter the Client Key &amp;amp; Room Name in the format &lt;clientKey&gt;=&lt;roomName&gt;&#8217;);<br \/>\n    }<br \/>\n}<br \/>\n[\/sourcecode]<\/p>\n<\/div>\n<p class=\"western\"><b>Step 2: <\/b>Lets add a Key in property Map,<\/p>\n<p class=\"western\">To add a key in Property Map we have to do the changes in createConferenceIq function in moderator.js , In the propertyMap we are adding a property named clientKey.<\/p>\n<div style=\"width: 800px; height: 250px; overflow: auto;\">\n<p>[sourcecode language=&#8221;java&#8221;]<br \/>\nModerator.prototype.createConferenceIq = function () {<\/p>\n<p>\/\/ Generate create conference IQ<\/p>\n<p>var elem = $iq({to: this.getFocusComponent(), type: &#8216;set&#8217;});<\/p>\n<p>\/\/ Session Id used for authentication<\/p>\n<p>var sessionId = this.settings.getSessionId();<\/p>\n<p>var machineUID = this.settings.getUserId();<\/p>\n<p>logger.info(<\/p>\n<p>&quot;Session ID: &quot; + sessionId + &quot; machine UID: &quot; + machineUID);<\/p>\n<p>elem.c(&#8216;conference&#8217;, {<\/p>\n<p>xmlns: &#8216;http:\/\/jitsi.org\/protocol\/focus&#8217;,<\/p>\n<p>room: this.roomName,<\/p>\n<p>&#8216;machine-uid&#8217;: machineUID<\/p>\n<p>});<\/p>\n<p>if (sessionId) {<\/p>\n<p>elem.attrs({ &#8216;session-id&#8217;: sessionId});<\/p>\n<p>}<\/p>\n<p>if (this.options.connection.hosts !== undefined<\/p>\n<p>&amp;&amp; this.options.connection.hosts.bridge !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;bridge&#8217;,<\/p>\n<p>value: this.options.connection.hosts.bridge<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>if (this.options.connection.enforcedBridge !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;enforcedBridge&#8217;,<\/p>\n<p>value: this.options.connection.enforcedBridge<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>\/\/ Tell the focus we have Jigasi configured<\/p>\n<p>if (this.options.connection.hosts !== undefined &amp;&amp;<\/p>\n<p>this.options.connection.hosts.call_control !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;call_control&#8217;,<\/p>\n<p>value: this.options.connection.hosts.call_control<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>if (this.options.conference.channelLastN !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;channelLastN&#8217;,<\/p>\n<p>value: this.options.conference.channelLastN<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>if (this.options.conference.adaptiveLastN !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;adaptiveLastN&#8217;,<\/p>\n<p>value: this.options.conference.adaptiveLastN<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>if (this.options.conference.disableAdaptiveSimulcast !== undefined ||<\/p>\n<p>this.options.conference.disableSimulcast) {<\/p>\n<p>\/\/ disableSimulcast implies disableAdaptiveSimulcast.<\/p>\n<p>var value = this.options.conference.disableSimulcast ? true :<\/p>\n<p>this.options.conference.disableAdaptiveSimulcast;<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;disableAdaptiveSimulcast&#8217;,<\/p>\n<p>value: value<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>\/\/ TODO: re-enable once rtx is stable<\/p>\n<p>\/\/if (this.options.conference.disableRtx !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;disableRtx&#8217;,<\/p>\n<p>\/\/value: this.options.conference.disableRtx<\/p>\n<p>value: true<\/p>\n<p>}).up();<\/p>\n<p>\/\/}<\/p>\n<p>if (this.options.conference.openSctp !== undefined) {<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;openSctp&#8217;,<\/p>\n<p>value: this.options.conference.openSctp<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>if (this.options.conference.startAudioMuted !== undefined)<\/p>\n<p>{<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;startAudioMuted&#8217;,<\/p>\n<p>value: this.options.conference.startAudioMuted<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>if (this.options.conference.startVideoMuted !== undefined)<\/p>\n<p>{<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;startVideoMuted&#8217;,<\/p>\n<p>value: this.options.conference.startVideoMuted<\/p>\n<p>}).up();<\/p>\n<p>}<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;simulcastMode&#8217;,<\/p>\n<p>value: &#8216;rewriting&#8217;<\/p>\n<p>}).up();<\/p>\n<p>\/\/elem.up();<\/p>\n<p>elem.c(<\/p>\n<p>&#8216;property&#8217;, {<\/p>\n<p>name: &#8216;clientKey&#8217;,<\/p>\n<p>value: this.clientKey<\/p>\n<p>}).up();<\/p>\n<p>elem.up();<\/p>\n<p>return elem;<\/p>\n<p>};<\/p>\n<p>[\/sourcecode]<\/p>\n<\/div>\n<p class=\"western\">After &#8220;lib-jitsi-meet&#8221; call goes to &#8220;JICOFO&#8221; module, In Jicofo we have a Function handleIQSet() in FocusComponent class where the call comes to Jicofo Which Handles an XMPP Packet(org.xmpp.packet.IQ) which represents a request &amp; returns an XMPP Packet(org.xmpp.packet.IQ) which represents the response to the specified request.<\/p>\n<p class=\"western\"><b>Step 3:\u00a0<\/b>Let&#8217;s create a property file on the server which will be having Client Key &amp; Client Name in this format ClientKey=ClientName .<\/p>\n<p class=\"western\">I am creating the file at this location <span style=\"color: #000000;\"><span style=\"font-size: medium;\">\/root\/Jitsi\/Keys\/ClientKeys.properties<\/span><\/span><\/p>\n<div style=\"width: 800px; height: 150px; overflow: auto;\">\n<p>[sourcecode language=&#8221;java&#8221;]<br \/>\n# Client Key &amp; Client Names<\/p>\n<p># Example<\/p>\n<p># client name = client key<\/p>\n<p>admin123=admin<br \/>\n[\/sourcecode]<\/p>\n<\/div>\n<p class=\"western\"><b>Step 4 :\u00a0<\/b>Let&#8217;s retrive the authorization Key from the XMPP Packet(org.xmpp.packet.IQ) which is coming as request in handleIQSet() function of focusComponent class of JICOFO &amp; Restrict the user to create\/enter room if it is not authorized key .<\/p>\n<p class=\"western\">Now in handleIQset() when we get packet as instanceof ConferenceIq then from this ConferenceIq we can fetch the map &amp; clientKey.<\/p>\n<p class=\"western\">String clientKey = conferenceIq.getPropertiesMap().get(&#8220;clientKey&#8221;);<\/p>\n<p class=\"western\">if Client key is empty then error is thrown saying <span style=\"color: #ff3333;\">&#8220;Client Name \/ Client Key is not Supplied. Please Retry&#8221;<\/span>.<\/p>\n<p class=\"western\">if Client key is not empty then will match client key with the keys in property file on the server.<\/p>\n<p class=\"western\">if Client Key matches the Key in Property file then will allow him\/her to create\/join the room.<\/p>\n<p class=\"western\">if Client Key is not matched he will not be allowed to create\/join room and thrown a error saying <span style=\"color: #ff3333;\">&#8220;Client Name \/ Client Key pair mismatch. Please Retry&#8221;<\/span> .<\/p>\n<div style=\"width: 800px; height: 250px; overflow: auto;\">\n<p>[sourcecode language=&#8221;java&#8221;]<br \/>\n@Override<br \/>\n\tpublic IQ handleIQSet(IQ iq) throws Exception {<br \/>\n\t\ttry {<br \/>\n\t\t\torg.jivesoftware.smack.packet.IQ smackIq = IQUtils.convert(iq);<br \/>\n\t\t\tString client = null;<br \/>\n\t\t\tif (smackIq instanceof ConferenceIq) {<\/p>\n<p>\t\t\t\tConferenceIq conferenceIq = (ConferenceIq) smackIq;<br \/>\n\t\t\t\tString clientKey = conferenceIq.getPropertiesMap().get(&quot;clientKey&quot;);<\/p>\n<p>\t\t\t\tif (clientKey != null &amp;&amp; !clientKey.isEmpty()) {<\/p>\n<p>\t\t\t\t\tProperties prop = new Properties();<br \/>\n\t\t\t\t\tString propFileName =&quot;\/root\/Jitsi\/Keys\/ClientKeys.properties&quot;;<\/p>\n<p>\t\t\t\t\tInputStream inputStream = new FileInputStream(propFileName);<\/p>\n<p>\t\t\t\t\tif (inputStream != null) {<br \/>\n\t\t\t\t\t\tprop.load(inputStream);<br \/>\n\t\t\t\t\t}<\/p>\n<p>\t\t\t\t\tif (prop.isEmpty()) {<br \/>\n\t\t\t\t\t\tthrow new FileNotFoundException(<br \/>\n\t\t\t\t\t\t\t\t&quot;property file &#8216;&quot; + propFileName + &quot;&#8217; does not contain any keys&quot;);<br \/>\n\t\t\t\t\t}<br \/>\n\t\t\t\t\tclient = prop.getProperty(clientKey);<\/p>\n<p>\t\t\t\t\tif (client != null &amp;&amp; !client.isEmpty()) {<\/p>\n<p>\t\t\t\t\t\tClientAttributes clientAttributes = makeClientObject(client);<\/p>\n<p>\t\t\t\t\t\tif(clientAttributes != null){<br \/>\n\t\t\t\t\t\t\tboolean roomExists = focusManager.getConference(conferenceIq.getRoom()) != null;<\/p>\n<p>\t\t\t\t\t\t\tif (!roomExists &amp;&amp; authAuthority != null) {<br \/>\n\t\t\t\t\t\t\t\tMap&lt;String, String&gt; propertyMap = conferenceIq.getPropertiesMap();<br \/>\n\t\t\t\t\t\t\t\tclientAttributes.setMachineUID(conferenceIq.getMachineUID());<br \/>\n\t\t\t\t\t\t\t\tclientAttributes.setClientKey(clientKey);<br \/>\n\t\t\t\t\t\t\t\tclientAttributes.setRoomName(conferenceIq.getRoom());<br \/>\n\t\t\t\t\t\t\t\tString sessionId = clientAuthenticationImpl.authenticateUser(clientAttributes, propertyMap);<\/p>\n<p>\t\t\t\t\t\t\t\tconferenceIq.setSessionId(sessionId);<br \/>\n\t\t\t\t\t\t\t}<br \/>\n\t\t\t\t\t\t}<\/p>\n<p>\t\t\t\t\t} else {<br \/>\n\t\t\t\t\t\tthrow new ClientKeyException(&quot;Client Name \/ Client Key pair mismatch. Please Retry&quot;);<br \/>\n\t\t\t\t\t}<br \/>\n\t\t\t\t} else {<br \/>\n\t\t\t\t\tthrow new ClientKeyException(&quot;Client Name \/ Client Key is not Supplied. Please Retry&quot;);<br \/>\n\t\t\t\t}<\/p>\n<p>\t\t\t\torg.jivesoftware.smack.packet.IQ response = handleConferenceIq((ConferenceIq) smackIq);<\/p>\n<p>\t\t\t\treturn response != null ? IQUtils.convert(response) : null;<\/p>\n<p>\t\t\t} else if (smackIq instanceof ShutdownIQ) {<br \/>\n\t\t\t\tShutdownIQ gracefulShutdownIQ = (ShutdownIQ) smackIq;<\/p>\n<p>\t\t\t\tif (!gracefulShutdownIQ.isGracefulShutdown()) {<br \/>\n\t\t\t\t\treturn IQUtils.convert(org.jivesoftware.smack.packet.IQ.createErrorResponse(smackIq,<br \/>\n\t\t\t\t\t\t\tnew XMPPError(XMPPError.Condition.bad_request)));<br \/>\n\t\t\t\t}<\/p>\n<p>\t\t\t\tString from = gracefulShutdownIQ.getFrom();<br \/>\n\t\t\t\tString bareFrom = org.jivesoftware.smack.util.StringUtils.parseBareAddress(from);<\/p>\n<p>\t\t\t\tif (StringUtils.isNullOrEmpty(shutdownAllowedJid) || !shutdownAllowedJid.equals(bareFrom)) {<br \/>\n\t\t\t\t\t\/\/ Forbidden<br \/>\n\t\t\t\t\tXMPPError forbiddenError = new XMPPError(XMPPError.Condition.forbidden);<\/p>\n<p>\t\t\t\t\tlogger.warn(&quot;Client : &quot; + client + &quot;Rejected shutdown request from: &quot; + from);<\/p>\n<p>\t\t\t\t\treturn IQUtils<br \/>\n\t\t\t\t\t\t\t.convert(org.jivesoftware.smack.packet.IQ.createErrorResponse(smackIq, forbiddenError));<br \/>\n\t\t\t\t}<\/p>\n<p>\t\t\t\tlogger.info(&quot;Client : &quot; + client + &quot;Accepted shutdown request from: &quot; + from);<\/p>\n<p>\t\t\t\tfocusManager.enableGracefulShutdownMode();<\/p>\n<p>\t\t\t\treturn IQUtils.convert(org.jivesoftware.smack.packet.IQ.createResultIQ(smackIq));<br \/>\n\t\t\t} else if (smackIq instanceof LogoutIq) {<br \/>\n\t\t\t\tlogger.info(&quot;Client : &quot; + client + &quot;Logout IQ received: &quot; + iq.toXML());<\/p>\n<p>\t\t\t\tif (authAuthority == null) {<br \/>\n\t\t\t\t\treturn null;<br \/>\n\t\t\t\t}<\/p>\n<p>\t\t\t\torg.jivesoftware.smack.packet.IQ smackResult = authAuthority.processLogoutIq((LogoutIq) smackIq);<\/p>\n<p>\t\t\t\treturn smackResult != null ? IQUtils.convert(smackResult) : null;<br \/>\n\t\t\t} else {<br \/>\n\t\t\t\treturn super.handleIQSet(iq);<br \/>\n\t\t\t}<\/p>\n<p>\t\t} catch (Exception e) {<br \/>\n\t\t\tlogger.error(e, e);<br \/>\n\t\t\tthrow e;<br \/>\n\t\t}<br \/>\n\t}<br \/>\n[\/sourcecode]<\/p>\n<\/div>\n<p class=\"western\">Thank You, Hope you liked it .<\/p>\n<p class=\"western\">Keep Jitsing , Cheers !!!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this blog, we are going to discuss how we can provide authorization for creating or entering a room in Jitsi. While using Jitsi at organisation level there must be some security so that conferences are created or entered after an authorization. About Jitsi : Jitsi is a free &amp; open source video conferencing application [&hellip;]<\/p>\n","protected":false},"author":923,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":42},"categories":[1],"tags":[3358,3357,3369,3368,3370,3371,3359,3367,3366],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/34657"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/923"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=34657"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/34657\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=34657"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=34657"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=34657"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}