Mercurial > prosody-modules
view mod_auth_ha1/mod_auth_ha1.lua @ 5715:8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
This follows the intent behind the OpenID Connect 'prompt' parameter
when it does not include the 'consent' keyword, that is the client
wishes to skip the consent screen. If the user has already granted the
exact same scopes to the exact same client in the past, then one can
assume that they may grant it again.
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Tue, 14 Nov 2023 23:03:37 +0100 |
parents | 31c4d92a81e5 |
children |
line wrap: on
line source
-- Prosody IM -- Copyright (C) 2014 Matthew Wild -- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- local usermanager = require "core.usermanager"; local new_sasl = require "util.sasl".new; local nodeprep = require "util.encodings".stringprep.nodeprep; local nameprep = require "util.encodings".stringprep.nameprep; local md5 = require "util.hashes".md5; local host = module.host; local auth_filename = module:get_option_string("auth_ha1_file", "auth.txt"); local auth_data = {}; function reload_auth_data() local f, err = io.open(auth_filename); if not f then module:log("error", "Failed to read from auth file: %s", err); return; end auth_data = {}; local line_number, imported_count, not_authorized_count = 0, 0, 0; for line in f:lines() do line_number = line_number + 1; local username, hash, realm, state = line:match("^([^:]+):(%x+):([^:]+):(.+)$"); if not username then if line:sub(1,1) ~= "#" then module:log("error", "Unable to parse line %d of auth file, skipping", line_number); end else username, realm = nodeprep(username), nameprep(realm); if not username then module:log("error", "Invalid username on line %d of auth file, skipping", line_number); elseif not realm then module:log("error", "Invalid hostname/realm on line %d of auth file, skipping", line_number); elseif state ~= "authorized" then not_authorized_count = not_authorized_count + 1; elseif realm == host then auth_data[username] = hash; imported_count = imported_count + 1; end end end f:close(); module:log("debug", "Loaded %d accounts from auth file (%d authorized)", imported_count, imported_count-not_authorized_count); end function module.load() reload_auth_data(); end module:hook_global("config-reloaded", reload_auth_data); -- define auth provider local provider = {}; function provider.test_password(username, password) module:log("debug", "test password for user %s at host %s, %s", username, host, password); local test_hash = md5(username..":"..host..":"..password, true); if test_hash == auth_data[username] then return true; else return nil, "Auth failed. Invalid username or password."; end end function provider.set_password(username, password) return nil, "Changing passwords not supported"; end function provider.user_exists(username) if not auth_data[username] then module:log("debug", "account not found for username '%s' at host '%s'", username, host); return nil, "Auth failed. Invalid username"; end return true; end function provider.create_user(username, password) return nil, "User creation not supported"; end function provider.delete_user(username) return nil , "User deletion not supported"; end function provider.get_sasl_handler() return new_sasl(host, { plain_test = function(sasl, username, password, realm) return usermanager.test_password(username, realm, password), true; end }); end module:provides("auth", provider);