-
Notifications
You must be signed in to change notification settings - Fork 0
/
readme_example.py
116 lines (84 loc) · 3.48 KB
/
readme_example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# flake8: noqa
import random
import falcon
from falcon_auth2 import AuthMiddleware
from falcon_auth2 import HeaderGetter
from falcon_auth2.backends import BasicAuthBackend
from falcon_auth2.backends import GenericAuthBackend
from falcon_auth2.backends import JWTAuthBackend
from falcon_auth2.backends import MultiAuthBackend
# To run this application with waitress (or any other wsgi server)
# waitress-serve --port 8080 readme_example:app
# You can then use httpie to interact with it. Example
# http :8080/hello -a foo:bar
# http :8080/hello 'Authorization:Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiYXIiLCJpc3MiOiJhbiBpc3N1ZXIiLCJhdWQiOiJhbiBhdWQiLCJpYXQiOjE2MDk0NTkyMDAsIm5iZiI6MTYwOTQ1OTIwMCwiZXhwIjoxOTI0OTkyMDAwfQ.FDpE_-jL-reHrheIYVGbwdVf8g1HWFAoGJet_6zC2Tk'
# http :8080/no-auth
# http POST :8080/generic User:foo
def authenticate(user, password):
# Check if the user exists and the password match.
# This is just for the example
return random.choice((True, False))
def basic_user_loader(attributes, user, password):
if authenticate(user, password):
return {"username": user, "kind": "basic"}
return None
def jwt_user_loader(attributes, payload):
# Perform additional authentication using the payload.
# This is just an example
if "sub" in payload:
return {"username": payload["sub"], "kind": "jwt"}
return None
# NOTE: this is just an example. A key should be propertly generated, like using:
# key=secrets.token_bytes(256)
key = "not-a-secret-key"
basic_backend = BasicAuthBackend(basic_user_loader)
jwt_backend = JWTAuthBackend(jwt_user_loader, key)
auth_backend = MultiAuthBackend((basic_backend, jwt_backend))
auth_middleware = AuthMiddleware(auth_backend)
# use falcon.API in falcon 2
app = falcon.App(middleware=[auth_middleware])
class HelloResource:
def on_get(self, req, resp):
# req.context.auth is of the form:
#
# {
# 'backend': <instance of the backend that performed the authentication>,
# 'user': <user object retrieved from the user_loader callable>,
# '<backend specific item>': <some extra data that may be added by the backend>,
# ...
# }
user = req.context.auth["user"]
resp.media = {"message": f"Hello {user['username']} from {user['kind']}"}
app.add_route("/hello", HelloResource())
def user_header_loader(attr, user_header):
# authenticate the user with the user_header
return user_header
class GenericResource:
auth = {
"backend": GenericAuthBackend(user_header_loader, getter=HeaderGetter("User")),
"exempt_methods": ["GET"],
}
def on_get(self, req, resp):
resp.media = {"type": "No authentication for GET"}
def on_post(self, req, resp):
resp.media = {"info": f"User header {req.context.auth['user']}"}
app.add_route("/generic", GenericResource())
class NoAuthResource:
auth = {"auth_disabled": True}
def on_get(self, req, resp):
resp.text = "No auth in this resource"
def on_post(self, req, resp):
resp.text = "No auth in this resource"
app.add_route("/no-auth", NoAuthResource())
def make_token():
# the token above was generated by calling this example function
from authlib.jose import jwt
payload = {
"sub": "bar",
"iss": "an issuer",
"aud": "an aud",
"iat": 1609459200,
"nbf": 1609459200,
"exp": 1924992000,
}
print(jwt.encode({"alg": "HS256"}, payload, key))