Skip to content

Commit 772f4ab

Browse files
committed
Sem-ver: feature Provide type information to consumers of the library
Signed-off-by: David Black <[email protected]> Sem-ver: bugfix Have mypy install stubs as part of ci Signed-off-by: David Black <[email protected]> Sem-ver: bugfix Typing fix ups - this commit will be merged into an earlier one Signed-off-by: David Black <[email protected]> Remove the unused UnitTestProtocol code Signed-off-by: David Black <[email protected]>
1 parent 764aacf commit 772f4ab

File tree

12 files changed

+46
-44
lines changed

12 files changed

+46
-44
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ jobs:
1818
python-version: ${{ matrix.python-version }}
1919
- name: Install dependencies
2020
run: |
21+
pip install -r requirements.txt
22+
pip install -r test-requirements.txt
2123
python -m pip install --upgrade pip wheel setuptools
2224
pip install -q ruff mypy
2325
- name: Lint

atlassian_jwt_auth/auth.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def create(
2626
cls,
2727
issuer: str,
2828
key_identifier: Union[KeyIdentifier, str],
29-
private_key_pem: str,
29+
private_key_pem: Union[str, bytes],
3030
audience: Union[str, Iterable[str]],
3131
**kwargs: Any,
3232
) -> "BaseJWTAuth":
@@ -39,4 +39,4 @@ def create(
3939
def _get_header_value(self) -> bytes:
4040
return b"Bearer " + self._signer.generate_jwt(
4141
self._audience, additional_claims=self._additional_claims
42-
).encode("utf-8")
42+
)

atlassian_jwt_auth/frameworks/common/asap.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def _process_asap_token(
3737
if verifier is None:
3838
verifier = backend.get_verifier(settings=settings)
3939
asap_claims = verifier.verify_jwt(
40-
token.decode("utf-8") if isinstance(token, bytes) else token,
40+
token,
4141
settings.ASAP_VALID_AUDIENCE,
4242
leeway=settings.ASAP_VALID_LEEWAY,
4343
)
@@ -94,5 +94,9 @@ def _verify_issuers(
9494
) -> None:
9595
"""Verify that the issuer in the claims is valid and is expected."""
9696
claim_iss = asap_claims.get("iss")
97-
if issuers is not None and claim_iss is not None and claim_iss not in issuers:
97+
if issuers is None:
98+
return None
99+
100+
if claim_iss is None or claim_iss not in issuers:
98101
raise InvalidIssuerError
102+
return None

atlassian_jwt_auth/frameworks/common/decorators.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,23 +72,22 @@ def restrict_asap_wrapper(request, *args, **kwargs) -> Any:
7272
asap_claims = getattr(request, "asap_claims", None)
7373
error_response = None
7474

75-
if required and not asap_claims:
76-
if backend is not None:
75+
if not asap_claims:
76+
if required:
7777
return backend.get_401_response("Unauthorized", request=request)
78-
78+
else:
79+
# Claims are not required and asap claims are not present.
80+
return func(request, *args, **kwargs)
7981
try:
80-
if asap_claims is not None:
81-
_verify_issuers(asap_claims, settings.ASAP_VALID_ISSUERS)
82+
_verify_issuers(asap_claims, settings.ASAP_VALID_ISSUERS)
8283
except InvalidIssuerError:
83-
if backend is not None:
84-
error_response = backend.get_403_response(
85-
"Forbidden: Invalid token issuer", request=request
86-
)
84+
error_response = backend.get_403_response(
85+
"Forbidden: Invalid token issuer", request=request
86+
)
8787
except InvalidTokenError:
88-
if backend is not None:
89-
error_response = backend.get_401_response(
90-
"Unauthorized: Invalid token", request=request
91-
)
88+
error_response = backend.get_401_response(
89+
"Unauthorized: Invalid token", request=request
90+
)
9291

9392
if error_response and required:
9493
return error_response

atlassian_jwt_auth/frameworks/django/decorators.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ def restrict_asap(
5656
must match the issuer for a
5757
token to be considered valid.
5858
"""
59-
issuers = issuers if issuers is not None else []
6059
return _restrict_asap(
61-
func, DjangoBackend(), issuers, required, subject_should_match_issuer=None
60+
func,
61+
DjangoBackend(),
62+
issuers,
63+
required,
64+
subject_should_match_issuer=None,
6265
)

atlassian_jwt_auth/frameworks/django/tests/test_django.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def check_response(
6868
token=None,
6969
authorization=None,
7070
retriever_key=None,
71-
):
71+
) -> None:
7272
if authorization is None:
7373
if token is None:
7474
if private_key is None:
@@ -211,7 +211,7 @@ def test_request_non_decorated_subject_is_rejected(self):
211211
def test_request_using_settings_only_is_allowed(self):
212212
self.check_response("unneeded", "two")
213213

214-
def test_request_subject_does_not_need_to_match_issuer_from_settings(self):
214+
def test_request_subject_does_not_need_to_match_issuer_from_settings(self) -> None:
215215
self.test_settings["ASAP_SUBJECT_SHOULD_MATCH_ISSUER"] = False
216216
self.check_response("needed", "one", 200, subject="different_than_is")
217217

atlassian_jwt_auth/frameworks/flask/decorators.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ def with_asap(
2727
must match the issuer for a
2828
token to be considered valid.
2929
"""
30+
if required is None:
31+
required = True
3032
return _with_asap(
31-
func, FlaskBackend(), issuers, required or False, subject_should_match_issuer
33+
func, FlaskBackend(), issuers, required, subject_should_match_issuer
3234
)

atlassian_jwt_auth/py.typed

Whitespace-only changes.

atlassian_jwt_auth/signer.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ def _generate_claims(
7272
def _now(self) -> datetime.datetime:
7373
return datetime.datetime.now(datetime.timezone.utc)
7474

75-
def generate_jwt(self, audience: Union[str, Iterable[str]], **kwargs: Any) -> str:
75+
def generate_jwt(self, audience: Union[str, Iterable[str]], **kwargs: Any) -> bytes:
7676
"""returns a new signed jwt for use."""
7777
key_identifier, private_key_pem = self.private_key_retriever.load(self.issuer)
7878
private_key = self._obtain_private_key(key_identifier, private_key_pem)
79-
token = jwt.encode(
79+
token: str = jwt.encode(
8080
self._generate_claims(audience, **kwargs),
8181
key=private_key,
8282
algorithm=self.algorithm,
@@ -86,9 +86,7 @@ def generate_jwt(self, audience: Union[str, Iterable[str]], **kwargs: Any) -> st
8686
else key_identifier
8787
},
8888
)
89-
if isinstance(token, bytes):
90-
return token.decode("utf-8")
91-
return token
89+
return token.encode("utf-8")
9290

9391

9492
class TokenReusingJWTAuthSigner(JWTAuthSigner):
@@ -102,7 +100,7 @@ def __init__(
102100

103101
def get_cached_token(
104102
self, audience: Union[str, Iterable[str]], **kwargs: Any
105-
) -> Optional[str]:
103+
) -> Optional[bytes]:
106104
"""returns the cached token. If there is no matching cached token
107105
then None is returned.
108106
"""
@@ -139,7 +137,7 @@ def can_reuse_token(self, existing_token, claims) -> bool:
139137
return False
140138
return True
141139

142-
def generate_jwt(self, audience: Union[str, Iterable[str]], **kwargs: Any) -> str:
140+
def generate_jwt(self, audience: Union[str, Iterable[str]], **kwargs: Any) -> bytes:
143141
existing_token = self.get_cached_token(audience, **kwargs)
144142
claims = self._generate_claims(audience, **kwargs)
145143
if existing_token and self.can_reuse_token(existing_token, claims):

atlassian_jwt_auth/tests/utils.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def create_token(
4545
issuer: str,
4646
audience: Union[str, Iterable[str]],
4747
key_id: Union[KeyIdentifier, str],
48-
private_key: str,
48+
private_key: Union[str, bytes],
4949
subject: Optional[str] = None,
5050
):
5151
""" " returns a token based upon the supplied parameters."""
@@ -65,18 +65,6 @@ def get_new_private_key_in_pem_format(self) -> bytes:
6565
raise NotImplementedError("not implemented.")
6666

6767

68-
class UnitTestProtocol(Protocol):
69-
def assertEqual(self, a, b): ...
70-
71-
def assertIsNotNone(self, a): ...
72-
73-
def assertTrue(self, a): ...
74-
75-
def assertIn(self, a, b): ...
76-
77-
def assertNotEqual(self, a, b): ...
78-
79-
8068
class KeyMixInProtocol(Protocol):
8169
@property
8270
def algorithm(self) -> str: ...

0 commit comments

Comments
 (0)