view plugins/mod_tokenauth.lua @ 11942:b4f77a7bf8ab

mod_http_openmetrics: Serve HTTP from global context Makes GET /metrics work regardless of the value of the Host header. This was not possible before 220468f7a103 which added the ability to have global HTTP modules, which was partly why the per-host part was kept while the module lived among the community modules. Another reason was to provide some semblance of security by obscurity by only loading the module on e.g. a 'localhost' VirtualHost or Component. The new IP limits obsoletes this.
author Kim Alvefur <zash@zash.se>
date Thu, 25 Nov 2021 16:57:01 +0100
parents 5efd6865486c
children 86e1187f6274
line wrap: on
line source

local id = require "util.id";
local jid = require "util.jid";
local base64 = require "util.encodings".base64;

local token_store = module:open_store("auth_tokens", "map");

function create_jid_token(actor_jid, token_jid, token_scope, token_ttl)
	token_jid = jid.prep(token_jid);
	if not actor_jid or token_jid ~= actor_jid and not jid.compare(token_jid, actor_jid) then
		return nil, "not-authorized";
	end

	local token_username, token_host, token_resource = jid.split(token_jid);

	if token_host ~= module.host then
		return nil, "invalid-host";
	end

	local token_info = {
		owner = actor_jid;
		created = os.time();
		expires = token_ttl and (os.time() + token_ttl) or nil;
		jid = token_jid;
		session = {
			username = token_username;
			host = token_host;
			resource = token_resource;

			auth_scope = token_scope;
		};
	};

	local token_id = id.long();
	local token = base64.encode("1;"..jid.join(token_username, token_host)..";"..token_id);
	token_store:set(token_username, token_id, token_info);

	return token, token_info;
end

local function parse_token(encoded_token)
	local token = base64.decode(encoded_token);
	if not token then return nil; end
	local token_jid, token_id = token:match("^1;([^;]+);(.+)$");
	if not token_jid then return nil; end
	local token_user, token_host = jid.split(token_jid);
	return token_id, token_user, token_host;
end

function get_token_info(token)
	local token_id, token_user, token_host = parse_token(token);
	if not token_id then
		return nil, "invalid-token-format";
	end
	if token_host ~= module.host then
		return nil, "invalid-host";
	end

	local token_info, err = token_store:get(token_user, token_id);
	if not token_info then
		if err then
			return nil, "internal-error";
		end
		return nil, "not-authorized";
	end

	if token_info.expires and token_info.expires < os.time() then
		return nil, "not-authorized";
	end

	return token_info
end

function revoke_token(token)
	local token_id, token_user, token_host = parse_token(token);
	if not token_id then
		return nil, "invalid-token-format";
	end
	if token_host ~= module.host then
		return nil, "invalid-host";
	end
	return token_store:set(token_user, token_id, nil);
end