Diff

mod_http_oauth2/mod_http_oauth2.lua @ 6245:ea58d2893afb draft default tip

Merge update
author Trần H. Trung <xmpp:trần.h.trung@trung.fun>
date Tue, 29 Apr 2025 23:27:06 +0700
parent 6211:750d64c47ec6
parent 6240:ab14e7ecb82f
line wrap: on
line diff
--- a/mod_http_oauth2/mod_http_oauth2.lua	Fri Apr 11 23:19:21 2025 +0700
+++ b/mod_http_oauth2/mod_http_oauth2.lua	Tue Apr 29 23:27:06 2025 +0700
@@ -134,6 +134,7 @@
 
 local pkce_required = module:get_option_boolean("oauth2_require_code_challenge", true);
 local respect_prompt = module:get_option_boolean("oauth2_respect_oidc_prompt", false);
+local expect_username_jid = module:get_option_boolean("oauth2_expect_username_jid", false);
 
 local verification_key;
 local sign_client, verify_client;
@@ -397,21 +398,52 @@
 	return oauth_error("invalid_request");
 end
 
+local function make_client_secret(client_id) --> client_secret
+       return hashes.hmac_sha256(verification_key, client_id, true);
+end
+
+local function verify_client_secret(client_id, client_secret)
+       return hashes.equals(make_client_secret(client_id), client_secret);
+end
+
 function grant_type_handlers.password(params)
-	local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)"));
-	local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'"));
-	local request_username, request_host, request_resource = jid.prepped_split(request_jid);
+	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
+
+	local client = check_client(params.client_id);
+	if not client then
+		return oauth_error("invalid_client", "incorrect credentials");
+	end
 
-	if not (request_username and request_host) or request_host ~= module.host then
-		return oauth_error("invalid_request", "invalid JID");
+	if not verify_client_secret(params.client_id, params.client_secret) then
+		module:log("debug", "client_secret mismatch");
+		return oauth_error("invalid_client", "incorrect credentials");
 	end
-	if not usermanager.test_password(request_username, request_host, request_password) then
+
+	local request_username
+
+	if expect_username_jid then
+		local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)"));
+		local _request_username, request_host, request_resource = jid.prepped_split(request_jid);
+
+		if not (_request_username and request_host) or request_host ~= module.host then
+			return oauth_error("invalid_request", "invalid JID");
+		end
+
+		request_username = _request_username
+	else
+		request_username = assert(params.username, oauth_error("invalid_request", "missing 'username'"));
+	end
+
+	local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'"));
+
+	if not usermanager.test_password(request_username, module.host, request_password) then
 		return oauth_error("invalid_grant", "incorrect credentials");
 	end
 
-	local granted_jid = jid.join(request_username, request_host, request_resource);
+	local granted_jid = jid.join(request_username, module.host);
 	local granted_scopes, granted_role = filter_scopes(request_username, params.scope);
-	return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, nil));
+	return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, client));
 end
 
 function response_type_handlers.code(client, params, granted_jid, id_token)
@@ -505,14 +537,6 @@
 	}
 end
 
-local function make_client_secret(client_id) --> client_secret
-	return hashes.hmac_sha256(verification_key, client_id, true);
-end
-
-local function verify_client_secret(client_id, client_secret)
-	return hashes.equals(make_client_secret(client_id), client_secret);
-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