author | Kim Alvefur <zash@zash.se> |
Fri, 23 Oct 2020 22:23:20 +0200 | |
changeset 4232 | 3eb595cf847f |
parent 3938 | 469408682152 |
child 4241 | a0ab7be0538d |
permissions | -rw-r--r-- |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1 |
local http = require "util.http"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
2 |
local jid = require "util.jid"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
3 |
local json = require "util.json"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
4 |
local usermanager = require "core.usermanager"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
5 |
local errors = require "util.error"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
6 |
|
3919
80dffbbd056b
mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents:
3912
diff
changeset
|
7 |
local tokens = module:depends("tokenauth"); |
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
8 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
9 |
local function oauth_error(err_name, err_desc) |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
10 |
return errors.new({ |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 |
type = "modify"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
12 |
condition = "bad-request"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
13 |
code = err_name == "invalid_client" and 401 or 400; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
14 |
text = err_desc and (err_name..": "..err_desc) or err_name; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
15 |
context = { oauth2_response = { error = err_name, error_description = err_desc } }; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
16 |
}); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
17 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
18 |
|
3922
dea6bea2ddd3
mod_http_oauth2: Refactor re-joining of JID out of token constructor
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
19 |
local function new_access_token(token_jid, scope, ttl) |
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
20 |
local token = tokens.create_jid_token(token_jid, token_jid, scope, ttl); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
21 |
return { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
22 |
token_type = "bearer"; |
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
23 |
access_token = token; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
24 |
expires_in = ttl; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
25 |
-- TODO: include refresh_token when implemented |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
26 |
}; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
27 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
28 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
29 |
local grant_type_handlers = {}; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
30 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
31 |
function grant_type_handlers.password(params) |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
32 |
local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)")); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
33 |
local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'")); |
3923
8ed261a08a9c
mod_http_oauth2: Allow creation of full JID tokens
Kim Alvefur <zash@zash.se>
parents:
3922
diff
changeset
|
34 |
local request_username, request_host, request_resource = jid.prepped_split(request_jid); |
4232
3eb595cf847f
mod_http_oauth2: Accept empty scope
Kim Alvefur <zash@zash.se>
parents:
3938
diff
changeset
|
35 |
if params.scope and param.scope ~= "" then |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
36 |
return oauth_error("invalid_scope", "unknown scope requested"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
37 |
end |
3912
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3907
diff
changeset
|
38 |
if not (request_username and request_host) or request_host ~= module.host then |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
39 |
return oauth_error("invalid_request", "invalid JID"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
40 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
41 |
if usermanager.test_password(request_username, request_host, request_password) then |
3923
8ed261a08a9c
mod_http_oauth2: Allow creation of full JID tokens
Kim Alvefur <zash@zash.se>
parents:
3922
diff
changeset
|
42 |
local granted_jid = jid.join(request_username, request_host, request_resource); |
3922
dea6bea2ddd3
mod_http_oauth2: Refactor re-joining of JID out of token constructor
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
43 |
return json.encode(new_access_token(granted_jid, request_host, nil, nil)); |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
44 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
45 |
return oauth_error("invalid_grant", "incorrect credentials"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
46 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
47 |
|
3924
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
48 |
if module:get_host_type() == "component" then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
49 |
local component_secret = assert(module:get_option_string("component_secret"), "'component_secret' is a required setting when loaded on a Component"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
50 |
|
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
51 |
function grant_type_handlers.password(params) |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
52 |
local request_jid = assert(params.username, oauth_error("invalid_request", "missing 'username' (JID)")); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
53 |
local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'")); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
54 |
local request_username, request_host, request_resource = jid.prepped_split(request_jid); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
55 |
if params.scope then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
56 |
return oauth_error("invalid_scope", "unknown scope requested"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
57 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
58 |
if not request_host or request_host ~= module.host then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
59 |
return oauth_error("invalid_request", "invalid JID"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
60 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
61 |
if request_password == component_secret then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
62 |
local granted_jid = jid.join(request_username, request_host, request_resource); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
63 |
return json.encode(new_access_token(granted_jid, request_host, nil, nil)); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
64 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
65 |
return oauth_error("invalid_grant", "incorrect credentials"); |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
66 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
67 |
end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3923
diff
changeset
|
68 |
|
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
69 |
function handle_token_grant(event) |
3938
469408682152
mod_http_oauth2: Set content type on successful repsponses (fixes #1501)
Kim Alvefur <zash@zash.se>
parents:
3924
diff
changeset
|
70 |
event.response.headers.content_type = "application/json"; |
3907
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
71 |
local params = http.formdecode(event.request.body); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
72 |
if not params then |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
73 |
return oauth_error("invalid_request"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
74 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
75 |
local grant_type = params.grant_type |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
76 |
local grant_handler = grant_type_handlers[grant_type]; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
77 |
if not grant_handler then |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
78 |
return oauth_error("unsupported_grant_type"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
79 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
80 |
return grant_handler(params); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
81 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
82 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
83 |
module:depends("http"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
84 |
module:provides("http", { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
85 |
route = { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
86 |
["POST /token"] = handle_token_grant; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
87 |
}; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
88 |
}); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
89 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
90 |
local http_server = require "net.http.server"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
91 |
|
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
92 |
module:hook_object_event(http_server, "http-error", function (event) |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
93 |
local oauth2_response = event.error and event.error.context and event.error.context.oauth2_response; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
94 |
if not oauth2_response then |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
95 |
return; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
96 |
end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
97 |
event.response.headers.content_type = "application/json"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
98 |
event.response.status_code = event.error.code or 400; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
99 |
return json.encode(oauth2_response); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
100 |
end, 5); |