feat(jwt) refactor token authentication plugin to use new luajwtjitsi version
This commit is contained in:
parent
dbc8f21b01
commit
46dd88c91b
|
@ -61,7 +61,7 @@ case "$1" in
|
||||||
sed -i '/^\s*--\s*"token_verification"/ s/--\s*//' $PROSODY_HOST_CONFIG
|
sed -i '/^\s*--\s*"token_verification"/ s/--\s*//' $PROSODY_HOST_CONFIG
|
||||||
|
|
||||||
# Install luajwt
|
# Install luajwt
|
||||||
if ! luarocks install luajwtjitsi 2.0-0; then
|
if ! luarocks install luajwtjitsi 3.0-0; then
|
||||||
echo "Failed to install luajwtjitsi - try installing it manually"
|
echo "Failed to install luajwtjitsi - try installing it manually"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ function Util.new(module)
|
||||||
self.appId = module:get_option_string("app_id");
|
self.appId = module:get_option_string("app_id");
|
||||||
self.appSecret = module:get_option_string("app_secret");
|
self.appSecret = module:get_option_string("app_secret");
|
||||||
self.asapKeyServer = module:get_option_string("asap_key_server");
|
self.asapKeyServer = module:get_option_string("asap_key_server");
|
||||||
|
self.signatureAlgorithm = module:get_option_string("signature_algorithm");
|
||||||
self.allowEmptyToken = module:get_option_boolean("allow_empty_token");
|
self.allowEmptyToken = module:get_option_boolean("allow_empty_token");
|
||||||
|
|
||||||
self.cache = require"util.cache".new(cacheSize);
|
self.cache = require"util.cache".new(cacheSize);
|
||||||
|
@ -85,6 +86,15 @@ function Util.new(module)
|
||||||
return nil;
|
return nil;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set defaults for signature algorithm
|
||||||
|
if self.signatureAlgorithm == nil then
|
||||||
|
if self.asapKeyServer ~= nil then
|
||||||
|
self.signatureAlgorithm = "RS256"
|
||||||
|
elseif self.appSecret ~= nil then
|
||||||
|
self.signatureAlgorithm = "HS256"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--array of accepted issuers: by default only includes our appId
|
--array of accepted issuers: by default only includes our appId
|
||||||
self.acceptedIssuers = module:get_option_array('asap_accepted_issuers',{self.appId})
|
self.acceptedIssuers = module:get_option_array('asap_accepted_issuers',{self.appId})
|
||||||
|
|
||||||
|
@ -143,94 +153,6 @@ function Util:get_public_key(keyId)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Verifies issuer part of token
|
|
||||||
-- @param 'issClaim' claim from the token to verify
|
|
||||||
-- @param 'acceptedIssuers' list of issuers to check
|
|
||||||
-- @return nil and error string or true for accepted claim
|
|
||||||
function Util:verify_issuer(issClaim, acceptedIssuers)
|
|
||||||
if not acceptedIssuers then
|
|
||||||
acceptedIssuers = self.acceptedIssuers
|
|
||||||
end
|
|
||||||
module:log("debug", "verify_issuer claim: %s against accepted: %s", issClaim, acceptedIssuers);
|
|
||||||
for i, iss in ipairs(acceptedIssuers) do
|
|
||||||
if iss == '*' then
|
|
||||||
-- "*" indicates to accept any issuer in the claims so return success
|
|
||||||
return true;
|
|
||||||
end
|
|
||||||
if issClaim == iss then
|
|
||||||
-- claim matches an accepted issuer so return success
|
|
||||||
return true;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- if issClaim not found in acceptedIssuers, fail claim
|
|
||||||
return nil, "Invalid issuer ('iss' claim)";
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Verifies audience part of token
|
|
||||||
-- @param 'audClaim' claim from the token to verify
|
|
||||||
-- @return nil and error string or true for accepted claim
|
|
||||||
function Util:verify_audience(audClaim)
|
|
||||||
module:log("debug", "verify_audience claim: %s against accepted: %s", audClaim, self.acceptedAudiences);
|
|
||||||
for i, aud in ipairs(self.acceptedAudiences) do
|
|
||||||
if aud == '*' then
|
|
||||||
-- "*" indicates to accept any audience in the claims so return success
|
|
||||||
return true;
|
|
||||||
end
|
|
||||||
if audClaim == aud then
|
|
||||||
-- claim matches an accepted audience so return success
|
|
||||||
return true;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- if audClaim not found in acceptedAudiences, fail claim
|
|
||||||
return nil, "Invalid audience ('aud' claim)";
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Verifies token
|
|
||||||
-- @param token the token to verify
|
|
||||||
-- @param secret the secret to use to verify token
|
|
||||||
-- @param acceptedIssuers the list of accepted issuers to check
|
|
||||||
-- @return nil and error or the extracted claims from the token
|
|
||||||
function Util:verify_token(token, secret, acceptedIssuers)
|
|
||||||
local claims, err = jwt.decode(token, secret, true);
|
|
||||||
if claims == nil then
|
|
||||||
return nil, err;
|
|
||||||
end
|
|
||||||
|
|
||||||
local alg = claims["alg"];
|
|
||||||
if alg ~= nil and (alg == "none" or alg == "") then
|
|
||||||
return nil, "'alg' claim must not be empty";
|
|
||||||
end
|
|
||||||
|
|
||||||
local issClaim = claims["iss"];
|
|
||||||
if issClaim == nil then
|
|
||||||
return nil, "'iss' claim is missing";
|
|
||||||
end
|
|
||||||
--check the issuer against the accepted list
|
|
||||||
local issCheck, issCheckErr = self:verify_issuer(issClaim, acceptedIssuers);
|
|
||||||
if issCheck == nil then
|
|
||||||
return nil, issCheckErr;
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.requireRoomClaim then
|
|
||||||
local roomClaim = claims["room"];
|
|
||||||
if roomClaim == nil then
|
|
||||||
return nil, "'room' claim is missing";
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local audClaim = claims["aud"];
|
|
||||||
if audClaim == nil then
|
|
||||||
return nil, "'aud' claim is missing";
|
|
||||||
end
|
|
||||||
--check the audience against the accepted list
|
|
||||||
local audCheck, audCheckErr = self:verify_audience(audClaim);
|
|
||||||
if audCheck == nil then
|
|
||||||
return nil, audCheckErr;
|
|
||||||
end
|
|
||||||
|
|
||||||
return claims;
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Verifies token and process needed values to be stored in the session.
|
--- Verifies token and process needed values to be stored in the session.
|
||||||
-- Token is obtained from session.auth_token.
|
-- Token is obtained from session.auth_token.
|
||||||
-- Stores in session the following values:
|
-- Stores in session the following values:
|
||||||
|
@ -255,11 +177,13 @@ function Util:process_and_verify_token(session, acceptedIssuers)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local pubKey;
|
local key;
|
||||||
if session.public_key then
|
if session.public_key then
|
||||||
|
-- We're using an public key stored in the session
|
||||||
module:log("debug","Public key was found on the session");
|
module:log("debug","Public key was found on the session");
|
||||||
pubKey = session.public_key;
|
key = session.public_key;
|
||||||
elseif self.asapKeyServer and session.auth_token ~= nil then
|
elseif self.asapKeyServer and session.auth_token ~= nil then
|
||||||
|
-- We're fetching an public key from an ASAP server
|
||||||
local dotFirst = session.auth_token:find("%.");
|
local dotFirst = session.auth_token:find("%.");
|
||||||
if not dotFirst then return false, "not-allowed", "Invalid token" end
|
if not dotFirst then return false, "not-allowed", "Invalid token" end
|
||||||
local header, err = json_safe.decode(basexx.from_url64(session.auth_token:sub(1,dotFirst-1)));
|
local header, err = json_safe.decode(basexx.from_url64(session.auth_token:sub(1,dotFirst-1)));
|
||||||
|
@ -274,23 +198,38 @@ function Util:process_and_verify_token(session, acceptedIssuers)
|
||||||
if alg == nil then
|
if alg == nil then
|
||||||
return false, "not-allowed", "'alg' claim is missing";
|
return false, "not-allowed", "'alg' claim is missing";
|
||||||
end
|
end
|
||||||
if alg.sub(alg,1,2) ~= "RS" then -- do not remove - needed to protect jwt.decode in verify_token
|
if alg.sub(alg,1,2) ~= "RS" then
|
||||||
return false, "not-allowed", "'kid' claim only support with RS family";
|
return false, "not-allowed", "'kid' claim only support with RS family";
|
||||||
end
|
end
|
||||||
pubKey = self:get_public_key(kid);
|
key = self:get_public_key(kid);
|
||||||
if pubKey == nil then
|
if key == nil then
|
||||||
return false, "not-allowed", "could not obtain public key";
|
return false, "not-allowed", "could not obtain public key";
|
||||||
end
|
end
|
||||||
|
elseif self.appSecret ~= nil then
|
||||||
|
-- We're using a symmetric secret
|
||||||
|
key = self.appSecret
|
||||||
|
end
|
||||||
|
|
||||||
|
if key == nil then
|
||||||
|
return false, "not-allowed", "signature verification key is missing";
|
||||||
end
|
end
|
||||||
|
|
||||||
-- now verify the whole token
|
-- now verify the whole token
|
||||||
local claims, msg;
|
local claims, msg = jwt.verify(
|
||||||
if self.asapKeyServer then
|
session.auth_token,
|
||||||
claims, msg = self:verify_token(session.auth_token, pubKey, acceptedIssuers);
|
self.signatureAlgorithm,
|
||||||
else
|
key,
|
||||||
claims, msg = self:verify_token(session.auth_token, self.appSecret, acceptedIssuers);
|
acceptedIssuers,
|
||||||
end
|
self.acceptedAudiences
|
||||||
|
)
|
||||||
if claims ~= nil then
|
if claims ~= nil then
|
||||||
|
if self.requireRoomClaim then
|
||||||
|
local roomClaim = claims["room"];
|
||||||
|
if roomClaim == nil then
|
||||||
|
return false, "'room' claim is missing";
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Binds room name to the session which is later checked on MUC join
|
-- Binds room name to the session which is later checked on MUC join
|
||||||
session.jitsi_meet_room = claims["room"];
|
session.jitsi_meet_room = claims["room"];
|
||||||
-- Binds domain name to the session
|
-- Binds domain name to the session
|
||||||
|
|
Loading…
Reference in New Issue