summaryrefslogtreecommitdiff
path: root/server.py
diff options
context:
space:
mode:
Diffstat (limited to 'server.py')
-rw-r--r--server.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..0bebe2a
--- /dev/null
+++ b/server.py
@@ -0,0 +1,87 @@
1import flask
2import urllib.parse
3from flask import request
4
5
6# Application Config
7OIDC_ISSUER = "https://id.crute.me/"
8OIDC_AUTH_ENDPOINT = "{}login".format(OIDC_ISSUER)
9OIDC_JWKS_ENDPOINT = "{}jwks".format(OIDC_ISSUER)
10DOMAIN_WHITELIST = ["crute.me", "crute.us"]
11
12
13# Generic Constants
14JRD_MIMETYPE = "application/jrd+json"
15OIDC_ISSUER_QUERY = "http://openid.net/specs/connect/1.0/issuer"
16JRD_404 = flask.Response("Not found", status=404, mimetype=JRD_MIMETYPE)
17
18
19app = flask.Flask(__name__)
20
21
22def parse_email_addr(addr):
23 try:
24 user, domain = addr.split("@")
25 return user, domain
26 except ValueError:
27 return None
28
29
30@app.route("/.well-known/webfinger", methods=["GET"])
31def webfinger():
32 resource = request.args.get("resource")
33 rel = request.args.get("rel")
34
35 # Only support OIDC queries
36 if not rel or not resource or not rel == OIDC_ISSUER_QUERY:
37 return JRD_404
38
39 # Only support email address queries
40 acct = urllib.parse.urlparse(resource)
41 if acct.scheme != "acct":
42 return JRD_404
43
44 # Ensure that the query is in a whitelisted domain
45 _, domain = parse_email_addr(acct.path)
46 if domain not in DOMAIN_WHITELIST:
47 return JRD_404
48
49 # We don't validate that the user exists to prevent leaking information
50 # about what users exist; plus, it doesn't really matter since the querier
51 # only cares about the OIDC issuer endpoint which is user independent
52 res = flask.jsonify({
53 "subject": resource,
54 "links": [{
55 "rel": OIDC_ISSUER_QUERY,
56 "href": OIDC_ISSUER,
57 }]
58 })
59 res.mimetype = JRD_MIMETYPE
60 return res
61
62
63
64@app.route("/.well-known/openid-configuration", methods=["GET"])
65def openid_configuration():
66 return flask.jsonify({
67 "issuer": OIDC_ISSUER,
68 "authorization_endpoint": OIDC_AUTH_ENDPOINT,
69 "jwks_uri": OIDC_JWKS_ENDPOINT,
70 "scopes_supported": ["openid"],
71 "response_types_supported": ["id_token"],
72 "response_modes_supported": ["query"],
73 "grant_types_supported": ["implicit"],
74 "subject_types_supported": ["public"],
75 "id_token_signing_alg_values_supported": ["RS256"],
76 "acr_values_supported": ["want_mfa", "need_mfa"],
77 })
78
79
80@app.route("/login", methods=["GET", "POST"])
81def login():
82 pass
83
84
85@app.route("/jwks", methods=["GET"])
86def keys():
87 pass