Skip to content

Commit a6abbc9

Browse files
authored
Merge pull request #18 from shenwpo/Bearer
Implement bearer authorization
2 parents d8dc7d0 + 6f5d7c5 commit a6abbc9

File tree

6 files changed

+45
-8
lines changed

6 files changed

+45
-8
lines changed

flask_authz/casbin_enforcer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ def wrapper(*args, **kwargs):
8080
if header == "authorization":
8181
# Get Auth Value then decode and parse for owner
8282
try:
83-
owner = authorization_decoder(request.headers.get(header))
83+
owner = authorization_decoder(self.app.config, request.headers.get(header))
8484
except UnSupportedAuthType:
8585
# Continue if catch unsupported type in the event of
8686
# Other headers needing to be checked
@@ -89,6 +89,9 @@ def wrapper(*args, **kwargs):
8989
"decoding is unsupported by flask-casbin at this time"
9090
)
9191
continue
92+
except Exception as e:
93+
self.app.logger.info(e)
94+
continue
9295

9396
if self.user_name_headers and header in map(str.lower, self.user_name_headers):
9497
owner_audit = owner

flask_authz/utils/auth_decoder.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from base64 import b64decode
22

3+
import jwt
4+
35

46
class UnSupportedAuthType(Exception):
57
status_code = 501
@@ -20,11 +22,12 @@ def to_dict(self):
2022
return rv
2123

2224

23-
def authorization_decoder(auth_str: str):
25+
def authorization_decoder(config, auth_str: str):
2426
"""
2527
Authorization token decoder based on type. This will decode the token and
2628
only return the owner
2729
Args:
30+
config: app.config object
2831
auth_str: Authorization string should be in "<type> <token>" format
2932
Returns:
3033
decoded owner from token
@@ -35,6 +38,9 @@ def authorization_decoder(auth_str: str):
3538
"""Basic format <user>:<password> return only the user"""
3639
return b64decode(token).decode().split(":")[0]
3740
elif type == "Bearer":
38-
raise UnSupportedAuthType("Bearer is not implemented yet")
41+
"""return only the identity, depends on JWT 2.x"""
42+
decoded_jwt = jwt.decode(token, config.get("JWT_SECRET_KEY"),
43+
algorithms=config.get("JWT_HASH"))
44+
return decoded_jwt.get("identity", "")
3945
else:
4046
raise UnSupportedAuthType("%s Authorization is not supported" % type)

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ jinja2==2.11.2
66
markupsafe==1.1.1
77
simpleeval==0.9.10
88
werkzeug==1.0.1
9+
PyJWT==2.0.1

tests/conftest.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ def app_fixture():
1212
)
1313
# Set headers where owner for enforcement policy should be located
1414
app.config["CASBIN_OWNER_HEADERS"] = {"Authorization", "X-User", "X-Idp-Groups"}
15+
app.config["JWT_SECRET_KEY"] = "SECRET_KEY"
16+
app.config["JWT_HASH"] = "HS256"
1517

1618
yield app

tests/test_casbin_enforcer.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ def update_callback(self):
6262
("X-Idp-Groups", "noexist testnoexist users", "GET", 200, None),
6363
("X-Idp-Groups", "noexist, testnoexist, users", "GET", 200, None),
6464
("Authorization", "Basic Ym9iOnBhc3N3b3Jk", "GET", 200, "Authorization"),
65+
("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZGVudGl0eSI6ImJvYiJ9."
66+
"LM-CqxAM2MtT2uT3AO69rZ3WJ81nnyMQicizh4oqBwk", "GET", 200, None),
67+
("Authorization", "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9."
68+
"eyJleHAiOjE2MTUxMDg0OTIuNTY5MjksImlkZW50aXR5IjoiQm9iIn0."
69+
"CAeMpG-gKbucHU7-KMiqM7H_gTkHSRvXSjNtlvh5DlE", "GET", 401, None),
70+
("Authorization", "Unsupported Ym9iOnBhc3N3b3Jk", "GET", 401, None),
6571
("Authorization", "Unsupported Ym9iOnBhc3N3b3Jk", "GET", 401, None),
6672
],
6773
)

tests/test_utils_auth_decoder.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
1+
import jwt
12
import pytest
23
from flask_authz.utils import authorization_decoder, UnSupportedAuthType
34

45

56
@pytest.mark.parametrize("auth_str, result", [("Basic Ym9iOnBhc3N3b3Jk", "Bob")])
6-
def test_auth_docode(auth_str, result):
7-
assert authorization_decoder(auth_str) == "bob"
7+
def test_auth_docode(app_fixture, auth_str, result):
8+
assert authorization_decoder(app_fixture.config, auth_str) == "bob"
89

910

1011
@pytest.mark.parametrize(
11-
"auth_str", [("Bearer Ym9iOnBhc3N3b3Jk"), ("Unsupported Ym9iOnBhc3N3b3Jk")]
12+
"auth_str, result",
13+
[("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZGVudGl0eSI6IkJvYiJ9"
14+
".YZqkPHdrxkkFNg7GNL8g-hRpiD9LPyospO47Mh3iEDk", "Bob")])
15+
def test_auth_docode(app_fixture, auth_str, result):
16+
assert authorization_decoder(app_fixture.config, auth_str) == "Bob"
17+
18+
19+
@pytest.mark.parametrize(
20+
"auth_str", [("Unsupported Ym9iOnBhc3N3b3Jk")]
1221
)
13-
def test_auth_docode_exceptions(auth_str):
22+
def test_auth_docode_exceptions(app_fixture, auth_str):
1423
with pytest.raises(UnSupportedAuthType):
15-
authorization_decoder(auth_str)
24+
authorization_decoder(app_fixture.config, auth_str)
25+
26+
27+
@pytest.mark.parametrize(
28+
"auth_str",
29+
[("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MTUxMDg0OTIuNTY5MjksImlkZW50aXR5IjoiQm9iIn0."
30+
"CAeMpG-gKbucHU7-KMiqM7H_gTkHSRvXSjNtlvh5DlE")]
31+
)
32+
def test_auth_docode_exceptions(app_fixture, auth_str):
33+
with pytest.raises(jwt.ExpiredSignatureError):
34+
authorization_decoder(app_fixture.config, auth_str)

0 commit comments

Comments
 (0)