1local adhoc = require "util.adhoc"; 2local dataforms = require "util.dataforms"; 3local errors = require "util.error"; 4local hashes = require "util.hashes"; 5local id = require "util.id"; 6local jid = require "util.jid"; 7local base64 = require"util.encodings".base64; 8 9local clients = module:open_store("oauth2_clients", "map"); 10 11local iteration_count = module:get_option_number("oauth2_client_iteration_count", 10000); 12local pepper = module:get_option_string("oauth2_client_pepper", ""); 13 14local new_client = dataforms.new({ 15 title = "Create OAuth2 client"; 16 {var = "FORM_TYPE"; type = "hidden"; value = "urn:uuid:ff0d55ed-2187-4ee0-820a-ab633a911c14#create"}; 17 {name = "name"; type = "text-single"; label = "Client name"; required = true}; 18 {name = "description"; type = "text-multi"; label = "Description"}; 19 {name = "info_url"; type = "text-single"; label = "Informative URL"; desc = "Link to information about your client"; datatype = "xs:anyURI"}; 20 { 21 name = "redirect_uri"; 22 type = "text-single"; 23 label = "Redirection URI"; 24 desc = "Where to redirect the user after authorizing."; 25 datatype = "xs:anyURI"; 26 required = true; 27 }; 28}) 29 30local client_created = dataforms.new({ 31 title = "New OAuth2 client created"; 32 instructions = "Save these details, they will not be shown again"; 33 {var = "FORM_TYPE"; type = "hidden"; value = "urn:uuid:ff0d55ed-2187-4ee0-820a-ab633a911c14#created"}; 34 {name = "client_id"; type = "text-single"; label = "Client ID"}; 35 {name = "client_secret"; type = "text-single"; label = "Client secret"}; 36}) 37 38local function create_client(client, formerr, data) 39 if formerr then 40 local errmsg = {"Error in form:"}; 41 for field, err in pairs(formerr) do table.insert(errmsg, field .. ": " .. err); end 42 return {status = "error"; error = {message = table.concat(errmsg, "\n")}}; 43 end 44 45 local creator = jid.split(data.from); 46 local client_uid = id.short(); 47 local client_id = jid.join(creator, module.host, client_uid); 48 local client_secret = id.long(); 49 local salt = id.medium(); 50 local i = iteration_count; 51 52 client.secret_hash = base64.encode(hashes.pbkdf2_hmac_sha256(client_secret, salt .. pepper, i)); 53 client.iteration_count = i; 54 client.salt = salt; 55 56 local ok, err = errors.coerce(clients:set(creator, client_uid, client)); 57 module:log("info", "OAuth2 client %q created by %s", client_id, data.from); 58 if not ok then return {status = "canceled"; error = {message = err}}; end 59 60 return {status = "completed"; result = {layout = client_created; values = {client_id = client_id; client_secret = client_secret}}}; 61end 62 63local handler = adhoc.new_simple_form(new_client, create_client); 64 65module:provides("adhoc", module:require "adhoc".new(new_client.title, new_client[1].value, handler, "local_user")); 66 67-- TODO list/manage/revoke clients 68