diff --git a/prosody-plugins/mod_auth_token.lua b/prosody-plugins/mod_auth_token.lua index bf2df1920..a8a899dac 100644 --- a/prosody-plugins/mod_auth_token.lua +++ b/prosody-plugins/mod_auth_token.lua @@ -27,10 +27,9 @@ local provider = {}; local appId = module:get_option_string("app_id"); local appSecret = module:get_option_string("app_secret"); -local tokenLifetime = module:get_option_number("token_lifetime"); function provider.test_password(username, password) - local result, msg = token_util.verify_password(password, appId, appSecret, tokenLifetime); + local result, msg = token_util.verify_password(password, appId, appSecret, nil); if result == true then return true; else diff --git a/prosody-plugins/mod_token_verification.lua b/prosody-plugins/mod_token_verification.lua index 08e1e53ec..79933040f 100644 --- a/prosody-plugins/mod_token_verification.lua +++ b/prosody-plugins/mod_token_verification.lua @@ -22,25 +22,34 @@ end local appId = parentCtx:get_option_string("app_id"); local appSecret = parentCtx:get_option_string("app_secret"); -local tokenLifetime = parentCtx:get_option_string("token_lifetime"); -log("debug", "%s - starting MUC token verifier app_id: %s app_secret: %s token-lifetime: %s", - tostring(host), tostring(appId), tostring(appSecret), tostring(tokenLifetime)); +log("debug", "%s - starting MUC token verifier app_id: %s app_secret: %s", + tostring(host), tostring(appId), tostring(appSecret)); local function handle_pre_create(event) + local origin, stanza = event.origin, event.stanza; local token = stanza:get_child("token", "http://jitsi.org/jitmeet/auth-token"); + -- token not required for admin users local user_jid = stanza.attr.from; if is_admin(user_jid) then log("debug", "Token not required from admin user: %s", user_jid); return nil; end - log("debug", "Will verify token for user: %s ", user_jid); + + local room = string.match(stanza.attr.to, "^(%w+)@"); + log("debug", "Will verify token for user: %s, room: %s ", user_jid, room); + if room == nil then + log("error", "Unable to get name of the MUC room ? to: %s", stanza.attr.to); + return nil; + end + if token ~= nil then token = token[1]; end - local result, msg = token_util.verify_password(token, appId, appSecret, tokenLifetime); + + local result, msg = token_util.verify_password(token, appId, appSecret, room); if result ~= true then log("debug", "Token verification failed: %s", msg); origin.send(st.error_reply(stanza, "cancel", "not-allowed", msg)); diff --git a/prosody-plugins/token/util.lib.lua b/prosody-plugins/token/util.lib.lua index 64747e03a..6781f07b9 100644 --- a/prosody-plugins/token/util.lib.lua +++ b/prosody-plugins/token/util.lib.lua @@ -1,76 +1,38 @@ -- Token authentication -- Copyright (C) 2015 Atlassian -local hashes = require "util.hashes"; +local jwt = require "luajwt"; local _M = {}; -local function calc_hash(password, appId, appSecret) - local hash, room, ts = string.match(password, "(%w+)_(%w+)_(%d+)"); - if hash ~= nil and room ~= nil and ts ~= nil then - log("debug", "Hash: '%s' room: '%s', ts: '%s'", hash, room, ts); - local toHash = room .. ts .. appId .. appSecret; - log("debug", "to be hashed: '%s'", toHash); - local hash = hashes.sha256(toHash, true); - log("debug", "hash: '%s'", hash); - return hash; - else - log("error", "Invalid password format: '%s'", password); - return nil; - end -end +local function verify_password_impl(password, appId, appSecret, roomName) -local function extract_hash(password) - local hash, room, ts = string.match(password, "(%w+)_(%w+)_(%d+)"); - return hash; -end - -local function extract_ts(password) - local hash, room, ts = string.match(password, "(%w+)_(%w+)_(%d+)"); - return ts; -end - -local function get_utc_timestamp() - return os.time(os.date("!*t")) * 1000; -end - -local function verify_timestamp(ts, tokenLifetime) - return get_utc_timestamp() - ts <= tokenLifetime; -end - -local function verify_password_impl(password, appId, appSecret, tokenLifetime) - - if password == nil then - return nil, "password is missing"; - end - - if tokenLifetime == nil then - tokenLifetime = 24 * 60 * 60 * 1000; + local claims, err = jwt.decode(password, appSecret, true); + if claims == nil then + return nil, err; end - local ts = extract_ts(password); - if ts == nil then - return nil, "timestamp not found in the password"; + local issClaim = claims["iss"]; + if issClaim == nil then + return nil, "Issuer field is missing"; end - local os_ts = get_utc_timestamp(); - log("debug", "System TS: '%s' user TS: %s", tostring(os_ts), tostring(ts)); - local isValid = verify_timestamp(ts, tokenLifetime); - if not isValid then - return nil, "token expired"; + if issClaim ~= appId then + return nil, "Invalid application ID('iss' claim)"; end - local realHash = calc_hash(password, appId, appSecret); - local givenhash = extract_hash(password); - log("debug", "Compare '%s' to '%s'", tostring(realHash), tostring(givenhash)); - if realHash == givenhash then - return true; - else - return nil, "invalid hash"; + local roomClaim = claims["room"]; + if roomClaim == nil then + return nil, "Room field is missing"; end + if roomName ~= nil and roomName ~= roomClaim then + return nil, "Invalid room name('room' claim)"; + end + + return true; end -function _M.verify_password(password, appId, appSecret, tokenLifetime) - return verify_password_impl(password, appId, appSecret, tokenLifetime); +function _M.verify_password(password, appId, appSecret, roomName) + return verify_password_impl(password, appId, appSecret, roomName); end return _M;