1 local hashes = require "util.hashes"; |
1 local hashes = require "util.hashes"; |
|
2 local cache = require "util.cache"; |
2 local http = require "util.http"; |
3 local http = require "util.http"; |
3 local jid = require "util.jid"; |
4 local jid = require "util.jid"; |
4 local json = require "util.json"; |
5 local json = require "util.json"; |
5 local usermanager = require "core.usermanager"; |
6 local usermanager = require "core.usermanager"; |
6 local errors = require "util.error"; |
7 local errors = require "util.error"; |
10 local base64 = encodings.base64; |
11 local base64 = encodings.base64; |
11 |
12 |
12 local tokens = module:depends("tokenauth"); |
13 local tokens = module:depends("tokenauth"); |
13 |
14 |
14 local clients = module:open_store("oauth2_clients", "map"); |
15 local clients = module:open_store("oauth2_clients", "map"); |
15 local codes = module:open_store("oauth2_codes", "map"); |
|
16 |
16 |
17 local function code_expired(code) |
17 local function code_expired(code) |
18 return os.difftime(os.time(), code.issued) > 120; |
18 return os.difftime(os.time(), code.issued) > 120; |
19 end |
19 end |
|
20 |
|
21 local codes = cache.new(10000, function (_, code) |
|
22 return code_expired(code) |
|
23 end); |
20 |
24 |
21 local function oauth_error(err_name, err_desc) |
25 local function oauth_error(err_name, err_desc) |
22 return errors.new({ |
26 return errors.new({ |
23 type = "modify"; |
27 type = "modify"; |
24 condition = "bad-request"; |
28 condition = "bad-request"; |
74 if not client then |
78 if not client then |
75 return oauth_error("invalid_client", "incorrect credentials"); |
79 return oauth_error("invalid_client", "incorrect credentials"); |
76 end |
80 end |
77 |
81 |
78 local code = uuid.generate(); |
82 local code = uuid.generate(); |
79 assert(codes:set(client_owner, client_id .. "#" .. code, {issued = os.time(); granted_jid = granted_jid})); |
83 assert(codes:set(params.client_id .. "#" .. code, {issued = os.time(); granted_jid = granted_jid})); |
80 |
84 |
81 local redirect = url.parse(params.redirect_uri); |
85 local redirect = url.parse(params.redirect_uri); |
82 local query = http.formdecode(redirect.query or ""); |
86 local query = http.formdecode(redirect.query or ""); |
83 if type(query) ~= "table" then query = {}; end |
87 if type(query) ~= "table" then query = {}; end |
84 table.insert(query, { name = "code", value = code }) |
88 table.insert(query, { name = "code", value = code }) |
118 if err then error(err); end |
122 if err then error(err); end |
119 if not client or not verify_secret(client.secret_hash, client.salt, client.iteration_count, params.client_secret) then |
123 if not client or not verify_secret(client.secret_hash, client.salt, client.iteration_count, params.client_secret) then |
120 module:log("debug", "client_secret mismatch"); |
124 module:log("debug", "client_secret mismatch"); |
121 return oauth_error("invalid_client", "incorrect credentials"); |
125 return oauth_error("invalid_client", "incorrect credentials"); |
122 end |
126 end |
123 local code, err = codes:get(client_owner, client_id .. "#" .. params.code); |
127 local code, err = codes:get(params.client_id .. "#" .. params.code); |
124 if err then error(err); end |
128 if err then error(err); end |
125 if not code or type(code) ~= "table" or code_expired(code) then |
129 if not code or type(code) ~= "table" or code_expired(code) then |
126 module:log("debug", "authorization_code invalid or expired: %q", code); |
130 module:log("debug", "authorization_code invalid or expired: %q", code); |
127 return oauth_error("invalid_client", "incorrect credentials"); |
131 return oauth_error("invalid_client", "incorrect credentials"); |
128 end |
132 end |