changeset 4263:d3af5f94d6df

mod_http_oauth2: Improve storage of client secret Note well: This is still a thing for developers, do not panic!
author Kim Alvefur <zash@zash.se>
date Sun, 22 Nov 2020 01:32:09 +0100
parents 6d7fb22c0440
children 84bdf7e01744
files mod_adhoc_oauth2_client/mod_adhoc_oauth2_client.lua mod_http_oauth2/mod_http_oauth2.lua
diffstat 2 files changed, 20 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/mod_adhoc_oauth2_client/mod_adhoc_oauth2_client.lua	Sun Nov 22 01:31:27 2020 +0100
+++ b/mod_adhoc_oauth2_client/mod_adhoc_oauth2_client.lua	Sun Nov 22 01:32:09 2020 +0100
@@ -1,11 +1,16 @@
 local adhoc = require "util.adhoc";
 local dataforms = require "util.dataforms";
 local errors = require "util.error";
+local hashes = require "util.hashes";
 local id = require "util.id";
 local jid = require "util.jid";
+local base64 = require"util.encodings".base64;
 
 local clients = module:open_store("oauth2_clients", "map");
 
+local iteration_count = module:get_option_number("oauth2_client_iteration_count", 10000);
+local pepper = module:get_option_string("oauth2_client_pepper", "");
+
 local new_client = dataforms.new({
 	title = "Create OAuth2 client";
 	{var = "FORM_TYPE"; type = "hidden"; value = "urn:uuid:ff0d55ed-2187-4ee0-820a-ab633a911c14#create"};
@@ -32,15 +37,19 @@
 
 	local creator = jid.split(data.from);
 	local client_id = id.short();
+	local client_secret = id.long();
+	local salt = id.medium();
+	local i = iteration_count;
 
-	client.client_id = jid.join(creator, module.host, client_id);
-	client.client_secret = id.long();
+	client.secret_hash = base64.encode(hashes.pbkdf2_hmac_sha256(client_secret, salt .. pepper, i));
+	client.iteration_count = i;
+	client.salt = salt;
 
 	local ok, err = errors.coerce(clients:set(creator, client_id, client));
 	module:log("info", "OAuth2 client %q created by %s", client_id, data.from);
 	if not ok then return {status = "error"; error = {message = err}}; end
 
-	return {status = "completed"; result = {layout = client_created; values = client}};
+	return {status = "completed"; result = {layout = client_created; values = {client_id = client.client_id; client_secret = client_secret}}};
 end
 
 local handler = adhoc.new_simple_form(new_client, create_client);
--- a/mod_http_oauth2/mod_http_oauth2.lua	Sun Nov 22 01:31:27 2020 +0100
+++ b/mod_http_oauth2/mod_http_oauth2.lua	Sun Nov 22 01:32:09 2020 +0100
@@ -1,3 +1,4 @@
+local hashes = require "util.hashes";
 local http = require "util.http";
 local jid = require "util.jid";
 local json = require "util.json";
@@ -90,6 +91,12 @@
 	}
 end
 
+local pepper = module:get_option_string("oauth2_client_pepper", "");
+
+local function verify_secret(stored, salt, i, secret)
+	return base64.decode(stored) == hashes.pbkdf2_hmac_sha256(secret, salt .. pepper, i);
+end
+
 function grant_type_handlers.authorization_code(params)
 	if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end
 	if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end
@@ -105,7 +112,7 @@
 	end
 	local client, err = clients:get(client_owner, client_id);
 	if err then error(err); end
-	if not client or client.client_secret ~= params.client_secret then
+	if not client or not verify_secret(client.secret_hash, client.salt, client.iteration_count, params.client_secret) then
 		module:log("debug", "client_secret mismatch");
 		return oauth_error("invalid_client", "incorrect credentials");
 	end