Mercurial > prosody-modules
annotate mod_http_oauth2/mod_http_oauth2.lua @ 5718:8cd617c0b701
mod_invites_page: Replace jQuery with vanilla.js in the HTML
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Thu, 16 Nov 2023 16:15:26 +0100 |
parents | 426c42c11f89 |
children | d563a6b0dfb7 |
rev | line source |
---|---|
5501 | 1 local usermanager = require "core.usermanager"; |
2 local url = require "socket.url"; | |
3 local array = require "util.array"; | |
4271
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
4 local cache = require "util.cache"; |
5501 | 5 local encodings = require "util.encodings"; |
6 local errors = require "util.error"; | |
7 local hashes = require "util.hashes"; | |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
8 local http = require "util.http"; |
5501 | 9 local id = require "util.id"; |
10 local it = require "util.iterators"; | |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
11 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
|
12 local json = require "util.json"; |
5501 | 13 local schema = require "util.jsonschema"; |
14 local jwt = require "util.jwt"; | |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
15 local random = require "util.random"; |
5209
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5208
diff
changeset
|
16 local set = require "util.set"; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
17 local st = require "util.stanza"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
18 |
5501 | 19 local base64 = encodings.base64; |
20 | |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
21 local function b64url(s) |
5392
c0a6f39caf47
mod_http_oauth2: Fix missing base64 part of base64url (Thanks KeyCloak)
Kim Alvefur <zash@zash.se>
parents:
5391
diff
changeset
|
22 return (base64.encode(s):gsub("[+/=]", { ["+"] = "-", ["/"] = "_", ["="] = "" })) |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
23 end |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
24 |
5400
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
25 local function tmap(t) |
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
26 return function(k) |
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
27 return t[k]; |
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
28 end |
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
29 end |
71766a4a7322
mod_http_oauth2: Reduce line count of metadata construction
Kim Alvefur <zash@zash.se>
parents:
5399
diff
changeset
|
30 |
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
31 local function strict_formdecode(query) |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
32 if not query then |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
33 return nil; |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
34 end |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
35 local params = http.formdecode(query); |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
36 if type(params) ~= "table" then |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
37 return nil, "no-pairs"; |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
38 end |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
39 local dups = {}; |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
40 for _, pair in ipairs(params) do |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
41 if dups[pair.name] then |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
42 return nil, "duplicate"; |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
43 end |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
44 dups[pair.name] = true; |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
45 end |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
46 return params; |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
47 end |
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
48 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
49 local function read_file(base_path, fn, required) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
50 local f, err = io.open(base_path .. "/" .. fn); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
51 if not f then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
52 module:log(required and "error" or "debug", "Unable to load template file: %s", err); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
53 if required then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
54 return error("Failed to load templates"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
55 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
56 return nil; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
57 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
58 local data = assert(f:read("*a")); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
59 assert(f:close()); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
60 return data; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
61 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
62 |
5554
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
63 local allowed_locales = module:get_option_array("allowed_oauth2_locales", {}); |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
64 -- TODO Allow translations or per-locale templates somehow. |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
65 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
66 local template_path = module:get_option_path("oauth2_template_path", "html"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
67 local templates = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
68 login = read_file(template_path, "login.html", true); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
69 consent = read_file(template_path, "consent.html", true); |
5495
7998b49d6512
mod_http_oauth2: Create proper template for OOB code delivery
Kim Alvefur <zash@zash.se>
parents:
5480
diff
changeset
|
70 oob = read_file(template_path, "oob.html", true); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
71 device = read_file(template_path, "device.html", true); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
72 error = read_file(template_path, "error.html", true); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
73 css = read_file(template_path, "style.css"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
74 js = read_file(template_path, "script.js"); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
75 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
76 |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
77 local site_name = module:get_option_string("site_name", module.host); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
78 |
5547
d4a2997deae9
mod_http_oauth2: Make CSP configurable
Kim Alvefur <zash@zash.se>
parents:
5544
diff
changeset
|
79 local security_policy = module:get_option_string("oauth2_security_policy", "default-src 'self'"); |
d4a2997deae9
mod_http_oauth2: Make CSP configurable
Kim Alvefur <zash@zash.se>
parents:
5544
diff
changeset
|
80 |
5544
cb141088eff0
mod_http_oauth2: Remove underscore prefix
Kim Alvefur <zash@zash.se>
parents:
5526
diff
changeset
|
81 local render_html = require"util.interpolation".new("%b{}", st.xml_escape); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
82 local function render_page(template, data, sensitive) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
83 data = data or {}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
84 data.site_name = site_name; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
85 local resp = { |
5470
40c990159006
mod_http_oauth2: Use error status code when rendering error page
Kim Alvefur <zash@zash.se>
parents:
5469
diff
changeset
|
86 status_code = data.error and data.error.code or 200; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
87 headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
88 ["Content-Type"] = "text/html; charset=utf-8"; |
5547
d4a2997deae9
mod_http_oauth2: Make CSP configurable
Kim Alvefur <zash@zash.se>
parents:
5544
diff
changeset
|
89 ["Content-Security-Policy"] = security_policy; |
5479
30e2722c9fa3
mod_http_oauth2: Disable Referrer via header
Kim Alvefur <zash@zash.se>
parents:
5478
diff
changeset
|
90 ["Referrer-Policy"] = "no-referrer"; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
91 ["X-Frame-Options"] = "DENY"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
92 ["Cache-Control"] = (sensitive and "no-store" or "no-cache")..", private"; |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
93 ["Pragma"] = "no-cache"; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
94 }; |
5544
cb141088eff0
mod_http_oauth2: Remove underscore prefix
Kim Alvefur <zash@zash.se>
parents:
5526
diff
changeset
|
95 body = render_html(template, data); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
96 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
97 return resp; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
98 end |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
99 |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
100 local authorization_server_metadata = nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
101 |
3915
80dffbbd056b
mod_rest, mod_http_oauth2: Switch from mod_authtokens to mod_tokenauth per Prosody bf81523e2ff4
Matthew Wild <mwild1@gmail.com>
parents:
3908
diff
changeset
|
102 local tokens = module:depends("tokenauth"); |
3908
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3903
diff
changeset
|
103 |
5617
d8622797e315
mod_http_oauth2: Shorten default token validity periods
Kim Alvefur <zash@zash.se>
parents:
5616
diff
changeset
|
104 local default_access_ttl = module:get_option_number("oauth2_access_token_ttl", 3600); |
5619
81042c2a235a
mod_http_oauth2: Don't use new time period API just yet
Kim Alvefur <zash@zash.se>
parents:
5618
diff
changeset
|
105 local default_refresh_ttl = module:get_option_number("oauth2_refresh_token_ttl", 604800); |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
106 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
107 -- Used to derive client_secret from client_id, set to enable stateless dynamic registration. |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
108 local registration_key = module:get_option_string("oauth2_registration_key"); |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
109 local registration_algo = module:get_option_string("oauth2_registration_algorithm", "HS256"); |
5416
2393dbae51ed
mod_http_oauth2: Add option for specifying TTL of registered clients
Kim Alvefur <zash@zash.se>
parents:
5409
diff
changeset
|
110 local registration_ttl = module:get_option("oauth2_registration_ttl", nil); |
2393dbae51ed
mod_http_oauth2: Add option for specifying TTL of registered clients
Kim Alvefur <zash@zash.se>
parents:
5409
diff
changeset
|
111 local registration_options = module:get_option("oauth2_registration_options", |
2393dbae51ed
mod_http_oauth2: Add option for specifying TTL of registered clients
Kim Alvefur <zash@zash.se>
parents:
5409
diff
changeset
|
112 { default_ttl = registration_ttl; accept_expired = not registration_ttl }); |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
113 |
5716
426c42c11f89
mod_http_oauth2: Make defaults more secure
Kim Alvefur <zash@zash.se>
parents:
5715
diff
changeset
|
114 local pkce_required = module:get_option_boolean("oauth2_require_code_challenge", true); |
426c42c11f89
mod_http_oauth2: Make defaults more secure
Kim Alvefur <zash@zash.se>
parents:
5715
diff
changeset
|
115 local respect_prompt = module:get_option_boolean("oauth2_respect_oidc_prompt", false); |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
116 |
5199
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5198
diff
changeset
|
117 local verification_key; |
5459
260a859be86a
mod_http_oauth2: Rename variables to improve clarity
Kim Alvefur <zash@zash.se>
parents:
5458
diff
changeset
|
118 local sign_client, verify_client; |
5196
6b63af56c8ac
mod_http_oauth2: Remove error message
Kim Alvefur <zash@zash.se>
parents:
5195
diff
changeset
|
119 if registration_key then |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
120 -- Tie it to the host if global |
5199
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5198
diff
changeset
|
121 verification_key = hashes.hmac_sha256(registration_key, module.host); |
5459
260a859be86a
mod_http_oauth2: Rename variables to improve clarity
Kim Alvefur <zash@zash.se>
parents:
5458
diff
changeset
|
122 sign_client, verify_client = jwt.init(registration_algo, registration_key, registration_key, registration_options); |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
123 end |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
124 |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
125 local new_device_token, verify_device_token = jwt.init("HS256", random.bytes(32), nil, { default_ttl = 600 }); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
126 |
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
127 -- verify and prepare client structure |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
128 local function check_client(client_id) |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
129 if not verify_client then |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
130 return nil, "client-registration-not-enabled"; |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
131 end |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
132 |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
133 local ok, client = verify_client(client_id); |
5511
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
134 if not ok then |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
135 return ok, client; |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
136 end |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
137 |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
138 client.client_hash = b64url(hashes.sha256(client_id)); |
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
139 return client; |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
140 end |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
141 |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
142 local purpose_map = { ["oauth2-refresh"] = "refresh_token"; ["oauth"] = "access_token" }; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
143 |
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
144 -- scope : string | array | set |
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
145 -- |
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
146 -- at each step, allow the same or a subset of scopes |
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
147 -- (all ( client ( grant ( token ) ) )) |
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
148 -- preserve order since it determines role if more than one granted |
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
149 |
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
150 -- string -> array |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
151 local function parse_scopes(scope_string) |
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
152 return array(scope_string:gmatch("%S+")); |
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
153 end |
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
154 |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
155 local openid_claims = set.new(); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
156 module:add_item("openid-claim", "openid"); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
157 |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
158 module:handle_items("openid-claim", function(event) |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
159 authorization_server_metadata = nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
160 openid_claims:add(event.item); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
161 end, function() |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
162 authorization_server_metadata = nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
163 openid_claims = set.new(module:get_host_items("openid-claim")); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
164 end, true); |
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
165 |
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
166 -- array -> array, array, array |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
167 local function split_scopes(scope_list) |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
168 local claims, roles, unknown = array(), array(), array(); |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
169 local all_roles = usermanager.get_all_roles(module.host); |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
170 for _, scope in ipairs(scope_list) do |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
171 if openid_claims:contains(scope) then |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
172 claims:push(scope); |
5467
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
173 elseif scope == "xmpp" or all_roles[scope] then |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
174 roles:push(scope); |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
175 else |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
176 unknown:push(scope); |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
177 end |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
178 end |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
179 return claims, roles, unknown; |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
180 end |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
181 |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
182 local function can_assume_role(username, requested_role) |
5467
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
183 return requested_role == "xmpp" or usermanager.user_can_assume_role(username, module.host, requested_role); |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
184 end |
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
185 |
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
186 -- function (string) : function(string) : boolean |
5427
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
187 local function role_assumable_by(username) |
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
188 return function(role) |
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
189 return can_assume_role(username, role); |
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
190 end |
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
191 end |
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
192 |
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
193 -- string, array --> array |
5426
f75d95f27da7
mod_http_oauth2: Add function for filtering roles
Kim Alvefur <zash@zash.se>
parents:
5425
diff
changeset
|
194 local function user_assumable_roles(username, requested_roles) |
5427
d69c10327d6d
mod_http_oauth2: More functional functions
Kim Alvefur <zash@zash.se>
parents:
5426
diff
changeset
|
195 return array.filter(requested_roles, role_assumable_by(username)); |
5426
f75d95f27da7
mod_http_oauth2: Add function for filtering roles
Kim Alvefur <zash@zash.se>
parents:
5425
diff
changeset
|
196 end |
f75d95f27da7
mod_http_oauth2: Add function for filtering roles
Kim Alvefur <zash@zash.se>
parents:
5425
diff
changeset
|
197 |
5449
9c19a6b8e542
mod_http_oauth2: Describe type signatures of scope handling functions
Kim Alvefur <zash@zash.se>
parents:
5448
diff
changeset
|
198 -- string, string|nil --> string, string |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
199 local function filter_scopes(username, requested_scope_string) |
5428
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
200 local requested_scopes, requested_roles = split_scopes(parse_scopes(requested_scope_string or "")); |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
201 |
5428
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
202 local granted_roles = user_assumable_roles(username, requested_roles); |
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
203 local granted_scopes = requested_scopes + granted_roles; |
5417
3902082c42c4
mod_http_oauth2: Refactor scope handling into smaller functions
Kim Alvefur <zash@zash.se>
parents:
5416
diff
changeset
|
204 |
5428
07e166b34c4c
mod_http_oauth2: Simplify code with the power of first class functions
Kim Alvefur <zash@zash.se>
parents:
5427
diff
changeset
|
205 local selected_role = granted_roles[1]; |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
206 |
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
207 return granted_scopes:concat(" "), selected_role; |
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
208 end |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
209 |
5213
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
210 local function code_expires_in(code) --> number, seconds until code expires |
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
211 return os.difftime(code.expires, os.time()); |
4669
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4370
diff
changeset
|
212 end |
d3434fd151b5
mod_http_oauth2: Optimize cleanup timer
Kim Alvefur <zash@zash.se>
parents:
4370
diff
changeset
|
213 |
5213
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
214 local function code_expired(code) --> boolean, true: has expired, false: still valid |
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
215 return code_expires_in(code) < 0; |
4269
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4265
diff
changeset
|
216 end |
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4265
diff
changeset
|
217 |
4271
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
218 local codes = cache.new(10000, function (_, code) |
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
219 return code_expired(code) |
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
220 end); |
9623b99bb8d2
mod_http_oauth2: Keep authorization codes in memory instead of storage
Kim Alvefur <zash@zash.se>
parents:
4270
diff
changeset
|
221 |
5618
869c01d91aea
mod_http_oauth2: Clean cache less frequently
Kim Alvefur <zash@zash.se>
parents:
5617
diff
changeset
|
222 -- Clear out unredeemed codes so they don't linger in memory. |
869c01d91aea
mod_http_oauth2: Clean cache less frequently
Kim Alvefur <zash@zash.se>
parents:
5617
diff
changeset
|
223 module:daily("Clear expired authorization codes", function() |
4272
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
224 local k, code = codes:tail(); |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
225 while code and code_expired(code) do |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
226 codes:set(k, nil); |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
227 k, code = codes:tail(); |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
228 end |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
229 end) |
91b951fb3018
mod_http_oauth2: Periodically trim unused authorization codes
Kim Alvefur <zash@zash.se>
parents:
4271
diff
changeset
|
230 |
5207
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
231 local function get_issuer() |
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
232 return (module:http_url(nil, "/"):gsub("/$", "")); |
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
233 end |
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
234 |
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
235 -- Non-standard special redirect URI that has the AS show the authorization |
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
236 -- code to the user for them to copy-paste into the client, which can then |
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
237 -- continue as if it received it via redirect. |
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
238 local oob_uri = "urn:ietf:wg:oauth:2.0:oob"; |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
239 local device_uri = "urn:ietf:params:oauth:grant-type:device_code"; |
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
240 |
5209
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5208
diff
changeset
|
241 local loopbacks = set.new({ "localhost", "127.0.0.1", "::1" }); |
942f8a2f722d
mod_http_oauth2: Allow non-HTTPS on localhost URLs
Matthew Wild <mwild1@gmail.com>
parents:
5208
diff
changeset
|
242 |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
243 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
|
244 return errors.new({ |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
245 type = "modify"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
246 condition = "bad-request"; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
247 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
|
248 text = err_desc and (err_name..": "..err_desc) or err_name; |
4276
ec33b3b1136c
mod_http_oauth2: Fix passing OAuth-specific error details
Kim Alvefur <zash@zash.se>
parents:
4272
diff
changeset
|
249 extra = { oauth2_response = { error = err_name, error_description = err_desc } }; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
250 }); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
251 end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
252 |
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
253 -- client_id / client_metadata are pretty large, filter out a subset of |
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
254 -- properties that are deemed useful e.g. in case tokens issued to a certain |
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
255 -- client needs to be revoked |
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
256 local function client_subset(client) |
5511
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
257 return { |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
258 name = client.client_name; |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
259 uri = client.client_uri; |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
260 id = client.software_id; |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
261 version = client.software_version; |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
262 hash = client.client_hash; |
0860497152af
mod_http_oauth2: Record hash of client_id to allow future verification
Kim Alvefur <zash@zash.se>
parents:
5510
diff
changeset
|
263 }; |
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
264 end |
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
265 |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
266 local function new_access_token(token_jid, role, scope_string, client, id_token, refresh_token_info) |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
267 local token_data = { oauth2_scopes = scope_string, oauth2_client = nil }; |
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
268 if client then |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
269 token_data.oauth2_client = client_subset(client); |
5248
b8b2bf0c1b4b
mod_http_oauth2: Record details of OAuth client a token is issued to
Kim Alvefur <zash@zash.se>
parents:
5247
diff
changeset
|
270 end |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
271 if next(token_data) == nil then |
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
272 token_data = nil; |
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
273 end |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
274 |
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
275 local grant = refresh_token_info and refresh_token_info.grant; |
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
276 if not grant then |
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
277 -- No existing grant, create one |
5646
d67980d9e12d
mod_http_oauth2: Apply refresh token ttl to refresh token instead of grant
Kim Alvefur <zash@zash.se>
parents:
5643
diff
changeset
|
278 grant = tokens.create_grant(token_jid, token_jid, nil, token_data); |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
279 end |
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
280 |
5616
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
281 if refresh_token_info then |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
282 -- out with the old refresh tokens |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
283 local ok, err = tokens.revoke_token(refresh_token_info.token); |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
284 if not ok then |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
285 module:log("error", "Could not revoke refresh token: %s", err); |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
286 return 500; |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
287 end |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
288 end |
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
289 -- in with the new refresh token |
5646
d67980d9e12d
mod_http_oauth2: Apply refresh token ttl to refresh token instead of grant
Kim Alvefur <zash@zash.se>
parents:
5643
diff
changeset
|
290 local refresh_token = refresh_token_info ~= false and tokens.create_token(token_jid, grant.id, nil, default_refresh_ttl, "oauth2-refresh"); |
5616
59d5fc50f602
mod_http_oauth2: Implement refresh token rotation
Kim Alvefur <zash@zash.se>
parents:
5614
diff
changeset
|
291 |
5467
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
292 if role == "xmpp" then |
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
293 -- Special scope meaning the users default role. |
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
294 local user_default_role = usermanager.get_user_role(jid.node(token_jid), module.host); |
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
295 role = user_default_role and user_default_role.name; |
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
296 end |
1c78a97a1091
mod_http_oauth2: Add a special "xmpp" scope that grants the users' default role
Kim Alvefur <zash@zash.se>
parents:
5466
diff
changeset
|
297 |
5451
6705f2a09702
mod_http_oauth2: Reference grant by id instead of value
Kim Alvefur <zash@zash.se>
parents:
5450
diff
changeset
|
298 local access_token, access_token_info = tokens.create_token(token_jid, grant.id, role, default_access_ttl, "oauth2"); |
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
299 |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
300 local expires_at = access_token_info.expires; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
301 return { |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
302 token_type = "bearer"; |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
303 access_token = access_token; |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
304 expires_in = expires_at and (expires_at - os.time()) or nil; |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
305 scope = scope_string; |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
306 id_token = id_token; |
5280
eb482defd9b0
mod_http_oauth2: Update to use new API of Prosody mod_tokenauth @ 601d9a375b86
Matthew Wild <mwild1@gmail.com>
parents:
5279
diff
changeset
|
307 refresh_token = refresh_token or nil; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
308 }; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
309 end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
310 |
5461
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
311 local function normalize_loopback(uri) |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
312 local u = url.parse(uri); |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
313 if u.scheme == "http" and loopbacks:contains(u.host) then |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
314 u.authority = nil; |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
315 u.host = "::1"; |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
316 u.port = nil; |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
317 return url.build(u); |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
318 end |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
319 -- else, not a valid loopback uri |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
320 end |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
321 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
322 local function get_redirect_uri(client, query_redirect_uri) -- record client, string : string |
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
323 if not query_redirect_uri then |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
324 if #client.redirect_uris ~= 1 then |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
325 -- Client registered multiple URIs, it needs specify which one to use |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
326 return; |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
327 end |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
328 -- When only a single URI is registered, that's the default |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
329 return client.redirect_uris[1]; |
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
330 end |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
331 if query_redirect_uri == device_uri and client.grant_types then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
332 for _, grant_type in ipairs(client.grant_types) do |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
333 if grant_type == device_uri then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
334 return query_redirect_uri; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
335 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
336 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
337 -- Tried to use device authorization flow without registering it. |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
338 return; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
339 end |
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
340 -- Verify the client-provided URI matches one previously registered |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
341 for _, redirect_uri in ipairs(client.redirect_uris) do |
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
342 if query_redirect_uri == redirect_uri then |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
343 return redirect_uri |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
344 end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
345 end |
5461
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
346 -- The authorization server MUST allow any port to be specified at the time |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
347 -- of the request for loopback IP redirect URIs, to accommodate clients that |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
348 -- obtain an available ephemeral port from the operating system at the time |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
349 -- of the request. |
5460
c0d62c1b4424
mod_http_oauth2: Add FIXME about loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5459
diff
changeset
|
350 -- https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-08.html#section-8.4.2 |
5461
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
351 local loopback_redirect_uri = normalize_loopback(query_redirect_uri); |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
352 if loopback_redirect_uri then |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
353 for _, redirect_uri in ipairs(client.redirect_uris) do |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
354 if loopback_redirect_uri == normalize_loopback(redirect_uri) then |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
355 return query_redirect_uri; |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
356 end |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
357 end |
06640647d193
mod_http_oauth2: Fix use of arbitrary ports in loopback redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5460
diff
changeset
|
358 end |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
359 end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
360 |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
361 local grant_type_handlers = {}; |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
362 local response_type_handlers = {}; |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
363 local verifier_transforms = {}; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
364 |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
365 function grant_type_handlers.implicit() |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
366 -- Placeholder to make discovery work correctly. |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
367 -- Access tokens are delivered via redirect when using the implict flow, not |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
368 -- via the token endpoint, so how did you get here? |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
369 return oauth_error("invalid_request"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
370 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
371 |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
372 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
|
373 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
|
374 local request_password = assert(params.password, oauth_error("invalid_request", "missing 'password'")); |
3919
8ed261a08a9c
mod_http_oauth2: Allow creation of full JID tokens
Kim Alvefur <zash@zash.se>
parents:
3918
diff
changeset
|
375 local request_username, request_host, request_resource = jid.prepped_split(request_jid); |
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
376 |
3908
8ac5d9933106
mod_http_oauth2: Implement real tokens using mod_authtokens
Matthew Wild <mwild1@gmail.com>
parents:
3903
diff
changeset
|
377 if not (request_username and request_host) or request_host ~= module.host then |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
378 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
|
379 end |
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
380 if not usermanager.test_password(request_username, request_host, request_password) then |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
381 return oauth_error("invalid_grant", "incorrect credentials"); |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
382 end |
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
383 |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
384 local granted_jid = jid.join(request_username, request_host, request_resource); |
5256
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
385 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
386 return json.encode(new_access_token(granted_jid, granted_role, granted_scopes, nil)); |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
387 end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
388 |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
389 function response_type_handlers.code(client, params, granted_jid, id_token) |
5191
f5a58cbe86e4
mod_http_oauth2: Derive scope from correct user details
Kim Alvefur <zash@zash.se>
parents:
5190
diff
changeset
|
390 local request_username, request_host = jid.split(granted_jid); |
5256
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
391 if not request_host or request_host ~= module.host then |
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
392 return oauth_error("invalid_request", "invalid JID"); |
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
393 end |
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
394 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
395 |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
396 if pkce_required and not params.code_challenge then |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
397 return oauth_error("invalid_request", "PKCE required"); |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
398 end |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
399 |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
400 local prefix = "authorization_code:"; |
5243
d5dc8edb2695
mod_http_oauth2: Use more compact IDs
Kim Alvefur <zash@zash.se>
parents:
5242
diff
changeset
|
401 local code = id.medium(); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
402 if params.redirect_uri == device_uri then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
403 local is_device, device_state = verify_device_token(params.state); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
404 if is_device then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
405 -- reconstruct the device_code |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
406 prefix = "device_code:"; |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
407 code = b64url(hashes.hmac_sha256(verification_key, device_state.user_code)); |
5628
9aace51c3637
mod_http_oauth2: Bail on invalid or expired device flow state token
Kim Alvefur <zash@zash.se>
parents:
5626
diff
changeset
|
408 else |
9aace51c3637
mod_http_oauth2: Bail on invalid or expired device flow state token
Kim Alvefur <zash@zash.se>
parents:
5626
diff
changeset
|
409 return oauth_error("invalid_request"); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
410 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
411 end |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
412 local ok = codes:set(prefix.. params.client_id .. "#" .. code, { |
5213
dc0f502c12f1
mod_http_oauth2: Fix authorization code logic
Kim Alvefur <zash@zash.se>
parents:
5210
diff
changeset
|
413 expires = os.time() + 600; |
4340
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
414 granted_jid = granted_jid; |
7cd3b7ec59e9
mod_http_oauth2: Rudimentary support for scopes (but not really)
Matthew Wild <mwild1@gmail.com>
parents:
4276
diff
changeset
|
415 granted_scopes = granted_scopes; |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
416 granted_role = granted_role; |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
417 challenge = params.code_challenge; |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
418 challenge_method = params.code_challenge_method; |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
419 id_token = id_token; |
4670
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4669
diff
changeset
|
420 }); |
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4669
diff
changeset
|
421 if not ok then |
5476
575f52b15f5a
mod_http_oauth2: Return OAuth error for authz code store error
Kim Alvefur <zash@zash.se>
parents:
5475
diff
changeset
|
422 return oauth_error("temporarily_unavailable"); |
4670
1b81b7269858
mod_http_oauth2: Gracefully handle cache write failure
Kim Alvefur <zash@zash.se>
parents:
4669
diff
changeset
|
423 end |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
424 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
425 local redirect_uri = get_redirect_uri(client, params.redirect_uri); |
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
426 if redirect_uri == oob_uri then |
5495
7998b49d6512
mod_http_oauth2: Create proper template for OOB code delivery
Kim Alvefur <zash@zash.se>
parents:
5480
diff
changeset
|
427 return render_page(templates.oob, { client = client; authorization_code = code }, true); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
428 elseif redirect_uri == device_uri then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
429 return render_page(templates.device, { client = client }, true); |
5219
25e824f64fd3
mod_http_oauth2: Improve handling of redirect_uri matching and fallback
Matthew Wild <mwild1@gmail.com>
parents:
5218
diff
changeset
|
430 elseif not redirect_uri then |
5462
f6d8830a83fe
mod_http_oauth2: Return proper OAuth error for invalid redirect URI
Kim Alvefur <zash@zash.se>
parents:
5461
diff
changeset
|
431 return oauth_error("invalid_redirect_uri"); |
5188
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
432 end |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
433 |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
434 local redirect = url.parse(redirect_uri); |
7c531137a553
mod_http_oauth2: Implement OOB special redirect URI in code flow
Kim Alvefur <zash@zash.se>
parents:
5187
diff
changeset
|
435 |
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
436 local query = strict_formdecode(redirect.query); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
437 if type(query) ~= "table" then query = {}; end |
5192
03aa9baa9ac3
mod_http_oauth2: Add support for 'iss' authz response parameter (RFC 9207)
Matthew Wild <mwild1@gmail.com>
parents:
5191
diff
changeset
|
438 table.insert(query, { name = "code", value = code }); |
5207
c72e3b0914e8
mod_http_oauth: Factor out issuer URL calculation to a helper function
Matthew Wild <mwild1@gmail.com>
parents:
5206
diff
changeset
|
439 table.insert(query, { name = "iss", value = get_issuer() }); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
440 if params.state then |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
441 table.insert(query, { name = "state", value = params.state }); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
442 end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
443 redirect.query = http.formencode(query); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
444 |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
445 return { |
5210
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5209
diff
changeset
|
446 status_code = 303; |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
447 headers = { |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
448 cache_control = "no-store"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
449 pragma = "no-cache"; |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
450 location = url.build(redirect); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
451 }; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
452 } |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
453 end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
454 |
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
455 -- Implicit flow |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
456 function response_type_handlers.token(client, params, granted_jid) |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
457 local request_username, request_host = jid.split(granted_jid); |
5256
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
458 if not request_host or request_host ~= module.host then |
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
459 return oauth_error("invalid_request", "invalid JID"); |
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
460 end |
44f7edd4f845
mod_http_oauth2: Reject non-local hosts in more code paths
Kim Alvefur <zash@zash.se>
parents:
5255
diff
changeset
|
461 local granted_scopes, granted_role = filter_scopes(request_username, params.scope); |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
462 local token_info = new_access_token(granted_jid, granted_role, granted_scopes, client, nil); |
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
463 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
464 local redirect = url.parse(get_redirect_uri(client, params.redirect_uri)); |
5463
dacde53467f3
mod_http_oauth2: Proper OAuth error for invalid redirect URI in implicit flow too
Kim Alvefur <zash@zash.se>
parents:
5462
diff
changeset
|
465 if not redirect then return oauth_error("invalid_redirect_uri"); end |
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
466 token_info.state = params.state; |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
467 redirect.fragment = http.formencode(token_info); |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
468 |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
469 return { |
5210
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5209
diff
changeset
|
470 status_code = 303; |
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
471 headers = { |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
472 cache_control = "no-store"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
473 pragma = "no-cache"; |
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
474 location = url.build(redirect); |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
475 }; |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
476 } |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
477 end |
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
478 |
5262
e73f364b5624
mod_http_oauth2: Rename oauth client credential related functions
Kim Alvefur <zash@zash.se>
parents:
5259
diff
changeset
|
479 local function make_client_secret(client_id) --> client_secret |
5199
f48628dc83f1
mod_http_oauth2: Separate client_secret verification key from JWT key
Kim Alvefur <zash@zash.se>
parents:
5198
diff
changeset
|
480 return hashes.hmac_sha256(verification_key, client_id, true); |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
481 end |
4263
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4260
diff
changeset
|
482 |
5262
e73f364b5624
mod_http_oauth2: Rename oauth client credential related functions
Kim Alvefur <zash@zash.se>
parents:
5259
diff
changeset
|
483 local function verify_client_secret(client_id, client_secret) |
e73f364b5624
mod_http_oauth2: Rename oauth client credential related functions
Kim Alvefur <zash@zash.se>
parents:
5259
diff
changeset
|
484 return hashes.equals(make_client_secret(client_id), client_secret); |
4263
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4260
diff
changeset
|
485 end |
d3af5f94d6df
mod_http_oauth2: Improve storage of client secret
Kim Alvefur <zash@zash.se>
parents:
4260
diff
changeset
|
486 |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
487 function grant_type_handlers.authorization_code(params) |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
488 if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
489 if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
490 if not params.code then return oauth_error("invalid_request", "missing 'code'"); end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
491 if params.scope and params.scope ~= "" then |
5450 | 492 -- FIXME allow a subset of granted scopes |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
493 return oauth_error("invalid_scope", "unknown scope requested"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
494 end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
495 |
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
496 local client = check_client(params.client_id); |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
497 if not client then |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
498 return oauth_error("invalid_client", "incorrect credentials"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
499 end |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
500 |
5262
e73f364b5624
mod_http_oauth2: Rename oauth client credential related functions
Kim Alvefur <zash@zash.se>
parents:
5259
diff
changeset
|
501 if not verify_client_secret(params.client_id, params.client_secret) then |
4260
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4259
diff
changeset
|
502 module:log("debug", "client_secret mismatch"); |
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4259
diff
changeset
|
503 return oauth_error("invalid_client", "incorrect credentials"); |
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4259
diff
changeset
|
504 end |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
505 local code, err = codes:get("authorization_code:" .. params.client_id .. "#" .. params.code); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
506 if err then error(err); end |
5214
d5492bc861f6
mod_http_oauth2: Remove authorization codes after use
Kim Alvefur <zash@zash.se>
parents:
5213
diff
changeset
|
507 -- MUST NOT use the authorization code more than once, so remove it to |
d5492bc861f6
mod_http_oauth2: Remove authorization codes after use
Kim Alvefur <zash@zash.se>
parents:
5213
diff
changeset
|
508 -- prevent a second attempted use |
5550
4fda06be6b08
mod_http_oauth2: Make note about handling repeated
Kim Alvefur <zash@zash.se>
parents:
5549
diff
changeset
|
509 -- TODO if a second attempt *is* made, revoke any tokens issued |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
510 codes:set("authorization_code:" .. params.client_id .. "#" .. params.code, nil); |
4269
143515d0b212
mod_http_oauth2: Factor out authorization code validity decision
Kim Alvefur <zash@zash.se>
parents:
4265
diff
changeset
|
511 if not code or type(code) ~= "table" or code_expired(code) then |
4260
c539334dd01a
mod_http_oauth2: Rescope oauth client config into users' storage
Kim Alvefur <zash@zash.se>
parents:
4259
diff
changeset
|
512 module:log("debug", "authorization_code invalid or expired: %q", code); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
513 return oauth_error("invalid_client", "incorrect credentials"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
514 end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
515 |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
516 -- TODO Decide if the code should be removed or not when PKCE fails |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
517 local transform = verifier_transforms[code.challenge_method or "plain"]; |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
518 if not transform then |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
519 return oauth_error("invalid_request", "unknown challenge transform method"); |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
520 elseif transform(params.code_verifier) ~= code.challenge then |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
521 return oauth_error("invalid_grant", "incorrect credentials"); |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
522 end |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
523 |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
524 return json.encode(new_access_token(code.granted_jid, code.granted_role, code.granted_scopes, client, code.id_token)); |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
525 end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
526 |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
527 function grant_type_handlers.refresh_token(params) |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
528 if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
529 if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
530 if not params.refresh_token then return oauth_error("invalid_request", "missing 'refresh_token'"); end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
531 |
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
532 local client = check_client(params.client_id); |
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
533 if not client then |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
534 return oauth_error("invalid_client", "incorrect credentials"); |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
535 end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
536 |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
537 if not verify_client_secret(params.client_id, params.client_secret) then |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
538 module:log("debug", "client_secret mismatch"); |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
539 return oauth_error("invalid_client", "incorrect credentials"); |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
540 end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
541 |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
542 local refresh_token_info = tokens.get_token_info(params.refresh_token); |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
543 if not refresh_token_info or refresh_token_info.purpose ~= "oauth2-refresh" then |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
544 return oauth_error("invalid_grant", "invalid refresh token"); |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
545 end |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
546 |
5512
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
547 local refresh_token_client = refresh_token_info.grant.data.oauth2_client; |
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
548 if not refresh_token_client.hash or refresh_token_client.hash ~= client.client_hash then |
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
549 module:log("warn", "OAuth client %q (%s) tried to use refresh token belonging to %q (%s)", client.client_name, client.client_hash, |
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
550 refresh_token_client.name, refresh_token_client.hash); |
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
551 return oauth_error("unauthorized_client", "incorrect credentials"); |
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
552 end |
1fbc8718bed6
mod_http_oauth2: Bind refresh tokens to client
Kim Alvefur <zash@zash.se>
parents:
5511
diff
changeset
|
553 |
5446
dd7bddc87f98
mod_http_oauth2: Fix inclusion of role in refreshed access tokens
Kim Alvefur <zash@zash.se>
parents:
5445
diff
changeset
|
554 local refresh_scopes = refresh_token_info.grant.data.oauth2_scopes; |
5448
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
555 |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
556 if params.scope then |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
557 local granted_scopes = set.new(parse_scopes(refresh_scopes)); |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
558 local requested_scopes = parse_scopes(params.scope); |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
559 refresh_scopes = array.filter(requested_scopes, function(scope) |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
560 return granted_scopes:contains(scope); |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
561 end):concat(" "); |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
562 end |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
563 |
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
564 local username = jid.split(refresh_token_info.jid); |
5446
dd7bddc87f98
mod_http_oauth2: Fix inclusion of role in refreshed access tokens
Kim Alvefur <zash@zash.se>
parents:
5445
diff
changeset
|
565 local new_scopes, role = filter_scopes(username, refresh_scopes); |
dd7bddc87f98
mod_http_oauth2: Fix inclusion of role in refreshed access tokens
Kim Alvefur <zash@zash.se>
parents:
5445
diff
changeset
|
566 |
5279
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
567 -- new_access_token() requires the actual token |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
568 refresh_token_info.token = params.refresh_token; |
2b858cccac8f
mod_http_oauth2: Add support for refresh tokens
Matthew Wild <mwild1@gmail.com>
parents:
5278
diff
changeset
|
569 |
5448
9d542e86e19a
mod_http_oauth2: Allow requesting a subset of scopes on token refresh
Kim Alvefur <zash@zash.se>
parents:
5447
diff
changeset
|
570 return json.encode(new_access_token(refresh_token_info.jid, role, new_scopes, client, nil, refresh_token_info)); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
571 end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
572 |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
573 grant_type_handlers[device_uri] = function(params) |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
574 if not params.client_id then return oauth_error("invalid_request", "missing 'client_id'"); end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
575 if not params.client_secret then return oauth_error("invalid_request", "missing 'client_secret'"); end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
576 if not params.device_code then return oauth_error("invalid_request", "missing 'device_code'"); end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
577 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
578 local client = check_client(params.client_id); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
579 if not client then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
580 return oauth_error("invalid_client", "incorrect credentials"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
581 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
582 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
583 if not verify_client_secret(params.client_id, params.client_secret) then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
584 module:log("debug", "client_secret mismatch"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
585 return oauth_error("invalid_client", "incorrect credentials"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
586 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
587 |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
588 local code = codes:get("device_code:" .. params.client_id .. "#" .. params.device_code); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
589 if type(code) ~= "table" or code_expired(code) then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
590 return oauth_error("expired_token"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
591 elseif code.error then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
592 return code.error; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
593 elseif not code.granted_jid then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
594 return oauth_error("authorization_pending"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
595 end |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
596 codes:set("device_code:" .. params.client_id .. "#" .. params.device_code, nil); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
597 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
598 return json.encode(new_access_token(code.granted_jid, code.granted_role, code.granted_scopes, client, code.id_token)); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
599 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
600 |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
601 -- RFC 7636 Proof Key for Code Exchange by OAuth Public Clients |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
602 |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
603 function verifier_transforms.plain(code_verifier) |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
604 -- code_challenge = code_verifier |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
605 return code_verifier; |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
606 end |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
607 |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
608 function verifier_transforms.S256(code_verifier) |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
609 -- code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) |
5391
4aedce4fb95d
mod_http_oauth2: Fix accidental uppercase in invocation of hash function
Kim Alvefur <zash@zash.se>
parents:
5390
diff
changeset
|
610 return code_verifier and b64url(hashes.sha256(code_verifier)); |
5383
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
611 end |
df11a2cbc7b7
mod_http_oauth2: Implement RFC 7628 Proof Key for Code Exchange
Kim Alvefur <zash@zash.se>
parents:
5382
diff
changeset
|
612 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
613 -- Used to issue/verify short-lived tokens for the authorization process below |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
614 local new_user_token, verify_user_token = jwt.init("HS256", random.bytes(32), nil, { default_ttl = 600 }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
615 |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
616 -- From the given request, figure out if the user is authenticated and has granted consent yet |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
617 -- As this requires multiple steps (seek credentials, seek consent), we have a lot of state to |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
618 -- carry around across requests. We also need to protect against CSRF and session mix-up attacks |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
619 -- (e.g. the user may have multiple concurrent flows in progress, session cookies aren't unique |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
620 -- to one of them). |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
621 -- Our strategy here is to preserve the original query string (containing the authz request), and |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
622 -- encode the rest of the flow in form POSTs. |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
623 local function get_auth_state(request) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
624 local form = request.method == "POST" |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
625 and request.body |
5276
67777cb7353d
mod_http_oauth2: Pedantic optimization
Kim Alvefur <zash@zash.se>
parents:
5273
diff
changeset
|
626 and request.body ~= "" |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
627 and request.headers.content_type == "application/x-www-form-urlencoded" |
5514
61b8d3eb91a4
mod_http_oauth2: Revert strict form check to allow consent of multiple scopes
Kim Alvefur <zash@zash.se>
parents:
5513
diff
changeset
|
628 and http.formdecode(request.body); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
629 |
5277
a1055024b94e
mod_http_oauth2: Stricten check of urlencoded form data
Kim Alvefur <zash@zash.se>
parents:
5276
diff
changeset
|
630 if type(form) ~= "table" then return {}; end |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
631 |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
632 if not form.user_token then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
633 -- First step: login |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
634 local username = encodings.stringprep.nodeprep(form.username); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
635 local password = encodings.stringprep.saslprep(form.password); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
636 if not (username and password) or not usermanager.test_password(username, module.host, password) then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
637 return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
638 error = "Invalid username/password"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
639 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
640 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
641 return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
642 user = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
643 username = username; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
644 host = module.host; |
5665
bbde136a4c29
mod_http_oauth2: Include 'amr' claim in ID Token
Kim Alvefur <zash@zash.se>
parents:
5646
diff
changeset
|
645 token = new_user_token({ username = username; host = module.host; auth_time = os.time(); amr = { "pwd" } }); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
646 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
647 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
648 elseif form.user_token and form.consent then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
649 -- Second step: consent |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
650 local ok, user = verify_user_token(form.user_token); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
651 if not ok then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
652 return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
653 error = user == "token-expired" and "Session expired - try again" or nil; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
654 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
655 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
656 |
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
657 local scopes = array():append(form):filter(function(field) |
5424
b45d9a81b3da
mod_http_oauth2: Revert role selector, going to try something else
Kim Alvefur <zash@zash.se>
parents:
5423
diff
changeset
|
658 return field.name == "scope"; |
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
659 end):pluck("value"); |
5271
3a1df3adad0c
mod_http_oauth2: Allow user to decide which requested scopes to grant
Kim Alvefur <zash@zash.se>
parents:
5268
diff
changeset
|
660 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
661 user.token = form.user_token; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
662 return { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
663 user = user; |
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
664 scopes = scopes; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
665 consent = form.consent == "granted"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
666 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
667 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
668 |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
669 return {}; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
670 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
671 |
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
672 local function get_request_credentials(request) |
5224
cd5cf4cc6304
mod_http_oauth2: Fail early when no authorization header present
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
673 if not request.headers.authorization then return; end |
cd5cf4cc6304
mod_http_oauth2: Fail early when no authorization header present
Matthew Wild <mwild1@gmail.com>
parents:
5223
diff
changeset
|
674 |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
675 local auth_type, auth_data = string.match(request.headers.authorization, "^(%S+)%s(.+)$"); |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
676 |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
677 if auth_type == "Basic" then |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
678 local creds = base64.decode(auth_data); |
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
679 if not creds then return; end |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
680 local username, password = string.match(creds, "^([^:]+):(.*)$"); |
5222
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
681 if not username then return; end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
682 return { |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
683 type = "basic"; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
684 username = username; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
685 password = password; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
686 }; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
687 elseif auth_type == "Bearer" then |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
688 return { |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
689 type = "bearer"; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
690 bearer_token = auth_data; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
691 }; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
692 end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
693 |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
694 return nil; |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
695 end |
578a72982bb2
mod_http_oauth2: Separate extracting credentials from requests and verifying
Matthew Wild <mwild1@gmail.com>
parents:
5221
diff
changeset
|
696 |
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
697 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:
3919
diff
changeset
|
698 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:
3919
diff
changeset
|
699 |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
700 function grant_type_handlers.password(params) |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
701 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:
3919
diff
changeset
|
702 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:
3919
diff
changeset
|
703 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:
3919
diff
changeset
|
704 if params.scope then |
5450 | 705 -- TODO shouldn't we support scopes / roles here? |
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
706 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:
3919
diff
changeset
|
707 end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
708 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:
3919
diff
changeset
|
709 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:
3919
diff
changeset
|
710 end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
711 if request_password == component_secret then |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
712 local granted_jid = jid.join(request_username, request_host, request_resource); |
5254
b0ccdd12a70d
mod_http_oauth2: Prepare to handle multiple e.g. non-role scopes
Kim Alvefur <zash@zash.se>
parents:
5252
diff
changeset
|
713 return json.encode(new_access_token(granted_jid, nil, nil, nil)); |
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
714 end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
715 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:
3919
diff
changeset
|
716 end |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
717 |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
718 -- TODO How would this make sense with components? |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
719 -- Have an admin authenticate maybe? |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
720 response_type_handlers.code = nil; |
5186
fa3059e653fa
mod_http_oauth2: Implement the Implicit flow
Kim Alvefur <zash@zash.se>
parents:
5185
diff
changeset
|
721 response_type_handlers.token = nil; |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
722 grant_type_handlers.authorization_code = nil; |
3920
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
723 end |
cf92e3b30c18
mod_http_oauth2: Use component_secret setting as password on Components
Kim Alvefur <zash@zash.se>
parents:
3919
diff
changeset
|
724 |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
725 local function render_error(err) |
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
726 return render_page(templates.error, { error = err }); |
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
727 end |
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
728 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
729 -- OAuth errors should be returned to the client if possible, i.e. by |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
730 -- appending the error information to the redirect_uri and sending the |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
731 -- redirect to the user-agent. In some cases we can't do this, e.g. if |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
732 -- the redirect_uri is missing or invalid. In those cases, we render an |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
733 -- error directly to the user-agent. |
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
734 local function error_response(request, redirect_uri, err) |
5478
af105c7a24b2
mod_http_oauth2: Always render errors as HTML for OOB redirect URI
Kim Alvefur <zash@zash.se>
parents:
5477
diff
changeset
|
735 if not redirect_uri or redirect_uri == oob_uri then |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
736 return render_error(err); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
737 end |
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
738 local q = strict_formdecode(request.url.query); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
739 local redirect_query = url.parse(redirect_uri); |
5229
c24a622a7b85
mod_http_oauth2: Fix appending of query parts in error redirects
Kim Alvefur <zash@zash.se>
parents:
5228
diff
changeset
|
740 local sep = redirect_query.query and "&" or "?"; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
741 redirect_uri = redirect_uri |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
742 .. sep .. http.formencode(err.extra.oauth2_response) |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
743 .. "&" .. http.formencode({ state = q.state, iss = get_issuer() }); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
744 module:log("warn", "Sending error response to client via redirect to %s", redirect_uri); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
745 return { |
5210
898575a0c6f3
mod_http_oauth2: Switch to '303 See Other' redirects
Matthew Wild <mwild1@gmail.com>
parents:
5209
diff
changeset
|
746 status_code = 303; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
747 headers = { |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
748 cache_control = "no-store"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
749 pragma = "no-cache"; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
750 location = redirect_uri; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
751 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
752 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
753 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
754 |
5549
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
755 local allowed_grant_type_handlers = module:get_option_set("allowed_oauth2_grant_types", { |
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
756 "authorization_code"; |
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
757 "refresh_token"; |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
758 device_uri; |
5549
01a0b67a9afd
mod_http_oauth2: Add TODO about disabling password grant
Kim Alvefur <zash@zash.se>
parents:
5548
diff
changeset
|
759 }) |
5614
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
760 if allowed_grant_type_handlers:contains("device_code") then |
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
761 -- expand short form because that URI is long |
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
762 module:log("debug", "Expanding %q to %q in '%s'", "device_code", device_uri, "allowed_oauth2_grant_types"); |
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
763 allowed_grant_type_handlers:remove("device_code"); |
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
764 allowed_grant_type_handlers:add(device_uri); |
7565298aa197
mod_http_oauth2: Allow a shorter form of the device grant in config
Kim Alvefur <zash@zash.se>
parents:
5608
diff
changeset
|
765 end |
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
766 for handler_type in pairs(grant_type_handlers) do |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
767 if not allowed_grant_type_handlers:contains(handler_type) then |
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
768 module:log("debug", "Grant type %q disabled", handler_type); |
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
769 grant_type_handlers[handler_type] = nil; |
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
770 else |
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
771 module:log("debug", "Grant type %q enabled", handler_type); |
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
772 end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
773 end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
774 |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
775 -- "token" aka implicit flow is considered insecure |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
776 local allowed_response_type_handlers = module:get_option_set("allowed_oauth2_response_types", {"code"}) |
5198
2e8a7a0f932d
mod_http_oauth2: Fix response type config
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
777 for handler_type in pairs(response_type_handlers) do |
2e8a7a0f932d
mod_http_oauth2: Fix response type config
Kim Alvefur <zash@zash.se>
parents:
5196
diff
changeset
|
778 if not allowed_response_type_handlers:contains(handler_type) then |
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
779 module:log("debug", "Response type %q disabled", handler_type); |
5231
bef543068077
mod_http_oauth2: Fix to disable disabled response handlers correctly
Kim Alvefur <zash@zash.se>
parents:
5230
diff
changeset
|
780 response_type_handlers[handler_type] = nil; |
5230
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
781 else |
ac252db71027
mod_http_oauth2: Log flows enabled and disabled
Kim Alvefur <zash@zash.se>
parents:
5229
diff
changeset
|
782 module:log("debug", "Response type %q enabled", handler_type); |
5187
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
783 end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
784 end |
6a3c1febd7be
mod_http_oauth2: Add settings for allowed grant and response types
Kim Alvefur <zash@zash.se>
parents:
5186
diff
changeset
|
785 |
5716
426c42c11f89
mod_http_oauth2: Make defaults more secure
Kim Alvefur <zash@zash.se>
parents:
5715
diff
changeset
|
786 local allowed_challenge_methods = module:get_option_set("allowed_oauth2_code_challenge_methods", { "S256" }) |
5384
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
787 for handler_type in pairs(verifier_transforms) do |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
788 if not allowed_challenge_methods:contains(handler_type) then |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
789 module:log("debug", "Challenge method %q disabled", handler_type); |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
790 verifier_transforms[handler_type] = nil; |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
791 else |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
792 module:log("debug", "Challenge method %q enabled", handler_type); |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
793 end |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
794 end |
b40f29ec391a
mod_http_oauth2: Allow configuring PKCE challenge methods
Kim Alvefur <zash@zash.se>
parents:
5383
diff
changeset
|
795 |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
796 function handle_token_grant(event) |
5223
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
797 local credentials = get_request_credentials(event.request); |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
798 |
3934
469408682152
mod_http_oauth2: Set content type on successful repsponses (fixes #1501)
Kim Alvefur <zash@zash.se>
parents:
3920
diff
changeset
|
799 event.response.headers.content_type = "application/json"; |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
800 event.response.headers.cache_control = "no-store"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
801 event.response.headers.pragma = "no-cache"; |
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
802 local params = strict_formdecode(event.request.body); |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
803 if not params then |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
804 return oauth_error("invalid_request", "Could not parse request body as 'application/x-www-form-urlencoded'"); |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
805 end |
5223
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
806 |
5225
3439eb37f23b
mod_http_oauth2: token endpoint: handle missing credentials
Matthew Wild <mwild1@gmail.com>
parents:
5224
diff
changeset
|
807 if credentials and credentials.type == "basic" then |
5385
544b92750a2a
mod_http_oauth2: Advertise supported token endpoint auth methods
Kim Alvefur <zash@zash.se>
parents:
5384
diff
changeset
|
808 -- client_secret_basic converted internally to client_secret_post |
5223
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
809 params.client_id = http.urldecode(credentials.username); |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
810 params.client_secret = http.urldecode(credentials.password); |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
811 end |
8b2a36847912
mod_http_oauth2: Support HTTP Basic auth on token endpoint
Matthew Wild <mwild1@gmail.com>
parents:
5222
diff
changeset
|
812 |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
813 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
|
814 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
|
815 if not grant_handler then |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
816 return oauth_error("invalid_request", "No such grant type."); |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
817 end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
818 return grant_handler(params); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
819 end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
820 |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
821 local function handle_authorization_request(event) |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
822 local request = event.request; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
823 |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
824 -- Directly returning errors to the user before we have a validated client object |
4258
cc712899becd
mod_http_oauth2: Unpack event object to improve readability
Kim Alvefur <zash@zash.se>
parents:
4257
diff
changeset
|
825 if not request.url.query then |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
826 return render_error(oauth_error("invalid_request", "Missing query parameters")); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
827 end |
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
828 local params = strict_formdecode(request.url.query); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
829 if not params then |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
830 return render_error(oauth_error("invalid_request", "Invalid query parameters")); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
831 end |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
832 |
5471
d4d333cb75b2
mod_http_oauth2: Clarify some error messages
Kim Alvefur <zash@zash.se>
parents:
5470
diff
changeset
|
833 if not params.client_id then |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
834 return render_error(oauth_error("invalid_request", "Missing 'client_id' parameter")); |
5471
d4d333cb75b2
mod_http_oauth2: Clarify some error messages
Kim Alvefur <zash@zash.se>
parents:
5470
diff
changeset
|
835 end |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
836 |
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
837 local client = check_client(params.client_id); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
838 |
5510
a49d73e4262e
mod_http_oauth2: Add client verification wrapper function
Kim Alvefur <zash@zash.se>
parents:
5509
diff
changeset
|
839 if not client then |
5472
b80b6947b079
mod_http_oauth2: Always show early errors to user
Kim Alvefur <zash@zash.se>
parents:
5471
diff
changeset
|
840 return render_error(oauth_error("invalid_request", "Invalid 'client_id' parameter")); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
841 end |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
842 |
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
843 local redirect_uri = get_redirect_uri(client, params.redirect_uri); |
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
844 if not redirect_uri then |
5475
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
845 return render_error(oauth_error("invalid_request", "Invalid 'redirect_uri' parameter")); |
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
846 end |
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
847 -- From this point we know that redirect_uri is safe to use |
022733437fef
mod_http_oauth2: Validate redirect_uri before using it for error redirects
Kim Alvefur <zash@zash.se>
parents:
5474
diff
changeset
|
848 |
5405
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
849 local client_response_types = set.new(array(client.response_types or { "code" })); |
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
850 client_response_types = set.intersection(client_response_types, allowed_response_type_handlers); |
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
851 if not client_response_types:contains(params.response_type) then |
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
852 return error_response(request, redirect_uri, oauth_error("invalid_client", "'response_type' not allowed")); |
5405
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
853 end |
c7a5caad28ef
mod_http_oauth2: Enforce response type encoded in client_id
Kim Alvefur <zash@zash.se>
parents:
5404
diff
changeset
|
854 |
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
855 local requested_scopes = parse_scopes(params.scope or ""); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
856 if client.scope then |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
857 local client_scopes = set.new(parse_scopes(client.scope)); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
858 requested_scopes:filter(function(scope) |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
859 return client_scopes:contains(scope); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
860 end); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
861 end |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
862 |
5518
d87d0e4a8516
mod_http_oauth2: Validate the OpenID 'prompt' parameter
Kim Alvefur <zash@zash.se>
parents:
5514
diff
changeset
|
863 -- The 'prompt' parameter from OpenID Core |
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
864 local prompt = set.new(parse_scopes(respect_prompt and params.prompt or "select_account login consent")); |
5518
d87d0e4a8516
mod_http_oauth2: Validate the OpenID 'prompt' parameter
Kim Alvefur <zash@zash.se>
parents:
5514
diff
changeset
|
865 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
866 local auth_state = get_auth_state(request); |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
867 if not auth_state.user then |
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
868 if not prompt:contains("login") then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
869 -- Currently no cookies or such are used, so login is required every time. |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
870 return error_response(request, redirect_uri, oauth_error("login_required")); |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
871 end |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
872 |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
873 -- Render login page |
5466
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
874 local extra = {}; |
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
875 if params.login_hint then |
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
876 extra.username_hint = (jid.prepped_split(params.login_hint)); |
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
877 elseif not prompt:contains("select_account") then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
878 -- TODO If the login page is split into account selection followed by login |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
879 -- (e.g. password), and then the account selection could be skipped iff the |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
880 -- 'login_hint' parameter is present. |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
881 return error_response(request, redirect_uri, oauth_error("account_selection_required")); |
5466
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
882 end |
398d936e77fb
mod_http_oauth2: Add support for the OpenID 'login_hint' parameter
Kim Alvefur <zash@zash.se>
parents:
5465
diff
changeset
|
883 return render_page(templates.login, { state = auth_state; client = client; extra = extra }); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
884 elseif auth_state.consent == nil then |
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
885 local scopes, roles = split_scopes(requested_scopes); |
5452
b071d8ee6555
mod_http_oauth2: Show only roles the user can use in consent dialog
Kim Alvefur <zash@zash.se>
parents:
5451
diff
changeset
|
886 roles = user_assumable_roles(auth_state.user.username, roles); |
5715
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
887 |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
888 if not prompt:contains("consent") then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
889 local grants = tokens.get_user_grants(auth_state.user.username); |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
890 local matching_grant; |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
891 if grants then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
892 for grant_id, grant in pairs(grants) do |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
893 if grant.data and grant.data.oauth2_client and grant.data.oauth2_client.hash == client.client_hash then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
894 if set.new(parse_scopes(grant.data.oauth2_scopes)) == set.new(scopes+roles) then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
895 matching_grant = grant_id; |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
896 break |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
897 end |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
898 end |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
899 end |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
900 end |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
901 |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
902 if not matching_grant then |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
903 return error_response(request, redirect_uri, oauth_error("consent_required")); |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
904 else |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
905 -- Consent for these scopes already granted to this exact client, continue |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
906 auth_state.scopes = scopes + roles; |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
907 auth_state.consent = "granted"; |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
908 end |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
909 |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
910 else |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
911 -- Render consent page |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
912 return render_page(templates.consent, { state = auth_state; client = client; scopes = scopes+roles }, true); |
8488ebde5739
mod_http_oauth2: Skip consent screen if requested by client and same scopes already granted
Kim Alvefur <zash@zash.se>
parents:
5682
diff
changeset
|
913 end |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
914 elseif not auth_state.consent then |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
915 -- Notify client of rejection |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
916 if redirect_uri == device_uri then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
917 local is_device, device_state = verify_device_token(params.state); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
918 if is_device then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
919 local device_code = b64url(hashes.hmac_sha256(verification_key, device_state.user_code)); |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
920 local code = codes:get("device_code:" .. params.client_id .. "#" .. device_code); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
921 code.error = oauth_error("access_denied"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
922 code.expires = os.time() + 60; |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
923 codes:set("device_code:" .. params.client_id .. "#" .. device_code, code); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
924 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
925 end |
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
926 return error_response(request, redirect_uri, oauth_error("access_denied")); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
927 end |
5271
3a1df3adad0c
mod_http_oauth2: Allow user to decide which requested scopes to grant
Kim Alvefur <zash@zash.se>
parents:
5268
diff
changeset
|
928 -- else auth_state.consent == true |
3a1df3adad0c
mod_http_oauth2: Allow user to decide which requested scopes to grant
Kim Alvefur <zash@zash.se>
parents:
5268
diff
changeset
|
929 |
5447
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
930 local granted_scopes = auth_state.scopes |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
931 if client.scope then |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
932 local client_scopes = set.new(parse_scopes(client.scope)); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
933 granted_scopes:filter(function(scope) |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
934 return client_scopes:contains(scope); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
935 end); |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
936 end |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
937 |
aa4828f040c5
mod_http_oauth2: Enforce client scope restrictions in authorization
Kim Alvefur <zash@zash.se>
parents:
5446
diff
changeset
|
938 params.scope = granted_scopes:concat(" "); |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
939 |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
940 local user_jid = jid.join(auth_state.user.username, module.host); |
5262
e73f364b5624
mod_http_oauth2: Rename oauth client credential related functions
Kim Alvefur <zash@zash.se>
parents:
5259
diff
changeset
|
941 local client_secret = make_client_secret(params.client_id); |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
942 local id_token_signer = jwt.new_signer("HS256", client_secret); |
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
943 local id_token = id_token_signer({ |
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
944 iss = get_issuer(); |
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
945 sub = url.build({ scheme = "xmpp"; path = user_jid }); |
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
946 aud = params.client_id; |
5519
83ebfc367169
mod_http_oauth2: Return Authentication Time per OpenID Core Section 2
Kim Alvefur <zash@zash.se>
parents:
5518
diff
changeset
|
947 auth_time = auth_state.user.auth_time; |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
948 nonce = params.nonce; |
5665
bbde136a4c29
mod_http_oauth2: Include 'amr' claim in ID Token
Kim Alvefur <zash@zash.se>
parents:
5646
diff
changeset
|
949 amr = auth_state.user.amr; |
5257
b2120fb4a279
mod_http_oauth2: Implement and return ID Token in authorization code flow
Kim Alvefur <zash@zash.se>
parents:
5256
diff
changeset
|
950 }); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
951 local response_type = params.response_type; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
952 local response_handler = response_type_handlers[response_type]; |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
953 if not response_handler then |
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
954 return error_response(request, redirect_uri, oauth_error("unsupported_response_type")); |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
955 end |
5468
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
956 local ret = response_handler(client, params, user_jid, id_token); |
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
957 if errors.is_err(ret) then |
5477
5986e0edd7a3
mod_http_oauth2: Use validated redirect URI when returning errors to client
Kim Alvefur <zash@zash.se>
parents:
5476
diff
changeset
|
958 return error_response(request, redirect_uri, ret); |
5468
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
959 end |
14b5446e22e1
mod_http_oauth2: Fix returning errors from response handlers
Kim Alvefur <zash@zash.se>
parents:
5467
diff
changeset
|
960 return ret; |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
961 end |
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
962 |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
963 local function handle_device_authorization_request(event) |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
964 local request = event.request; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
965 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
966 local credentials = get_request_credentials(request); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
967 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
968 local params = strict_formdecode(request.body); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
969 if not params then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
970 return render_error(oauth_error("invalid_request", "Invalid query parameters")); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
971 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
972 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
973 if credentials and credentials.type == "basic" then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
974 -- client_secret_basic converted internally to client_secret_post |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
975 params.client_id = http.urldecode(credentials.username); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
976 local client_secret = http.urldecode(credentials.password); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
977 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
978 if not verify_client_secret(params.client_id, client_secret) then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
979 module:log("debug", "client_secret mismatch"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
980 return oauth_error("invalid_client", "incorrect credentials"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
981 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
982 else |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
983 return 401; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
984 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
985 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
986 local client = check_client(params.client_id); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
987 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
988 if not client then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
989 return render_error(oauth_error("invalid_request", "Invalid 'client_id' parameter")); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
990 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
991 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
992 if not set.new(client.grant_types):contains(device_uri) then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
993 return render_error(oauth_error("invalid_client", "Client not registered for device authorization grant")); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
994 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
995 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
996 local requested_scopes = parse_scopes(params.scope or ""); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
997 if client.scope then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
998 local client_scopes = set.new(parse_scopes(client.scope)); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
999 requested_scopes:filter(function(scope) |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1000 return client_scopes:contains(scope); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1001 end); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1002 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1003 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1004 -- TODO better code generator, this one should be easy to type from a |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1005 -- screen onto a phone |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1006 local user_code = (id.tiny() .. "-" .. id.tiny()):upper(); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1007 local collisions = 0; |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1008 while codes:get("authorization_code:" .. device_uri .. "#" .. user_code) do |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1009 collisions = collisions + 1; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1010 if collisions > 10 then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1011 return oauth_error("temporarily_unavailable"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1012 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1013 user_code = (id.tiny() .. "-" .. id.tiny()):upper(); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1014 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1015 -- device code should be derivable after consent but not guessable by the user |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1016 local device_code = b64url(hashes.hmac_sha256(verification_key, user_code)); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1017 local verification_uri = module:http_url() .. "/device"; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1018 local verification_uri_complete = verification_uri .. "?" .. http.formencode({ user_code = user_code }); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1019 |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
1020 local expires = os.time() + 600; |
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
1021 local dc_ok = codes:set("device_code:" .. params.client_id .. "#" .. device_code, { expires = expires }); |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1022 local uc_ok = codes:set("user_code:" .. user_code, |
5629
ef0a283507c9
mod_http_oauth2: Make storage of various code more consistent
Kim Alvefur <zash@zash.se>
parents:
5628
diff
changeset
|
1023 { user_code = user_code; expires = expires; client_id = params.client_id; |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1024 scope = requested_scopes:concat(" ") }); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1025 if not dc_ok or not uc_ok then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1026 return oauth_error("temporarily_unavailable"); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1027 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1028 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1029 return { |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1030 headers = { content_type = "application/json"; cache_control = "no-store"; pragma = "no-cache" }; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1031 body = json.encode { |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1032 device_code = device_code; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1033 user_code = user_code; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1034 verification_uri = verification_uri; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1035 verification_uri_complete = verification_uri_complete; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1036 expires_in = 600; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1037 interval = 5; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1038 }; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1039 } |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1040 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1041 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1042 local function handle_device_verification_request(event) |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1043 local request = event.request; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1044 local params = strict_formdecode(request.url.query); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1045 if not params or not params.user_code then |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1046 return render_page(templates.device, { client = false }); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1047 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1048 |
5607
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1049 local device_info = codes:get("user_code:" .. params.user_code); |
ad9b8f659c96
mod_http_oauth2: Namespace the various codes to minimize confusion
Kim Alvefur <zash@zash.se>
parents:
5605
diff
changeset
|
1050 if not device_info or code_expired(device_info) or not codes:set("user_code:" .. params.user_code, nil) then |
5608
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1051 return render_page(templates.device, { |
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1052 client = false; |
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1053 error = oauth_error("expired_token", "Incorrect or expired code"); |
1893ae742f66
mod_http_oauth2: Show errors on device flow user code entry page
Kim Alvefur <zash@zash.se>
parents:
5607
diff
changeset
|
1054 }); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1055 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1056 |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1057 return { |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1058 status_code = 303; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1059 headers = { |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1060 location = module:http_url() .. "/authorize" .. "?" .. http.formencode({ |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1061 client_id = device_info.client_id; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1062 redirect_uri = device_uri; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1063 response_type = "code"; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1064 scope = device_info.scope; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1065 state = new_device_token({ user_code = params.user_code }); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1066 }); |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1067 }; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1068 } |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1069 end |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1070 |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1071 local function handle_introspection_request(event) |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1072 local request = event.request; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1073 local credentials = get_request_credentials(request); |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1074 if not credentials or credentials.type ~= "basic" then |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1075 event.response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1076 return 401; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1077 end |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1078 -- OAuth "client" credentials |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1079 if not verify_client_secret(credentials.username, credentials.password) then |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1080 return 401; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1081 end |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1082 |
5681
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1083 local client = check_client(credentials.username); |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1084 if not client then |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1085 return 401; |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1086 end |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1087 |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1088 local form_data = http.formdecode(request.body or "="); |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1089 local token = form_data.token; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1090 if not token then |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1091 return 400; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1092 end |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1093 |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1094 local token_info = tokens.get_token_info(form_data.token); |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1095 if not token_info then |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1096 return { headers = { content_type = "application/json" }; body = json.encode { active = false } }; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1097 end |
5681
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1098 local token_client = token_info.grant.data.oauth2_client; |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1099 if not token_client or token_client.hash ~= client.client_hash then |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1100 return 403; |
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1101 end |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1102 |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1103 return { |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1104 headers = { content_type = "application/json" }; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1105 body = json.encode { |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1106 active = true; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1107 client_id = credentials.username; -- We don't really know for sure |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1108 username = jid.node(token_info.jid); |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1109 scope = token_info.grant.data.oauth2_scopes; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1110 token_type = purpose_map[token_info.purpose]; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1111 exp = token.expires; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1112 iat = token.created; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1113 sub = url.build({ scheme = "xmpp"; path = token_info.jid }); |
5681
8cb3da7df521
mod_http_oauth2: Restrict introspection to clients own tokens
Kim Alvefur <zash@zash.se>
parents:
5680
diff
changeset
|
1114 aud = credentials.username; |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1115 iss = get_issuer(); |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1116 jti = token_info.id; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1117 }; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1118 }; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1119 end |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1120 |
5682
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1121 -- RFC 7009 says that the authorization server should validate that only the client that a token was issued to should be able to revoke it. However |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1122 -- this would prevent someone who comes across a leaked token from doing the responsible thing and revoking it, so this is not enforced by default. |
5626
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1123 local strict_auth_revoke = module:get_option_boolean("oauth2_require_auth_revoke", false); |
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1124 |
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1125 local function handle_revocation_request(event) |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1126 local request, response = event.request, event.response; |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1127 response.headers.cache_control = "no-store"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1128 response.headers.pragma = "no-cache"; |
5682
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1129 local credentials = get_request_credentials(request); |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1130 if credentials then |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1131 if credentials.type ~= "basic" then |
5265
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1132 response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1133 return 401; |
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1134 end |
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1135 -- OAuth "client" credentials |
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1136 if not verify_client_secret(credentials.username, credentials.password) then |
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1137 return 401; |
f845c218e52c
mod_http_oauth2: Allow revoking a token without OAuth client credentials
Kim Alvefur <zash@zash.se>
parents:
5264
diff
changeset
|
1138 end |
5626
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1139 -- TODO check that it's their token I guess? |
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1140 elseif strict_auth_revoke then |
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1141 -- Why require auth to revoke a leaked token? |
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1142 response.headers.www_authenticate = string.format("Basic realm=%q", module.host.."/"..module.name); |
a44af1b646f5
mod_http_oauth2: Optionally enforce authentication on revocation endpoint
Kim Alvefur <zash@zash.se>
parents:
5619
diff
changeset
|
1143 return 401; |
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1144 end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1145 |
5513
0005d4201030
mod_http_oauth2: Reject duplicate form-urlencoded parameters
Kim Alvefur <zash@zash.se>
parents:
5512
diff
changeset
|
1146 local form_data = strict_formdecode(event.request.body); |
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1147 if not form_data or not form_data.token then |
5267
60e0bc35de33
mod_http_oauth2: Relax payload content type checking in revocation
Kim Alvefur <zash@zash.se>
parents:
5266
diff
changeset
|
1148 response.headers.accept = "application/x-www-form-urlencoded"; |
60e0bc35de33
mod_http_oauth2: Relax payload content type checking in revocation
Kim Alvefur <zash@zash.se>
parents:
5266
diff
changeset
|
1149 return 415; |
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1150 end |
5682
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1151 |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1152 if credentials then |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1153 local client = check_client(credentials.username); |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1154 if not client then |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1155 return 401; |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1156 end |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1157 local token_info = tokens.get_token_info(form_data.token); |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1158 if not token_info then |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1159 return 404; |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1160 end |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1161 local token_client = token_info.grant.data.oauth2_client; |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1162 if not token_client or token_client.hash ~= client.client_hash then |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1163 return 403; |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1164 end |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1165 end |
527c747711f3
mod_http_oauth2: Limit revocation to clients own tokens in strict mode
Kim Alvefur <zash@zash.se>
parents:
5681
diff
changeset
|
1166 |
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1167 local ok, err = tokens.revoke_token(form_data.token); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1168 if not ok then |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1169 module:log("warn", "Unable to revoke token: %s", tostring(err)); |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1170 return 500; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1171 end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1172 return 200; |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1173 end |
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1174 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1175 local registration_schema = { |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1176 title = "OAuth 2.0 Dynamic Client Registration Protocol"; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1177 type = "object"; |
5237
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1178 required = { |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1179 -- These are shown to users in the template |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1180 "client_name"; |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1181 "client_uri"; |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1182 -- We need at least one redirect URI for things to work |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1183 "redirect_uris"; |
3354f943c1fa
mod_http_oauth2: Require URL to client informational page in registration
Kim Alvefur <zash@zash.se>
parents:
5236
diff
changeset
|
1184 }; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1185 properties = { |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1186 redirect_uris = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1187 title = "List of Redirect URIs"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1188 type = "array"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1189 minItems = 1; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1190 uniqueItems = true; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1191 items = { title = "Redirect URI"; type = "string"; format = "uri" }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1192 }; |
5377
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1193 token_endpoint_auth_method = { |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1194 title = "Token Endpoint Authentication Method"; |
5377
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1195 type = "string"; |
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1196 enum = { "none"; "client_secret_post"; "client_secret_basic" }; |
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1197 default = "client_secret_basic"; |
ca477408f90b
mod_http_oauth2: Fix misplaced 'default' on wrong side of } in client registration schema
Kim Alvefur <zash@zash.se>
parents:
5375
diff
changeset
|
1198 }; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1199 grant_types = { |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1200 title = "Grant Types"; |
5236
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5231
diff
changeset
|
1201 type = "array"; |
5455
80a81e7f3c4e
mod_http_oauth2: Require non-empty arrays in client registration
Kim Alvefur <zash@zash.se>
parents:
5454
diff
changeset
|
1202 minItems = 1; |
5456
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1203 uniqueItems = true; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1204 items = { |
5236
ff8623e2f9d9
mod_http_oauth2: Reorder client metadata validation schema
Kim Alvefur <zash@zash.se>
parents:
5231
diff
changeset
|
1205 type = "string"; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1206 enum = { |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1207 "authorization_code"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1208 "implicit"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1209 "password"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1210 "client_credentials"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1211 "refresh_token"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1212 "urn:ietf:params:oauth:grant-type:jwt-bearer"; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1213 "urn:ietf:params:oauth:grant-type:saml2-bearer"; |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1214 device_uri; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1215 }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1216 }; |
5366
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1217 default = { "authorization_code" }; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1218 }; |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1219 application_type = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1220 title = "Application Type"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1221 description = "Determines which kinds of redirect URIs the client may register. \z |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1222 The value 'web' limits the client to https:// URLs with the same hostname as in 'client_uri' \z |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1223 while the value 'native' allows either loopback http:// URLs or application specific URIs."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1224 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1225 enum = { "native"; "web" }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1226 default = "web"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1227 }; |
5456
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1228 response_types = { |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1229 title = "Response Types"; |
5456
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1230 type = "array"; |
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1231 minItems = 1; |
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1232 uniqueItems = true; |
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1233 items = { type = "string"; enum = { "code"; "token" } }; |
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1234 default = { "code" }; |
9008aea491bf
mod_http_oauth2: Reject duplicate list items in client registration
Kim Alvefur <zash@zash.se>
parents:
5455
diff
changeset
|
1235 }; |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1236 client_name = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1237 title = "Client Name"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1238 description = "Human-readable name of the client, presented to the user in the consent dialog."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1239 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1240 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1241 client_uri = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1242 title = "Client URL"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1243 description = "Should be an link to a page with information about the client."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1244 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1245 format = "uri"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1246 pattern = "^https:"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1247 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1248 logo_uri = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1249 title = "Logo URL"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1250 description = "URL to the clients logotype (not currently used)."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1251 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1252 format = "uri"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1253 pattern = "^https:"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1254 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1255 scope = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1256 title = "Scopes"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1257 description = "Space-separated list of scopes the client promises to restrict itself to."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1258 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1259 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1260 contacts = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1261 title = "Contact Addresses"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1262 description = "Addresses, typically email or URLs where the client developers can be contacted."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1263 type = "array"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1264 minItems = 1; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1265 items = { type = "string"; format = "email" }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1266 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1267 tos_uri = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1268 title = "Terms of Service URL"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1269 description = "Link to Terms of Service for the client, presented to the user in the consent dialog. \z |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1270 MUST be a https:// URL with hostname matching that of 'client_uri'."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1271 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1272 format = "uri"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1273 pattern = "^https:"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1274 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1275 policy_uri = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1276 title = "Privacy Policy URL"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1277 description = "Link to a Privacy Policy for the client. MUST be a https:// URL with hostname matching that of 'client_uri'."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1278 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1279 format = "uri"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1280 pattern = "^https:"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1281 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1282 software_id = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1283 title = "Software ID"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1284 description = "Unique identifier for the client software, common for all instances. Typically an UUID."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1285 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1286 format = "uuid"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1287 }; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1288 software_version = { |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1289 title = "Software Version"; |
5605
17aa3bac7f3a
mod_http_oauth2: Improve a description in schema
Kim Alvefur <zash@zash.se>
parents:
5598
diff
changeset
|
1290 description = "Version of the client software being registered. \z |
5598
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1291 E.g. to allow revoking all related tokens in the event of a security incident."; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1292 type = "string"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1293 example = "2.3.1"; |
b496ebc12aed
mod_http_oauth2: Add titles and descriptions to registration schema
Kim Alvefur <zash@zash.se>
parents:
5589
diff
changeset
|
1294 }; |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1295 }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1296 } |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1297 |
5554
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1298 -- Limit per-locale fields to allowed locales, partly to keep size of client_id |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1299 -- down, partly because we don't yet use them for anything. |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1300 -- Only relevant for user-visible strings and URIs. |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1301 if allowed_locales[1] then |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1302 local props = registration_schema.properties; |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1303 for _, locale in ipairs(allowed_locales) do |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1304 props["client_name#" .. locale] = props["client_name"]; |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1305 props["client_uri#" .. locale] = props["client_uri"]; |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1306 props["logo_uri#" .. locale] = props["logo_uri"]; |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1307 props["tos_uri#" .. locale] = props["tos_uri"]; |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1308 props["policy_uri#" .. locale] = props["policy_uri"]; |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1309 end |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1310 end |
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1311 |
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1312 local function redirect_uri_allowed(redirect_uri, client_uri, app_type) |
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1313 local uri = url.parse(redirect_uri); |
5457
9156a4754466
mod_http_oauth2: Reject relative redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5456
diff
changeset
|
1314 if not uri.scheme then |
9156a4754466
mod_http_oauth2: Reject relative redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5456
diff
changeset
|
1315 return false; -- no relative URLs |
9156a4754466
mod_http_oauth2: Reject relative redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5456
diff
changeset
|
1316 end |
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1317 if app_type == "native" then |
5458
813fe4f76286
mod_http_oauth2: Do minimal validation of private-use URI schemes
Kim Alvefur <zash@zash.se>
parents:
5457
diff
changeset
|
1318 return uri.scheme == "http" and loopbacks:contains(uri.host) or redirect_uri == oob_uri or uri.scheme:find(".", 1, true) ~= nil; |
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1319 elseif app_type == "web" then |
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1320 return uri.scheme == "https" and uri.host == client_uri.host; |
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1321 end |
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1322 end |
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1323 |
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1324 function create_client(client_metadata) |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1325 if not schema.validate(registration_schema, client_metadata) then |
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1326 return nil, oauth_error("invalid_request", "Failed schema validation."); |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1327 end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1328 |
5633
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1329 local client_uri = url.parse(client_metadata.client_uri); |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1330 if not client_uri or client_uri.scheme ~= "https" or loopbacks:contains(client_uri.host) then |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1331 return nil, oauth_error("invalid_client_metadata", "Missing, invalid or insecure client_uri"); |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1332 end |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1333 |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1334 if not client_metadata.application_type and redirect_uri_allowed(client_metadata.redirect_uris[1], client_uri, "native") then |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1335 client_metadata.application_type = "native"; |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1336 -- else defaults to "web" |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1337 end |
dd2079b3dec6
mod_http_oauth2: Allow omitting application type for native apps
Kim Alvefur <zash@zash.se>
parents:
5629
diff
changeset
|
1338 |
5366
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1339 -- Fill in default values |
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1340 for propname, propspec in pairs(registration_schema.properties) do |
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1341 if client_metadata[propname] == nil and type(propspec) == "table" and propspec.default ~= nil then |
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1342 client_metadata[propname] = propspec.default; |
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1343 end |
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1344 end |
db4c66a1d24b
mod_http_oauth2: Fill in some client metadata defaults
Kim Alvefur <zash@zash.se>
parents:
5365
diff
changeset
|
1345 |
5559
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1346 -- MUST ignore any metadata that it does not understand |
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1347 for propname in pairs(client_metadata) do |
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1348 if not registration_schema.properties[propname] then |
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1349 client_metadata[propname] = nil; |
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1350 end |
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1351 end |
d7fb8b266663
mod_http_oauth2: Strip unknown client metadata
Kim Alvefur <zash@zash.se>
parents:
5554
diff
changeset
|
1352 |
5239
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1353 for _, redirect_uri in ipairs(client_metadata.redirect_uris) do |
5367
93d445b26063
mod_http_oauth2: Validate redirect URI depending on application type
Kim Alvefur <zash@zash.se>
parents:
5366
diff
changeset
|
1354 if not redirect_uri_allowed(redirect_uri, client_uri, client_metadata.application_type) then |
5402
fbf3ede7541b
mod_http_oauth2: More appropriate error conditions in client validation
Kim Alvefur <zash@zash.se>
parents:
5401
diff
changeset
|
1355 return nil, oauth_error("invalid_redirect_uri", "Invalid, insecure or inappropriate redirect URI."); |
5242
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1356 end |
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1357 end |
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1358 |
5244
fa7bd721a3f6
mod_http_oauth2: Fix validation of informative URIs
Kim Alvefur <zash@zash.se>
parents:
5243
diff
changeset
|
1359 for field, prop_schema in pairs(registration_schema.properties) do |
5246
fd0d25b42cd9
mod_http_oauth2: Validate all URIs against client_uri in client registration
Kim Alvefur <zash@zash.se>
parents:
5245
diff
changeset
|
1360 if field ~= "client_uri" and prop_schema.format == "uri" and client_metadata[field] then |
5403
c574aaaa4d57
mod_http_oauth2: Simplify validation of various URIs
Kim Alvefur <zash@zash.se>
parents:
5402
diff
changeset
|
1361 if not redirect_uri_allowed(client_metadata[field], client_uri, "web") then |
c574aaaa4d57
mod_http_oauth2: Simplify validation of various URIs
Kim Alvefur <zash@zash.se>
parents:
5402
diff
changeset
|
1362 return nil, oauth_error("invalid_client_metadata", "Invalid, insecure or inappropriate informative URI"); |
5242
4746609a6656
mod_http_oauth2: Validate that informative URLs match the redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5241
diff
changeset
|
1363 end |
5239
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1364 end |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1365 end |
8620a635106e
mod_http_oauth2: Validate basic URI syntax of redirect URIs
Kim Alvefur <zash@zash.se>
parents:
5237
diff
changeset
|
1366 |
5406
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1367 local grant_types = set.new(client_metadata.grant_types); |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1368 local response_types = set.new(client_metadata.response_types); |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1369 |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1370 if grant_types:contains("authorization_code") and not response_types:contains("code") then |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1371 return nil, oauth_error("invalid_client_metadata", "Inconsistency between 'grant_types' and 'response_types'"); |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1372 elseif grant_types:contains("implicit") and not response_types:contains("token") then |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1373 return nil, oauth_error("invalid_client_metadata", "Inconsistency between 'grant_types' and 'response_types'"); |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1374 end |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1375 |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1376 if set.intersection(grant_types, allowed_grant_type_handlers):empty() then |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1377 return nil, oauth_error("invalid_client_metadata", "No allowed 'grant_types' specified"); |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1378 elseif set.intersection(response_types, allowed_response_type_handlers):empty() then |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1379 return nil, oauth_error("invalid_client_metadata", "No allowed 'response_types' specified"); |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1380 end |
b86d80e21c60
mod_http_oauth2: Validate consistency of response and grant types
Kim Alvefur <zash@zash.se>
parents:
5405
diff
changeset
|
1381 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1382 -- Do we want to keep everything? |
5459
260a859be86a
mod_http_oauth2: Rename variables to improve clarity
Kim Alvefur <zash@zash.se>
parents:
5458
diff
changeset
|
1383 local client_id = sign_client(client_metadata); |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1384 |
5221
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5219
diff
changeset
|
1385 client_metadata.client_id = client_id; |
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5219
diff
changeset
|
1386 client_metadata.client_id_issued_at = os.time(); |
22483cfce3ce
mod_http_oauth2: Reflect ALL attributes of the client registration
Matthew Wild <mwild1@gmail.com>
parents:
5219
diff
changeset
|
1387 |
5407
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1388 if client_metadata.token_endpoint_auth_method ~= "none" then |
5580
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1389 -- Ensure that each client_id JWT with a client_secret is unique. |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1390 -- A short ID along with the issued at timestamp should be sufficient to |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1391 -- rule out brute force attacks. |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1392 -- Not needed for public clients without a secret, but those are expected |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1393 -- to be uncommon since they can only do the insecure implicit flow. |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1394 client_metadata.nonce = id.short(); |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1395 |
feadbd481285
mod_http_oauth2: Only add nonce when issuing a client_secret
Kim Alvefur <zash@zash.se>
parents:
5560
diff
changeset
|
1396 local client_secret = make_client_secret(client_id, client_metadata); |
5407
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1397 client_metadata.client_secret = client_secret; |
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1398 client_metadata.client_secret_expires_at = 0; |
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1399 |
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1400 if not registration_options.accept_expired then |
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1401 client_metadata.client_secret_expires_at = client_metadata.client_id_issued_at + (registration_options.default_ttl or 3600); |
149634647b48
mod_http_oauth2: Don't issue client_secret when not using authentication
Kim Alvefur <zash@zash.se>
parents:
5406
diff
changeset
|
1402 end |
5202
b81fd0d22c66
mod_http_oauth2: Calculate client secret expiry in registration response
Kim Alvefur <zash@zash.se>
parents:
5201
diff
changeset
|
1403 end |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1404 |
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1405 return client_metadata; |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1406 end |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1407 |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1408 local function handle_register_request(event) |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1409 local request = event.request; |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1410 local client_metadata, err = json.decode(request.body); |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1411 if err then |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1412 return oauth_error("invalid_request", "Invalid JSON"); |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1413 end |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1414 |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1415 local response, err = create_client(client_metadata); |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1416 if err then return err end |
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1417 |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1418 return { |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1419 status_code = 201; |
5509
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1420 headers = { |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1421 cache_control = "no-store"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1422 pragma = "no-cache"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1423 content_type = "application/json"; |
ae007be8a6bd
mod_http_oauth2: Add Cache-Control and Pragma headers per by RFC 6749
Kim Alvefur <zash@zash.se>
parents:
5502
diff
changeset
|
1424 }; |
5259
8fba651b10ef
mod_http_oauth2: Refactor to allow reuse of OAuth client creation
Kim Alvefur <zash@zash.se>
parents:
5258
diff
changeset
|
1425 body = json.encode(response); |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1426 }; |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1427 end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1428 |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1429 if not registration_key then |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1430 module:log("info", "No 'oauth2_registration_key', dynamic client registration disabled") |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1431 handle_authorization_request = nil |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1432 handle_register_request = nil |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1433 handle_device_authorization_request = nil |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1434 handle_device_verification_request = nil |
5193
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1435 end |
2bb29ece216b
mod_http_oauth2: Implement stateless dynamic client registration
Kim Alvefur <zash@zash.se>
parents:
5192
diff
changeset
|
1436 |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1437 local function handle_userinfo_request(event) |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1438 local request = event.request; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1439 local credentials = get_request_credentials(request); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1440 if not credentials or not credentials.bearer_token then |
5336
77ac04bd2f65
mod_http_oauth2: Add some debug logging for UserInfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5335
diff
changeset
|
1441 module:log("debug", "Missing credentials for UserInfo endpoint: %q", credentials) |
5335
53c6f49dcbb8
mod_http_oauth2: Correct error code when missing credentials for userinfo
Kim Alvefur <zash@zash.se>
parents:
5280
diff
changeset
|
1442 return 401; |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1443 end |
5336
77ac04bd2f65
mod_http_oauth2: Add some debug logging for UserInfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5335
diff
changeset
|
1444 local token_info,err = tokens.get_token_info(credentials.bearer_token); |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1445 if not token_info then |
5336
77ac04bd2f65
mod_http_oauth2: Add some debug logging for UserInfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5335
diff
changeset
|
1446 module:log("debug", "UserInfo query failed token validation: %s", err) |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1447 return 403; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1448 end |
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1449 local scopes = set.new() |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1450 if type(token_info.grant.data) == "table" and type(token_info.grant.data.oauth2_scopes) == "string" then |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1451 scopes:add_list(parse_scopes(token_info.grant.data.oauth2_scopes)); |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1452 else |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1453 module:log("debug", "token_info = %q", token_info) |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1454 end |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1455 |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1456 if not scopes:contains("openid") then |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1457 module:log("debug", "Missing the 'openid' scope in %q", scopes) |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1458 -- The 'openid' scope is required for access to this endpoint. |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1459 return 403; |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1460 end |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1461 |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1462 local user_info = { |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1463 iss = get_issuer(); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1464 sub = url.build({ scheme = "xmpp"; path = token_info.jid }); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1465 } |
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1466 |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1467 local token_claims = set.intersection(openid_claims, scopes); |
5375
8b7d97f0ae8a
mod_http_oauth2: Fix to include "openid" scope in discovery metadata
Kim Alvefur <zash@zash.se>
parents:
5367
diff
changeset
|
1468 token_claims:remove("openid"); -- that's "iss" and "sub" above |
5337
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1469 if not token_claims:empty() then |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1470 -- Another module can do that |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1471 module:fire_event("token/userinfo", { |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1472 token = token_info; |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1473 claims = token_claims; |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1474 username = jid.split(token_info.jid); |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1475 userinfo = user_info; |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1476 }); |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1477 end |
8d8e85d6dc91
mod_http_oauth2: Support OpenID UserInfo claims
Kim Alvefur <zash@zash.se>
parents:
5336
diff
changeset
|
1478 |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1479 return { |
5258
9629971e307f
mod_http_oauth2: Fix userinfo status code off-by-one
Kim Alvefur <zash@zash.se>
parents:
5257
diff
changeset
|
1480 status_code = 200; |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1481 headers = { content_type = "application/json" }; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1482 body = json.encode(user_info); |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1483 }; |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1484 end |
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1485 |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1486 module:depends("http"); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1487 module:provides("http", { |
5480
5108f63e762b
mod_http_oauth2: Allow CORS for browser clients
Kim Alvefur <zash@zash.se>
parents:
5479
diff
changeset
|
1488 cors = { enabled = true; credentials = true }; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1489 route = { |
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1490 -- OAuth 2.0 in 5 simple steps! |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1491 -- This is the normal 'authorization_code' flow. |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1492 |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1493 -- Step 1. Create OAuth client |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1494 ["POST /register"] = handle_register_request; |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1495 |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1496 -- Device flow |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1497 ["POST /device"] = handle_device_authorization_request; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1498 ["GET /device"] = handle_device_verification_request; |
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1499 |
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1500 -- Step 2. User-facing login and consent view |
4256
c4b9d4ba839b
mod_http_oauth2: Authorization code flow
Kim Alvefur <zash@zash.se>
parents:
4237
diff
changeset
|
1501 ["GET /authorize"] = handle_authorization_request; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1502 ["POST /authorize"] = handle_authorization_request; |
5548
fd3c12c40cd9
mod_http_oauth2: Disable CORS for authorization endpoint
Kim Alvefur <zash@zash.se>
parents:
5547
diff
changeset
|
1503 ["OPTIONS /authorize"] = { status_code = 403; body = "" }; |
5245
e22cae58141d
mod_http_oauth2: Organize HTTP routes with comments
Kim Alvefur <zash@zash.se>
parents:
5244
diff
changeset
|
1504 |
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1505 -- Step 3. User is redirected to the 'redirect_uri' along with an |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1506 -- authorization code. In the insecure 'implicit' flow, the access token |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1507 -- is delivered here. |
5245
e22cae58141d
mod_http_oauth2: Organize HTTP routes with comments
Kim Alvefur <zash@zash.se>
parents:
5244
diff
changeset
|
1508 |
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1509 -- Step 4. Retrieve access token using the code. |
5245
e22cae58141d
mod_http_oauth2: Organize HTTP routes with comments
Kim Alvefur <zash@zash.se>
parents:
5244
diff
changeset
|
1510 ["POST /token"] = handle_token_grant; |
5382
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1511 |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1512 -- Step 4 is later repeated using the refresh token to get new access tokens. |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1513 |
12498c0d705f
mod_http_oauth2: Reorder routes into order they happen in OAuth 2.0
Kim Alvefur <zash@zash.se>
parents:
5378
diff
changeset
|
1514 -- Step 5. Revoke token (access or refresh) |
4370
dee6b5098278
mod_http_oauth2: Add endpoint to revoke a key (RFC 7009 kinda)
Matthew Wild <mwild1@gmail.com>
parents:
4340
diff
changeset
|
1515 ["POST /revoke"] = handle_revocation_request; |
5245
e22cae58141d
mod_http_oauth2: Organize HTTP routes with comments
Kim Alvefur <zash@zash.se>
parents:
5244
diff
changeset
|
1516 |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1517 -- Get info about a token |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1518 ["POST /introspect"] = handle_introspection_request; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1519 |
5245
e22cae58141d
mod_http_oauth2: Organize HTTP routes with comments
Kim Alvefur <zash@zash.se>
parents:
5244
diff
changeset
|
1520 -- OpenID |
5228
77cd01af06a9
mod_http_oauth2: Implement the OpenID userinfo endpoint
Kim Alvefur <zash@zash.se>
parents:
5225
diff
changeset
|
1521 ["GET /userinfo"] = handle_userinfo_request; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1522 |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1523 -- Optional static content for templates |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1524 ["GET /style.css"] = templates.css and { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1525 headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1526 ["Content-Type"] = "text/css"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1527 }; |
5642
7c105277a9ca
mod_http_oauth2: Remove broken in-CSS templating
Kim Alvefur <zash@zash.se>
parents:
5633
diff
changeset
|
1528 body = templates.css; |
5208
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1529 } or nil; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1530 ["GET /script.js"] = templates.js and { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1531 headers = { |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1532 ["Content-Type"] = "text/javascript"; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1533 }; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1534 body = templates.js; |
aaa64c647e12
mod_http_oauth2: Add authentication, consent and error pages
Matthew Wild <mwild1@gmail.com>
parents:
5207
diff
changeset
|
1535 } or nil; |
5393
9b9d612f9083
mod_http_oauth2: Add way to retrieve registration schema
Kim Alvefur <zash@zash.se>
parents:
5392
diff
changeset
|
1536 |
9b9d612f9083
mod_http_oauth2: Add way to retrieve registration schema
Kim Alvefur <zash@zash.se>
parents:
5392
diff
changeset
|
1537 -- Some convenient fallback handlers |
9b9d612f9083
mod_http_oauth2: Add way to retrieve registration schema
Kim Alvefur <zash@zash.se>
parents:
5392
diff
changeset
|
1538 ["GET /register"] = { headers = { content_type = "application/schema+json" }; body = json.encode(registration_schema) }; |
5396
ac7c5669e5f5
mod_http_oauth2: Return status 405 for GET to endpoints without GET handler
Kim Alvefur <zash@zash.se>
parents:
5394
diff
changeset
|
1539 ["GET /token"] = function() return 405; end; |
ac7c5669e5f5
mod_http_oauth2: Return status 405 for GET to endpoints without GET handler
Kim Alvefur <zash@zash.se>
parents:
5394
diff
changeset
|
1540 ["GET /revoke"] = function() return 405; end; |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1541 ["GET /introspect"] = function() return 405; end; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1542 }; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1543 }); |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1544 |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1545 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
|
1546 |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1547 module:hook_object_event(http_server, "http-error", function (event) |
4276
ec33b3b1136c
mod_http_oauth2: Fix passing OAuth-specific error details
Kim Alvefur <zash@zash.se>
parents:
4272
diff
changeset
|
1548 local oauth2_response = event.error and event.error.extra and event.error.extra.oauth2_response; |
3903
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1549 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
|
1550 return; |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1551 end |
cfeb93b80621
mod_http_oauth2: OAuth2 API (work in progress for developers only)
Matthew Wild <mwild1@gmail.com>
parents:
diff
changeset
|
1552 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
|
1553 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
|
1554 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
|
1555 end, 5); |
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1556 |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1557 -- OIDC Discovery |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1558 |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1559 function get_authorization_server_metadata() |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1560 if authorization_server_metadata then |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1561 return authorization_server_metadata; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1562 end |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1563 authorization_server_metadata = { |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1564 -- RFC 8414: OAuth 2.0 Authorization Server Metadata |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1565 issuer = get_issuer(); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1566 authorization_endpoint = handle_authorization_request and module:http_url() .. "/authorize" or nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1567 token_endpoint = handle_token_grant and module:http_url() .. "/token" or nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1568 registration_endpoint = handle_register_request and module:http_url() .. "/register" or nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1569 scopes_supported = usermanager.get_all_roles |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1570 and array(it.keys(usermanager.get_all_roles(module.host))):push("xmpp"):append(array(openid_claims:items())); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1571 response_types_supported = array(it.keys(response_type_handlers)); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1572 token_endpoint_auth_methods_supported = array({ "client_secret_post"; "client_secret_basic" }); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1573 op_policy_uri = module:get_option_string("oauth2_policy_url", nil); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1574 op_tos_uri = module:get_option_string("oauth2_terms_url", nil); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1575 revocation_endpoint = handle_revocation_request and module:http_url() .. "/revoke" or nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1576 revocation_endpoint_auth_methods_supported = array({ "client_secret_basic" }); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1577 device_authorization_endpoint = handle_device_authorization_request and module:http_url() .. "/device"; |
5680
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1578 introspection_endpoint = handle_introspection_request and module:http_url() .. "/introspect"; |
b43c989fb69c
mod_http_oauth2: Implement introspection endpoint
Kim Alvefur <zash@zash.se>
parents:
5665
diff
changeset
|
1579 introspection_endpoint_auth_methods_supported = nil; |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1580 code_challenge_methods_supported = array(it.keys(verifier_transforms)); |
5589
7040d0772758
mod_http_oauth2: Implement RFC 8628 Device Authorization Grant
Kim Alvefur <zash@zash.se>
parents:
5580
diff
changeset
|
1581 grant_types_supported = array(it.keys(grant_type_handlers)); |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1582 response_modes_supported = array(it.keys(response_type_handlers)):map(tmap { token = "fragment"; code = "query" }); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1583 authorization_response_iss_parameter_supported = true; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1584 service_documentation = module:get_option_string("oauth2_service_documentation", "https://modules.prosody.im/mod_http_oauth2.html"); |
5554
90449babaa48
mod_http_oauth2: Make allowed locales configurable
Kim Alvefur <zash@zash.se>
parents:
5553
diff
changeset
|
1585 ui_locales_supported = allowed_locales[1] and allowed_locales; |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1586 |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1587 -- OpenID |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1588 userinfo_endpoint = handle_register_request and module:http_url() .. "/userinfo" or nil; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1589 jwks_uri = nil; -- REQUIRED in OpenID Discovery but not in OAuth 2.0 Metadata |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1590 id_token_signing_alg_values_supported = { "HS256" }; -- The algorithm RS256 MUST be included, but we use HS256 and client_secret as shared key. |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1591 } |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1592 return authorization_server_metadata; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1593 end |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1594 |
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1595 module:provides("http", { |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1596 name = "oauth2-discovery"; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1597 default_path = "/.well-known/oauth-authorization-server"; |
5480
5108f63e762b
mod_http_oauth2: Allow CORS for browser clients
Kim Alvefur <zash@zash.se>
parents:
5479
diff
changeset
|
1598 cors = { enabled = true }; |
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1599 route = { |
5502
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1600 ["GET"] = function() |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1601 return { |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1602 headers = { content_type = "application/json" }; |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1603 body = json.encode(get_authorization_server_metadata()); |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1604 } |
fd4d89a5b8db
mod_http_oauth2: Add provisions for dynamically adding simple scopes
Kim Alvefur <zash@zash.se>
parents:
5501
diff
changeset
|
1605 end |
5189
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1606 }; |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1607 }); |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1608 |
4ee8eb1134a8
mod_http_oauth2: Add OIDC discovery endpoint (thanks Zash)
Matthew Wild <mwild1@gmail.com>
parents:
5188
diff
changeset
|
1609 module:shared("tokenauth/oauthbearer_config").oidc_discovery_url = module:http_url("oauth2-discovery", "/.well-known/oauth-authorization-server"); |