Skip to content

Commit e2ffb75

Browse files
authored
Merge pull request #72 from richardkeit/expiry
feat(ApiAuth): reduce probability of token expiry moments after retrieval
2 parents fa64970 + dee12e5 commit e2ffb75

3 files changed

Lines changed: 66 additions & 3 deletions

File tree

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ export STAX_ACCESS_KEY=<your_access_key>
2121
export STAX_SECRET_KEY=<your_secret_key>
2222
```
2323

24+
*Optional configuration:*
25+
26+
##### Authentication token expiry
27+
28+
Allows configuration of the threshold to when the Auth library should re-cache the credentials
29+
*Suggested use when running within CI/CD tools to reduce overall auth calls*
30+
~~~bash
31+
export TOKEN_EXPIRY_THRESHOLD_IN_MINS=2 # Type: Integer representing minutes
32+
~~~
33+
2434
## Usage
2535

2636
### Read Accounts

staxapp/auth.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#!/usr/local/bin/python3
2-
from datetime import datetime, timezone
2+
from datetime import datetime, timedelta, timezone
3+
from os import environ
34

45
import boto3
56
from aws_requests_auth.aws_auth import AWSRequestsAuth
@@ -139,7 +140,10 @@ def requests_auth(username, password, **kwargs):
139140
class ApiTokenAuth:
140141
@staticmethod
141142
def requests_auth(username, password, **kwargs):
142-
if StaxConfig.expiration and StaxConfig.expiration > datetime.now(timezone.utc):
143+
# Minimize the potentical for token to expire while still being used for auth (say within a lambda function)
144+
if StaxConfig.expiration and StaxConfig.expiration - timedelta(
145+
minutes=int(environ.get("TOKEN_EXPIRY_THRESHOLD_IN_MINS", 1))
146+
) > datetime.now(timezone.utc):
143147
return StaxConfig.auth
144148

145149
return StaxAuth("ApiAuth").requests_auth(username, password, **kwargs)

tests/test_auth.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""
77

88
import unittest
9+
from unittest.mock import patch
910
import jwt
1011
import botocore
1112
import requests
@@ -15,6 +16,7 @@
1516
from botocore.client import Config as BotoConfig
1617
from botocore.stub import Stubber, ANY
1718
from datetime import datetime, timedelta, timezone
19+
from os import environ
1820

1921
from staxapp.api import Api
2022
from staxapp.auth import StaxAuth, ApiTokenAuth, RootAuth
@@ -156,7 +158,7 @@ def testCredsClient(self):
156158
expected_params=expected_parameters,
157159
)
158160
self.cognito_stub.activate()
159-
161+
160162
with self.assertRaises(InvalidCredentialsException) as e:
161163
sa.sts_from_cognito_identity_pool(jwt_token.get("sub"), cognito_client=self.cognito_client)
162164

@@ -305,6 +307,52 @@ def testApiTokenAuth(self):
305307
)
306308
self.assertIsNotNone(StaxConfig.auth)
307309

310+
311+
@patch("test_auth.StaxAuth.requests_auth")
312+
def testApiTokenAuthExpiring(self, requests_auth_mock):
313+
"""
314+
Test credentials close to expiration get refreshed
315+
"""
316+
sa = StaxAuth("ApiAuth")
317+
StaxConfig = Config
318+
## expiration 20 minutes in the future, no need to refresh
319+
StaxConfig.expiration = datetime.now(timezone.utc) + timedelta(minutes=20)
320+
321+
ApiTokenAuth.requests_auth(
322+
"username",
323+
"password",
324+
srp_client=self.aws_srp_client,
325+
cognito_client=self.cognito_client,
326+
)
327+
requests_auth_mock.assert_not_called()
328+
329+
requests_auth_mock.reset_mock()
330+
## expiration in 5 seconds from now, refresh to avoid token becoming stale used
331+
StaxConfig.expiration = datetime.now(timezone.utc) + timedelta(seconds=5)
332+
333+
ApiTokenAuth.requests_auth(
334+
"username",
335+
"password",
336+
srp_client=self.aws_srp_client,
337+
cognito_client=self.cognito_client,
338+
)
339+
requests_auth_mock.assert_called_once()
340+
341+
342+
requests_auth_mock.reset_mock()
343+
## expiration in 5 minutes from now, refresh to avoid token becoming stale used
344+
## override default triggering library to not refresh
345+
environ["TOKEN_EXPIRY_THRESHOLD_IN_MINS"] = "10"
346+
StaxConfig.expiration = datetime.now(timezone.utc) + timedelta(minutes=2)
347+
348+
ApiTokenAuth.requests_auth(
349+
"username",
350+
"password",
351+
srp_client=self.aws_srp_client,
352+
cognito_client=self.cognito_client,
353+
)
354+
requests_auth_mock.assert_called_once()
355+
308356
def testRootAuthNotExpired(self):
309357
"""
310358
Test credentials have not expired
@@ -359,5 +407,6 @@ def testApiAuth(self):
359407
self.assertIsNotNone(Api._requests_auth)
360408

361409

410+
362411
if __name__ == "__main__":
363412
unittest.main()

0 commit comments

Comments
 (0)