annotate mod_couchdb/couchdb/couchapi.lib.lua @ 5193:2bb29ece216b

mod_http_oauth2: Implement stateless dynamic client registration Replaces previous explicit registration that required either the additional module mod_adhoc_oauth2_client or manually editing the database. That method was enough to have something to test with, but would not probably not scale easily. Dynamic client registration allows creating clients on the fly, which may be even easier in theory. In order to not allow basically unauthenticated writes to the database, we implement a stateless model here. per_host_key := HMAC(config -> oauth2_registration_key, hostname) client_id := JWT { client metadata } signed with per_host_key client_secret := HMAC(per_host_key, client_id) This should ensure everything we need to know is part of the client_id, allowing redirects etc to be validated, and the client_secret can be validated with only the client_id and the per_host_key. A nonce injected into the client_id JWT should ensure nobody can submit the same client metadata and retrieve the same client_secret
author Kim Alvefur <zash@zash.se>
date Fri, 03 Mar 2023 21:14:19 +0100
parents 316d7c8e1fb0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
204
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
1
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
2 local setmetatable = setmetatable;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
3 local pcall = pcall;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
4 local type = type;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
5 local t_concat = table.concat;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
6 local print = print;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
7
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
8 local socket_url = require "socket.url";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
9 local http = require "socket.http";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
10 local ltn12 = require "ltn12";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
11
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
12 --local json = require "json";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
13 local json = module:require("couchdb/json");
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
14
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
15 --module("couchdb")
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
16 local _M = {};
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
17
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
18 local function urlcat(url, path)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
19 return url:gsub("/*$", "").."/"..path:gsub("^/*", "");
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
20 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
21
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
22 local doc_mt = {};
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
23 doc_mt.__index = doc_mt;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
24
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
25 function doc_mt:get()
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
26 return self.db:get(socket_url.escape(self.id));
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
27 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
28 function doc_mt:put(val)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
29 return self.db:put(socket_url.escape(self.id), val);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
30 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
31 function doc_mt:__tostring()
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
32 return "couchdb.doc("..self.url..")";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
33 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
34
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
35
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
36 local db_mt = {};
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
37 db_mt.__index = db_mt;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
38
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
39 function db_mt:__tostring()
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
40 return "couchdb.db("..self.url..")";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
41 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
42 function db_mt:doc(id)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
43 local url = urlcat(self.url, socket_url.escape(id));
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
44 return setmetatable({ url = url, db = self, id = id }, doc_mt);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
45 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
46 function db_mt:get(id)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
47 local url = urlcat(self.url, id);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
48 local a,b = http.request(url);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
49 local r,x = pcall(json.decode, a);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
50 if r then a = x; end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
51 return a,b;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
52 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
53 function db_mt:put(id, value)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
54 local url = urlcat(self.url, id);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
55 if type(value) == "table" then
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
56 value = json.encode(value);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
57 elseif value ~= nil and type(value) ~= "string" then
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
58 return nil, "Invalid type";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
59 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
60 local t = {};
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
61 local a,b = http.request {
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
62 url = url,
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
63 sink = ltn12.sink.table(t),
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
64 source = ltn12.source.string(value),
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
65 method = "PUT",
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
66 headers = {
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
67 ["Content-Length"] = #value,
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
68 ["Content-Type"] = "application/json"
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
69 }
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
70 };
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
71 a = t_concat(t);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
72 local r,x = pcall(json.decode, a);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
73 if r then a = x; end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
74 return a,b;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
75 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
76
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
77
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
78 local server_mt = {};
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
79 server_mt.__index = server_mt;
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
80
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
81 function server_mt:db(name)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
82 local url = urlcat(self.url, socket_url.escape(name));
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
83 return setmetatable({ url = url }, db_mt);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
84 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
85 function server_mt:__tostring()
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
86 return "couchdb.server("..self.url..")";
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
87 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
88
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
89
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
90 function _M.server(url)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
91 return setmetatable({ url = url }, server_mt);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
92 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
93 function _M.db(url)
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
94 return setmetatable({ url = url }, db_mt);
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
95 end
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
96
316d7c8e1fb0 mod_couchdb: Initial commit.
Waqas Hussain <waqas20@gmail.com>
parents:
diff changeset
97 return _M;