diff options
author | Mike Crute <mike@crute.us> | 2017-07-18 03:35:52 +0000 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2017-07-18 03:35:52 +0000 |
commit | 72f7d25a69b6ed41a15eef973f9fbb821931c901 (patch) | |
tree | fb6c7e60e273c7a471c10c4ab6236a58f1efe2d2 /server.py | |
download | py_openid_connect-72f7d25a69b6ed41a15eef973f9fbb821931c901.tar.bz2 py_openid_connect-72f7d25a69b6ed41a15eef973f9fbb821931c901.tar.xz py_openid_connect-72f7d25a69b6ed41a15eef973f9fbb821931c901.zip |
Diffstat (limited to 'server.py')
-rw-r--r-- | server.py | 87 |
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 @@ | |||
1 | import flask | ||
2 | import urllib.parse | ||
3 | from flask import request | ||
4 | |||
5 | |||
6 | # Application Config | ||
7 | OIDC_ISSUER = "https://id.crute.me/" | ||
8 | OIDC_AUTH_ENDPOINT = "{}login".format(OIDC_ISSUER) | ||
9 | OIDC_JWKS_ENDPOINT = "{}jwks".format(OIDC_ISSUER) | ||
10 | DOMAIN_WHITELIST = ["crute.me", "crute.us"] | ||
11 | |||
12 | |||
13 | # Generic Constants | ||
14 | JRD_MIMETYPE = "application/jrd+json" | ||
15 | OIDC_ISSUER_QUERY = "http://openid.net/specs/connect/1.0/issuer" | ||
16 | JRD_404 = flask.Response("Not found", status=404, mimetype=JRD_MIMETYPE) | ||
17 | |||
18 | |||
19 | app = flask.Flask(__name__) | ||
20 | |||
21 | |||
22 | def 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"]) | ||
31 | def 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"]) | ||
65 | def 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"]) | ||
81 | def login(): | ||
82 | pass | ||
83 | |||
84 | |||
85 | @app.route("/jwks", methods=["GET"]) | ||
86 | def keys(): | ||
87 | pass | ||