plugins/mod_tokenauth.lua
author Kim Alvefur <zash@zash.se>
Wed, 19 Oct 2022 14:07:48 +0200
changeset 12780 4715301a3504
parent 12776 daa654dbd8de
child 12917 012fa81d1f5d
permissions -rw-r--r--
util.datamapper: Remove leftover debug assert (Only Teal, not included in build)
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     1
local id = require "util.id";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     2
local jid = require "util.jid";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     3
local base64 = require "util.encodings".base64;
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
     4
local usermanager = require "core.usermanager";
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
     5
local generate_identifier = require "util.id".short;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     6
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     7
local token_store = module:open_store("auth_tokens", "map");
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
     9
local function select_role(username, host, role)
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    10
	if role then
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    11
		return prosody.hosts[host].authz.get_role_by_name(role);
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    12
	end
12666
07424992d7fc mod_authz_internal, and more: New iteration of role API
Matthew Wild <mwild1@gmail.com>
parents: 12653
diff changeset
    13
	return usermanager.get_user_role(username, host);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    14
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    15
12776
daa654dbd8de mod_tokenauth: Allow attaching an arbitrary data table to a token
Matthew Wild <mwild1@gmail.com>
parents: 12747
diff changeset
    16
function create_jid_token(actor_jid, token_jid, token_role, token_ttl, token_data)
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    17
	token_jid = jid.prep(token_jid);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    18
	if not actor_jid or token_jid ~= actor_jid and not jid.compare(token_jid, actor_jid) then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    19
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    20
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    21
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    22
	local token_username, token_host, token_resource = jid.split(token_jid);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    23
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    24
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    25
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
	local token_info = {
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    29
		owner = actor_jid;
10679
5efd6865486c mod_tokenauth: Track creation time of tokens
Matthew Wild <mwild1@gmail.com>
parents: 10678
diff changeset
    30
		created = os.time();
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    31
		expires = token_ttl and (os.time() + token_ttl) or nil;
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
		jid = token_jid;
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    34
		resource = token_resource;
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    35
		role = token_role;
12776
daa654dbd8de mod_tokenauth: Allow attaching an arbitrary data table to a token
Matthew Wild <mwild1@gmail.com>
parents: 12747
diff changeset
    36
		data = token_data;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    37
	};
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    38
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    39
	local token_id = id.long();
10678
4459afac4d13 mod_tokenauth: Handle tokens issued to bare hosts (eg components)
Kim Alvefur <zash@zash.se>
parents: 10673
diff changeset
    40
	local token = base64.encode("1;"..jid.join(token_username, token_host)..";"..token_id);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
	token_store:set(token_username, token_id, token_info);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    42
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    43
	return token, token_info;
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    44
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    45
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    46
local function parse_token(encoded_token)
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    47
	local token = base64.decode(encoded_token);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
	if not token then return nil; end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    49
	local token_jid, token_id = token:match("^1;([^;]+);(.+)$");
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    50
	if not token_jid then return nil; end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    51
	local token_user, token_host = jid.split(token_jid);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    52
	return token_id, token_user, token_host;
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    55
local function _get_parsed_token_info(token_id, token_user, token_host)
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    56
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    57
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    58
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    60
	local token_info, err = token_store:get(token_user, token_id);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    61
	if not token_info then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    62
		if err then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    63
			return nil, "internal-error";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    64
		end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    65
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    66
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    67
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
	if token_info.expires and token_info.expires < os.time() then
12747
19113f232423 mod_tokenauth: Remove expired tokens from storage
Matthew Wild <mwild1@gmail.com>
parents: 12746
diff changeset
    69
		token_store:set(token_user, token_id, nil);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    70
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    71
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    72
12746
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
    73
	local account_info = usermanager.get_account_info(token_user, module.host);
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
    74
	local password_updated_at = account_info and account_info.password_updated;
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
    75
	if password_updated_at and password_updated_at > token_info.created then
12747
19113f232423 mod_tokenauth: Remove expired tokens from storage
Matthew Wild <mwild1@gmail.com>
parents: 12746
diff changeset
    76
		token_store:set(token_user, token_id, nil);
12746
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
    77
		return nil, "not-authorized";
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
    78
	end
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
    79
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    80
	return token_info
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    81
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    82
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    83
function get_token_info(token)
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    84
	local token_id, token_user, token_host = parse_token(token);
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    85
	if not token_id then
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    86
		return nil, "invalid-token-format";
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    87
	end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    88
	return _get_parsed_token_info(token_id, token_user, token_host);
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    89
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    90
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    91
function get_token_session(token, resource)
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    92
	local token_id, token_user, token_host = parse_token(token);
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    93
	if not token_id then
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    94
		return nil, "invalid-token-format";
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    95
	end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    96
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    97
	local token_info, err = _get_parsed_token_info(token_id, token_user, token_host);
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    98
	if not token_info then return nil, err; end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    99
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   100
	return {
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   101
		username = token_user;
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   102
		host = token_host;
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   103
		resource = token_info.resource or resource or generate_identifier();
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   104
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   105
		role = select_role(token_user, token_host, token_info.role);
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   106
	};
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   107
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   108
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   109
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   110
function revoke_token(token)
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   111
	local token_id, token_user, token_host = parse_token(token);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   112
	if not token_id then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   113
		return nil, "invalid-token-format";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   114
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   115
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   116
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   117
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   118
	return token_store:set(token_user, token_id, nil);
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   119
end