plugins/mod_tokenauth.lua
author Kim Alvefur <zash@zash.se>
Wed, 27 Mar 2024 19:33:11 +0100
changeset 13471 c2a476f4712a
parent 13360 bbbda8819331
permissions -rw-r--r--
util.startup: Fix exiting on pidfile trouble prosody.shutdown() relies on prosody.main_thread, which has not been set yet at this point. Doing a clean shutdown might actually be harmful in case it tears down things set up by the conflicting Prosody, such as the very pidfile we were looking at. Thanks again SigmaTel71 for noticing
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12981
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     1
local base64 = require "prosody.util.encodings".base64;
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     2
local hashes = require "prosody.util.hashes";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     3
local id = require "prosody.util.id";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     4
local jid = require "prosody.util.jid";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     5
local random = require "prosody.util.random";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     6
local usermanager = require "prosody.core.usermanager";
74b9e05af71e plugins: Prefix module imports with prosody namespace
Kim Alvefur <zash@zash.se>
parents: 12963
diff changeset
     7
local generate_identifier = require "prosody.util.id".short;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
     8
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
     9
local token_store = module:open_store("auth_tokens", "keyval+");
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    10
13213
c8d949cf6b09 plugins: Switch to :get_option_period() for time range options
Kim Alvefur <zash@zash.se>
parents: 13103
diff changeset
    11
local access_time_granularity = module:get_option_period("token_auth_access_time_granularity", 60);
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
    12
local empty_grant_lifetime = module:get_option_period("tokenless_grant_ttl", "2w");
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    13
13103
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    14
local function select_role(username, host, role_name)
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    15
	if not role_name then return end
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    16
	local role = usermanager.get_role_by_name(role_name, host);
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    17
	if not role then return end
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    18
	if not usermanager.user_can_assume_role(username, host, role.name) then return end
a1ba503610ed mod_tokenauth: Support selection of _no_ role at all
Kim Alvefur <zash@zash.se>
parents: 13102
diff changeset
    19
	return role;
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    20
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
    21
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    22
function create_grant(actor_jid, grant_jid, grant_ttl, grant_data)
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    23
	grant_jid = jid.prep(grant_jid);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    24
	if not actor_jid or actor_jid ~= grant_jid and not jid.compare(grant_jid, actor_jid) then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    25
		module:log("debug", "Actor <%s> is not permitted to create a token granting access to JID <%s>", actor_jid, grant_jid);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    26
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    27
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    28
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    29
	local grant_username, grant_host, grant_resource = jid.split(grant_jid);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    30
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    31
	if grant_host ~= module.host then
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    32
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    33
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    34
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    35
	local grant_id = id.short();
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    36
	local now = os.time();
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    37
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    38
	local grant = {
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    39
		id = grant_id;
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
    40
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    41
		owner = actor_jid;
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    42
		created = now;
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    43
		expires = grant_ttl and (now + grant_ttl) or nil;
12984
6ebad8e16b3b mod_tokenauth: Track last access time (last time a token was used)
Matthew Wild <mwild1@gmail.com>
parents: 12981
diff changeset
    44
		accessed = now;
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    45
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    46
		jid = grant_jid;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    47
		resource = grant_resource;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    48
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    49
		data = grant_data;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    50
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    51
		-- tokens[<hash-name>..":"..<secret>] = token_info
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    52
		tokens = {};
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    53
	};
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    54
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    55
	local ok, err = token_store:set_key(grant_username, grant_id, grant);
13000
e8716515405e mod_tokenauth: return error if storage of new token fails
Matthew Wild <mwild1@gmail.com>
parents: 12984
diff changeset
    56
	if not ok then
e8716515405e mod_tokenauth: return error if storage of new token fails
Matthew Wild <mwild1@gmail.com>
parents: 12984
diff changeset
    57
		return nil, err;
e8716515405e mod_tokenauth: return error if storage of new token fails
Matthew Wild <mwild1@gmail.com>
parents: 12984
diff changeset
    58
	end
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    59
13007
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    60
	module:fire_event("token-grant-created", {
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    61
		id = grant_id;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    62
		grant = grant;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    63
		username = grant_username;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    64
		host = grant_host;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    65
	});
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
    66
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    67
	return grant;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    68
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
    69
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    70
function create_token(grant_jid, grant, token_role, token_ttl, token_purpose, token_data)
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    71
	if (token_data and type(token_data) ~= "table") or (token_purpose and type(token_purpose) ~= "string") then
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    72
		return nil, "bad-request";
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    73
	end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    74
	local grant_username, grant_host = jid.split(grant_jid);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    75
	if grant_host ~= module.host then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    76
		return nil, "invalid-host";
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    77
	end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    78
	if type(grant) == "string" then -- lookup by id
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    79
		grant = token_store:get_key(grant_username, grant);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    80
		if not grant then return nil; end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    81
	end
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    82
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    83
	if not grant.tokens then return nil, "internal-server-error"; end -- old-style token?
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    84
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    85
	local now = os.time();
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    86
	local expires = grant.expires; -- Default to same expiry as grant
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    87
	if token_ttl then -- explicit lifetime requested
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    88
		if expires then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    89
			-- Grant has an expiry, so limit to that or shorter
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    90
			expires = math.min(now + token_ttl, expires);
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    91
		else
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    92
			-- Grant never expires, just use whatever expiry is requested for the token
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    93
			expires = now + token_ttl;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    94
		end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    95
	end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
    96
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    97
	local token_info = {
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    98
		role = token_role;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
    99
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   100
		created = now;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   101
		expires = expires;
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   102
		purpose = token_purpose;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   103
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   104
		data = token_data;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   105
	};
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   106
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   107
	local token_secret = random.bytes(18);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   108
	grant.tokens["sha256:"..hashes.sha256(token_secret, true)] = token_info;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   109
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   110
	local ok, err = token_store:set_key(grant_username, grant.id, grant);
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   111
	if not ok then
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   112
		return nil, err;
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   113
	end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   114
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   115
	local token_string = "secret-token:"..base64.encode("2;"..grant.id..";"..token_secret..";"..grant.jid);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   116
	return token_string, token_info;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   117
end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   118
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   119
local function parse_token(encoded_token)
12921
e4de42495fb7 mod_tokenauth: Gracefully handle missing tokens
Matthew Wild <mwild1@gmail.com>
parents: 12919
diff changeset
   120
	if not encoded_token then return nil; end
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   121
	local encoded_data = encoded_token:match("^secret%-token:(.+)$");
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   122
	if not encoded_data then return nil; end
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   123
	local token = base64.decode(encoded_data);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   124
	if not token then return nil; end
13078
794a5ad5495e mod_tokenauth: Fix parsing binary part of tokens
Kim Alvefur <zash@zash.se>
parents: 13077
diff changeset
   125
	local token_id, token_secret, token_jid = token:match("^2;([^;]+);(..................);(.+)$");
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   126
	if not token_id then return nil; end
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   127
	local token_user, token_host = jid.split(token_jid);
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   128
	return token_id, token_user, token_host, token_secret;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   129
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   130
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   131
local function clear_expired_grant_tokens(grant, now)
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   132
	local updated;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   133
	now = now or os.time();
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   134
	for secret, token_info in pairs(grant.tokens) do
13003
c87ac7d1967f mod_tokenauth: Fix traceback when checking expiry of tokens with no expiry
Matthew Wild <mwild1@gmail.com>
parents: 13002
diff changeset
   135
		local expires = token_info.expires;
c87ac7d1967f mod_tokenauth: Fix traceback when checking expiry of tokens with no expiry
Matthew Wild <mwild1@gmail.com>
parents: 13002
diff changeset
   136
		if expires and expires < now then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   137
			grant.tokens[secret] = nil;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   138
			updated = true;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   139
		end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   140
	end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   141
	return updated;
13001
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   142
end
0a56b84ec4ad mod_tokenauth: Support for creating sub-tokens
Matthew Wild <mwild1@gmail.com>
parents: 13000
diff changeset
   143
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   144
local function _get_validated_grant_info(username, grant)
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   145
	if type(grant) == "string" then
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   146
		grant = token_store:get_key(username, grant);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   147
	end
13360
bbbda8819331 mod_tokenauth: Ignore invalid grants in storage that have no id
Matthew Wild <mwild1@gmail.com>
parents: 13325
diff changeset
   148
	if not grant or not grant.created or not grant.id then return nil; end
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   149
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   150
	-- Invalidate grants from before last password change
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   151
	local account_info = usermanager.get_account_info(username, module.host);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   152
	local password_updated_at = account_info and account_info.password_updated;
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   153
	local now = os.time();
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   154
	if password_updated_at and grant.created < password_updated_at then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   155
		module:log("debug", "Token grant %s of %s issued before last password change, invalidating it now", grant.id, username);
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   156
		token_store:set_key(username, grant.id, nil);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   157
		return nil, "not-authorized";
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   158
	elseif grant.expires and grant.expires < now then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   159
		module:log("debug", "Token grant %s of %s expired, cleaning up", grant.id, username);
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   160
		token_store:set_key(username, grant.id, nil);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   161
		return nil, "expired";
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   162
	end
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   163
13275
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   164
	if not grant.tokens then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   165
		module:log("debug", "Token grant %s of %s without tokens, cleaning up", grant.id, username);
13275
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   166
		token_store:set_key(username, grant.id, nil);
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   167
		return nil, "invalid";
56c1d2498d66 mod_tokenauth: Delete grants in the wrong formats on retrieval
Kim Alvefur <zash@zash.se>
parents: 13250
diff changeset
   168
	end
13309
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   169
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   170
	local found_expired = false
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   171
	for secret_hash, token_info in pairs(grant.tokens) do
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   172
		if token_info.expires and token_info.expires < now then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   173
			module:log("debug", "Token %s of grant %s of %s has expired, cleaning it up", secret_hash:sub(-8), grant.id, username);
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   174
			grant.tokens[secret_hash] = nil;
13279
5db61e0dfc62 mod_tokenauth: Save grant after removing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13278
diff changeset
   175
			found_expired = true;
5db61e0dfc62 mod_tokenauth: Save grant after removing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13278
diff changeset
   176
		end
13276
8535a6105919 mod_tokenauth: Clear expired tokens on grant retrieval
Kim Alvefur <zash@zash.se>
parents: 13275
diff changeset
   177
	end
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   178
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   179
	if not grant.expires and next(grant.tokens) == nil and grant.accessed + empty_grant_lifetime < now then
13325
19c814d4dd3a mod_tokenauth: Include more details in debug logs
Kim Alvefur <zash@zash.se>
parents: 13309
diff changeset
   180
		module:log("debug", "Token %s of %s grant has no tokens, discarding", grant.id, username);
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   181
		token_store:set_key(username, grant.id, nil);
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   182
		return nil, "expired";
13309
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   183
	elseif found_expired then
852a61c720d0 mod_tokenauth: Fix saving grants after clearing expired tokens
Kim Alvefur <zash@zash.se>
parents: 13280
diff changeset
   184
		token_store:set_key(username, grant.id, grant);
13277
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   185
	end
a1c927323f06 mod_tokenauth: Delete grants without tokens after period
Kim Alvefur <zash@zash.se>
parents: 13276
diff changeset
   186
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   187
	return grant;
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   188
end
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   189
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   190
local function _get_validated_token_info(token_id, token_user, token_host, token_secret)
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   191
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   192
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   193
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   194
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   195
	local grant, err = token_store:get_key(token_user, token_id);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   196
	if not grant or not grant.tokens then
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   197
		if err then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   198
			module:log("error", "Unable to read from token storage: %s", err);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   199
			return nil, "internal-error";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   200
		end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   201
		module:log("warn", "Invalid token in storage (%s / %s)", token_user, token_id);
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   202
		return nil, "not-authorized";
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   203
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   204
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   205
	-- Check provided secret
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   206
	local secret_hash = "sha256:"..hashes.sha256(token_secret, true);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   207
	local token_info = grant.tokens[secret_hash];
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   208
	if not token_info then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   209
		module:log("debug", "No tokens matched the given secret");
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   210
		return nil, "not-authorized";
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   211
	end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   212
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   213
	-- Check expiry
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   214
	local now = os.time();
13077
9e5802b45b9e mod_tokenauth: Only check if expiry of expiring tokens
Kim Alvefur <zash@zash.se>
parents: 13028
diff changeset
   215
	if token_info.expires and token_info.expires < now then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   216
		module:log("debug", "Token has expired, cleaning it up");
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   217
		grant.tokens[secret_hash] = nil;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   218
		token_store:set_key(token_user, token_id, grant);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   219
		return nil, "not-authorized";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   220
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   221
13013
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   222
	-- Verify grant validity (expiry, etc.)
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   223
	grant = _get_validated_grant_info(token_user, grant);
a70ff0c524c9 mod_tokenauth: Move grant validation to a reusable function
Matthew Wild <mwild1@gmail.com>
parents: 13010
diff changeset
   224
	if not grant then
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   225
		return nil, "not-authorized";
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   226
	end
12746
126aefd2c4c6 mod_tokenauth: Invalidate tokens issued before most recent password change
Matthew Wild <mwild1@gmail.com>
parents: 12666
diff changeset
   227
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   228
	-- Update last access time if necessary
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   229
	local last_accessed = grant.accessed;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   230
	if not last_accessed or (now - last_accessed) > access_time_granularity then
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   231
		grant.accessed = now;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   232
		clear_expired_grant_tokens(grant); -- Clear expired tokens while we're here
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   233
		token_store:set_key(token_user, token_id, grant);
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   234
	end
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   235
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   236
	token_info.id = token_id;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   237
	token_info.grant = grant;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   238
	token_info.jid = grant.jid;
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   239
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   240
	return token_info;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   241
end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   242
13014
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   243
function get_grant_info(username, grant_id)
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   244
	local grant = _get_validated_grant_info(username, grant_id);
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   245
	if not grant then return nil; end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   246
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   247
	-- Caller is only interested in the grant, no need to expose token stuff to them
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   248
	grant.tokens = nil;
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   249
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   250
	return grant;
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   251
end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   252
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   253
function get_user_grants(username)
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   254
	local grants = token_store:get(username);
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   255
	if not grants then return nil; end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   256
	for grant_id, grant in pairs(grants) do
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   257
		grants[grant_id] = _get_validated_grant_info(username, grant);
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   258
	end
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   259
	return grants;
3e454af3615d mod_tokenauth: Add API to inspect individual grants or all of a user's grants
Matthew Wild <mwild1@gmail.com>
parents: 13013
diff changeset
   260
end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   261
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   262
function get_token_info(token)
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   263
	local token_id, token_user, token_host, token_secret = parse_token(token);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   264
	if not token_id then
12956
a668bc1aa39d mod_tokenauth: Log error when token validation fails
Matthew Wild <mwild1@gmail.com>
parents: 12942
diff changeset
   265
		module:log("warn", "Failed to verify access token: %s", token_user);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   266
		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
   267
	end
12957
ebe3b2f96cad mod_tokenauth: Switch to new token format (invalidates existing tokens!)
Matthew Wild <mwild1@gmail.com>
parents: 12956
diff changeset
   268
	return _get_validated_token_info(token_id, token_user, token_host, token_secret);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   269
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   270
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   271
function get_token_session(token, resource)
12963
e331210beeb2 mod_tokenauth: Fix traceback in get_token_session()
Kim Alvefur <zash@zash.se>
parents: 12957
diff changeset
   272
	local token_id, token_user, token_host, token_secret = parse_token(token);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   273
	if not token_id then
12956
a668bc1aa39d mod_tokenauth: Log error when token validation fails
Matthew Wild <mwild1@gmail.com>
parents: 12942
diff changeset
   274
		module:log("warn", "Failed to verify access token: %s", token_user);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   275
		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
   276
	end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   277
12963
e331210beeb2 mod_tokenauth: Fix traceback in get_token_session()
Kim Alvefur <zash@zash.se>
parents: 12957
diff changeset
   278
	local token_info, err = _get_validated_token_info(token_id, token_user, token_host, token_secret);
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   279
	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
   280
13102
65d2ff6e674e mod_tokenauth: Return error instead of session for token without role
Kim Alvefur <zash@zash.se>
parents: 13078
diff changeset
   281
	local role = select_role(token_user, token_host, token_info.role);
65d2ff6e674e mod_tokenauth: Return error instead of session for token without role
Kim Alvefur <zash@zash.se>
parents: 13078
diff changeset
   282
	if not role then return nil, "not-authorized"; end
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   283
	return {
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   284
		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
   285
		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
   286
		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
   287
13102
65d2ff6e674e mod_tokenauth: Return error instead of session for token without role
Kim Alvefur <zash@zash.se>
parents: 13078
diff changeset
   288
		role = role;
12653
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   289
	};
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   290
end
86e1187f6274 mod_tokenauth: New API that better fits how modules are using token auth
Matthew Wild <mwild1@gmail.com>
parents: 10679
diff changeset
   291
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   292
function revoke_token(token)
13250
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   293
	local grant_id, token_user, token_host, token_secret = parse_token(token);
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   294
	if not grant_id then
12956
a668bc1aa39d mod_tokenauth: Log error when token validation fails
Matthew Wild <mwild1@gmail.com>
parents: 12942
diff changeset
   295
		module:log("warn", "Failed to verify access token: %s", token_user);
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   296
		return nil, "invalid-token-format";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   297
	end
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   298
	if token_host ~= module.host then
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   299
		return nil, "invalid-host";
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   300
	end
13250
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   301
	local grant, err = _get_validated_grant_info(token_user, grant_id);
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   302
	if not grant then return grant, err; end
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   303
	local secret_hash = "sha256:"..hashes.sha256(token_secret, true);
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   304
	local token_info = grant.tokens[secret_hash];
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   305
	if not grant or not token_info then
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   306
		return nil, "item-not-found";
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   307
	end
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   308
	grant.tokens[secret_hash] = nil;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   309
	local ok, err = token_store:set_key(token_user, grant_id, grant);
13007
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   310
	if not ok then
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   311
		return nil, err;
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   312
	end
13250
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   313
	module:fire_event("token-revoked", {
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   314
		grant_id = grant_id;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   315
		grant = grant;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   316
		info = token_info;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   317
		username = token_user;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   318
		host = token_host;
2e04d54fb013 mod_tokenauth: Fix revoking a single token without revoking whole grant
Kim Alvefur <zash@zash.se>
parents: 13213
diff changeset
   319
	});
13007
34ed17ef1c1a mod_tokenauth: Fire events on grant creation and revocation
Matthew Wild <mwild1@gmail.com>
parents: 13004
diff changeset
   320
	return true;
10672
25c84c0a66fd mod_authtokens: New module for managing auth tokens
Matthew Wild <mwild1@gmail.com>
parents:
diff changeset
   321
end
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   322
13028
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   323
function revoke_grant(username, grant_id)
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   324
	local ok, err = token_store:set_key(username, grant_id, nil);
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   325
	if not ok then return nil, err; end
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   326
	module:fire_event("token-grant-revoked", { id = grant_id, username = username, host = module.host });
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   327
	return true;
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   328
end
7558fd152459 mod_tokenauth: Add API method to revoke a grant by id
Matthew Wild <mwild1@gmail.com>
parents: 13014
diff changeset
   329
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   330
function sasl_handler(auth_provider, purpose, extra)
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   331
	return function (sasl, token, realm, _authzid)
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   332
		local token_info, err = get_token_info(token);
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   333
		if not token_info then
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   334
			module:log("debug", "SASL handler failed to verify token: %s", err);
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   335
			return nil, nil, extra;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   336
		end
13002
601d9a375b86 mod_tokenauth: Refactor API to separate tokens and grants
Matthew Wild <mwild1@gmail.com>
parents: 13001
diff changeset
   337
		local token_user, token_host, resource = jid.split(token_info.grant.jid);
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   338
		if realm ~= token_host or (purpose and token_info.purpose ~= purpose) then
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   339
			return nil, nil, extra;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   340
		end
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   341
		if auth_provider.is_enabled and not auth_provider.is_enabled(token_user) then
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   342
			return true, false, token_info;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   343
		end
12942
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   344
		sasl.resource = resource;
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   345
		sasl.token_info = token_info;
055b03d3059b util.sasl.oauthbearer: Return username from callback instead using authzid (BC)
Kim Alvefur <zash@zash.se>
parents: 12923
diff changeset
   346
		return token_user, true, token_info;
12919
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   347
	end;
70f6a8dceb1d mod_tokenauth: Add SASL handler backend that can accept and verify tokens
Matthew Wild <mwild1@gmail.com>
parents: 12918
diff changeset
   348
end
13278
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   349
13280
c34266c061c9 mod_tokenauth: Set name/description on cleanup job
Kim Alvefur <zash@zash.se>
parents: 13279
diff changeset
   350
module:daily("clear expired grants", function()
13278
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   351
	for username in token_store:items() do
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   352
		get_user_grants(username); -- clears out expired grants
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   353
	end
ddfe07041fc5 mod_tokenauth: Periodically clear out expired tokens and grants
Kim Alvefur <zash@zash.se>
parents: 13277
diff changeset
   354
end)