您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

mod_token_verification.lua 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. -- Token authentication
  2. -- Copyright (C) 2021-present 8x8, Inc.
  3. local log = module._log;
  4. local host = module.host;
  5. local st = require "util.stanza";
  6. local um_is_admin = require "core.usermanager".is_admin;
  7. local jid_split = require 'util.jid'.split;
  8. local jid_bare = require 'util.jid'.bare;
  9. local DEBUG = false;
  10. local measure_success = module:measure('success', 'counter');
  11. local measure_fail = module:measure('fail', 'counter');
  12. local function is_admin(jid)
  13. return um_is_admin(jid, host);
  14. end
  15. local parentHostName = string.gmatch(tostring(host), "%w+.(%w.+)")();
  16. if parentHostName == nil then
  17. module:log("error", "Failed to start - unable to get parent hostname");
  18. return;
  19. end
  20. local parentCtx = module:context(parentHostName);
  21. if parentCtx == nil then
  22. module:log("error",
  23. "Failed to start - unable to get parent context for host: %s",
  24. tostring(parentHostName));
  25. return;
  26. end
  27. local token_util = module:require "token/util".new(parentCtx);
  28. -- no token configuration
  29. if token_util == nil then
  30. return;
  31. end
  32. module:log("debug",
  33. "%s - starting MUC token verifier app_id: %s app_secret: %s allow empty: %s",
  34. tostring(host), tostring(token_util.appId), tostring(token_util.appSecret),
  35. tostring(token_util.allowEmptyToken));
  36. -- option to disable room modification (sending muc config form) for guest that do not provide token
  37. local require_token_for_moderation;
  38. -- option to allow domains to skip token verification
  39. local allowlist;
  40. local function load_config()
  41. require_token_for_moderation = module:get_option_boolean("token_verification_require_token_for_moderation");
  42. allowlist = module:get_option_set('token_verification_allowlist', {});
  43. end
  44. load_config();
  45. -- verify user and whether he is allowed to join a room based on the token information
  46. local function verify_user(session, stanza)
  47. if DEBUG then
  48. module:log("debug", "Session token: %s, session room: %s",
  49. tostring(session.auth_token), tostring(session.jitsi_meet_room));
  50. end
  51. -- token not required for admin users
  52. local user_jid = stanza.attr.from;
  53. if is_admin(user_jid) then
  54. if DEBUG then module:log("debug", "Token not required from admin user: %s", user_jid); end
  55. return true;
  56. end
  57. -- token not required for users matching allow list
  58. local user_bare_jid = jid_bare(user_jid);
  59. local _, user_domain = jid_split(user_jid);
  60. -- allowlist for participants
  61. if allowlist:contains(user_domain) or allowlist:contains(user_bare_jid) then
  62. if DEBUG then module:log("debug", "Token not required from user in allow list: %s", user_jid); end
  63. return true;
  64. end
  65. if DEBUG then module:log("debug", "Will verify token for user: %s, room: %s ", user_jid, stanza.attr.to); end
  66. if not token_util:verify_room(session, stanza.attr.to) then
  67. module:log("error", "Token %s not allowed to join: %s",
  68. tostring(session.auth_token), tostring(stanza.attr.to));
  69. session.send(
  70. st.error_reply(
  71. stanza, "cancel", "not-allowed", "Room and token mismatched"));
  72. return false; -- we need to just return non nil
  73. end
  74. if DEBUG then module:log("debug", "allowed: %s to enter/create room: %s", user_jid, stanza.attr.to); end
  75. return true;
  76. end
  77. module:hook("muc-room-pre-create", function(event)
  78. local origin, stanza = event.origin, event.stanza;
  79. if DEBUG then module:log("debug", "pre create: %s %s", tostring(origin), tostring(stanza)); end
  80. if not verify_user(origin, stanza) then
  81. measure_fail(1);
  82. return true; -- Returning any value other than nil will halt processing of the event
  83. end
  84. measure_success(1);
  85. end, 99);
  86. module:hook("muc-occupant-pre-join", function(event)
  87. local origin, room, stanza = event.origin, event.room, event.stanza;
  88. if DEBUG then module:log("debug", "pre join: %s %s", tostring(room), tostring(stanza)); end
  89. if not verify_user(origin, stanza) then
  90. measure_fail(1);
  91. return true; -- Returning any value other than nil will halt processing of the event
  92. end
  93. measure_success(1);
  94. end, 99);
  95. for event_name, method in pairs {
  96. -- Normal room interactions
  97. ["iq-set/bare/http://jabber.org/protocol/muc#owner:query"] = "handle_owner_query_set_to_room" ;
  98. -- Host room
  99. ["iq-set/host/http://jabber.org/protocol/muc#owner:query"] = "handle_owner_query_set_to_room" ;
  100. } do
  101. module:hook(event_name, function (event)
  102. local session, stanza = event.origin, event.stanza;
  103. -- if we do not require token we pass it through(default behaviour)
  104. -- or the request is coming from admin (focus)
  105. if not require_token_for_moderation or is_admin(stanza.attr.from) then
  106. return;
  107. end
  108. -- jitsi_meet_room is set after the token had been verified
  109. if not session.auth_token or not session.jitsi_meet_room then
  110. session.send(
  111. st.error_reply(
  112. stanza, "cancel", "not-allowed", "Room modification disabled for guests"));
  113. return true;
  114. end
  115. end, -1); -- the default prosody hook is on -2
  116. end
  117. module:hook_global('config-reloaded', load_config);