| rev |
line source |
|
bsw/jbe@1309
|
1 if not request.is_post() then
|
|
bsw/jbe@1309
|
2 return execute.view { module = "index", view = "405" }
|
|
bsw/jbe@1309
|
3 end
|
|
bsw/jbe@1309
|
4
|
|
bsw/jbe@1309
|
5 slot.set_layout(nil, "application/json;charset=UTF-8")
|
|
bsw/jbe@1309
|
6
|
|
bsw/jbe@1309
|
7 local r = json.object()
|
|
bsw/jbe@1309
|
8
|
|
bsw/jbe@1309
|
9 local function error_result(error_code, error_description)
|
|
bsw/jbe@1309
|
10 -- TODO special HTTP status codes for some errors?
|
|
bsw/jbe@1309
|
11 request.set_status("400 Bad Request")
|
|
bsw/jbe@1309
|
12 slot.put_into("data", json.export{
|
|
bsw/jbe@1309
|
13 error = error_code,
|
|
bsw/jbe@1309
|
14 error_description = error_description
|
|
bsw/jbe@1309
|
15 })
|
|
bsw/jbe@1309
|
16 end
|
|
bsw/jbe@1309
|
17
|
|
bsw/jbe@1309
|
18 local client_id = param.get("client_id")
|
|
bsw/jbe@1309
|
19 local flow = param.get("flow")
|
|
bsw/jbe@1309
|
20 local scope = param.get("scope")
|
|
bsw/jbe@1309
|
21
|
|
bsw/jbe@1309
|
22 if flow ~= "code" and flow ~= "token" then
|
|
bsw/jbe@1309
|
23 return error_result("invalid_request", "invalid flow")
|
|
bsw/jbe@1309
|
24 end
|
|
bsw/jbe@1309
|
25
|
|
bsw/jbe@1309
|
26 local domain
|
|
bsw/jbe@1309
|
27
|
|
bsw/jbe@1309
|
28 if client_id then
|
|
bsw/jbe@1309
|
29 domain = string.match(client_id, "^dynamic:([a-z0-9.-]+)$")
|
|
bsw/jbe@1309
|
30 if not domain then
|
|
bsw/jbe@1309
|
31 return error_result("invalid_client", "invalid client_id (use lower case host name prefixed with 'dynamic:')")
|
|
bsw/jbe@1309
|
32 end
|
|
bsw/jbe@1309
|
33 end
|
|
bsw/jbe@1309
|
34
|
|
bsw/jbe@1309
|
35 local cert_ca = request.get_header("X-LiquidFeedback-CA")
|
|
bsw/jbe@1309
|
36 local cert_distinguished_name = request.get_header("X-SSL-DN")
|
|
bsw/jbe@1309
|
37 local cert_common_name
|
|
bsw/jbe@1309
|
38
|
|
bsw/jbe@1309
|
39 if cert_distinguished_name then
|
|
bsw/jbe@1309
|
40 cert_common_name = string.match(cert_distinguished_name, "%f[^/\0]CN=([A-Za-z0-9_.-]+)%f[/\0]")
|
|
bsw/jbe@1309
|
41 if not cert_common_name then
|
|
bsw/jbe@1309
|
42 return error_result("invalid_client", "CN in X.509 certificate invalid")
|
|
bsw/jbe@1309
|
43 end
|
|
bsw/jbe@1309
|
44 else
|
|
bsw/jbe@1309
|
45 return error_result("invalid_client", "X.509 client authorization missing")
|
|
bsw/jbe@1309
|
46 end
|
|
bsw/jbe@1309
|
47
|
|
bsw/jbe@1309
|
48 if cert_ca ~= "public" then
|
|
bsw/jbe@1309
|
49 return error_result("invalid_client", "X.509 certificate not signed by publicly trusted certificate authority or wrong endpoint used")
|
|
bsw/jbe@1309
|
50 end
|
|
bsw/jbe@1309
|
51
|
|
bsw/jbe@1309
|
52 if domain then
|
|
bsw/jbe@1309
|
53 if domain ~= cert_common_name then
|
|
bsw/jbe@1309
|
54 return error_result("invalid_grant", "CN in X.509 certificate incorrect")
|
|
bsw/jbe@1309
|
55 end
|
|
bsw/jbe@1309
|
56 else
|
|
bsw/jbe@1309
|
57 domain = cert_common_name
|
|
bsw/jbe@1309
|
58 end
|
|
bsw/jbe@1309
|
59
|
|
bsw/jbe@1309
|
60 local redirect_uri = "https://" .. domain .. "/" .. config.oauth2.endpoint_magic
|
|
bsw/jbe@1309
|
61
|
|
bsw/jbe@1309
|
62 local expiry = db:query({ "SELECT now() + (? || 'sec')::interval AS expiry", config.oauth2.dynamic_registration_lifetime }, "object").expiry
|
|
bsw/jbe@1309
|
63
|
|
bsw/jbe@1309
|
64 for s in string.gmatch(scope, "[^ ]+") do
|
|
bsw/jbe@1309
|
65 local dynamic_application_scope = DynamicApplicationScope:new()
|
|
bsw/jbe@1309
|
66 dynamic_application_scope.redirect_uri = redirect_uri
|
|
bsw/jbe@1309
|
67 dynamic_application_scope.flow = flow
|
|
bsw/jbe@1309
|
68 dynamic_application_scope.scope = s
|
|
bsw/jbe@1309
|
69 dynamic_application_scope.expiry = expiry
|
|
bsw/jbe@1309
|
70 dynamic_application_scope:upsert_mode()
|
|
bsw/jbe@1309
|
71 dynamic_application_scope:save()
|
|
bsw/jbe@1309
|
72 end
|
|
bsw/jbe@1309
|
73
|
|
bsw/jbe@1309
|
74 r.client_id = "dynamic:" .. domain
|
|
bsw/jbe@1309
|
75 r.expires_in = config.oauth2.dynamic_registration_lifetime
|
|
bsw/jbe@1309
|
76
|
|
bsw/jbe@1309
|
77 slot.put_into("data", json.export(r))
|