Skip to content

Commit 50798b4

Browse files
committed
feat(auth) mock id_token_from_cognito in tests
1 parent e9578d3 commit 50798b4

6 files changed

Lines changed: 137 additions & 119 deletions

File tree

Pipfile

Lines changed: 0 additions & 28 deletions
This file was deleted.

examples/test.py

Lines changed: 0 additions & 51 deletions
This file was deleted.

staxapp/auth.py

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from aws_requests_auth.aws_auth import AWSRequestsAuth
99
from botocore import UNSIGNED
1010
from botocore.client import Config as BotoConfig
11+
from botocore.exceptions import ClientError
1112
from warrant import AWSSRP, Cognito
1213

1314
from staxapp.config import Config as JumaConfig
@@ -25,9 +26,13 @@ def __init__(self, config_branch):
2526

2627
def requests_auth(self, username, password):
2728
if username is None:
28-
raise InvalidCredentialsException("Please provide an Access Key to your config")
29+
raise InvalidCredentialsException(
30+
"Please provide an Access Key to your config"
31+
)
2932
if password is None:
30-
raise InvalidCredentialsException("Please provide a Secret Key to your config")
33+
raise InvalidCredentialsException(
34+
"Please provide a Secret Key to your config"
35+
)
3136

3237
id_token = self.id_token_from_cognito(username, password)
3338
id_creds = self.sts_from_cognito_identity_pool(id_token)
@@ -38,14 +43,15 @@ def requests_auth(self, username, password):
3843

3944
return JumaConfig.auth
4045

41-
def id_token_from_cognito(self, username=None, password=None):
46+
def id_token_from_cognito(self, username=None, password=None, client=None):
4247
token = None
4348
if username and password:
44-
client = boto3.client(
45-
"cognito-idp",
46-
region_name=self.aws_region,
47-
config=BotoConfig(signature_version=UNSIGNED),
48-
)
49+
if not client:
50+
client = boto3.client(
51+
"cognito-idp",
52+
region_name=self.aws_region,
53+
config=BotoConfig(signature_version=UNSIGNED),
54+
)
4955
aws = AWSSRP(
5056
username=username,
5157
password=password,
@@ -55,16 +61,21 @@ def id_token_from_cognito(self, username=None, password=None):
5561
)
5662
try:
5763
tokens = aws.authenticate_user()
58-
except client.exceptions.NotAuthorizedException as e:
59-
logging.error(e)
60-
raise InvalidCredentialsException(message=str(e), detail="Please check your Secret Key is correct")
61-
except client.exceptions.UserNotFoundException as e:
62-
raise InvalidCredentialsException(message=str(e), detail="Please check your Access Key, that you have created your Api Token and that you are using the right STAX REGION")
63-
64-
# logging.debug(f"TOKEN: {tokens}")
64+
except ClientError as e:
65+
if e.response["Error"]["Code"] == "UserNotFoundException":
66+
raise InvalidCredentialsException(
67+
message=str(e), detail="Please check your Secret Key is correct"
68+
)
69+
elif e.response["Error"]["Code"] == "NotAuthorizedException":
70+
raise InvalidCredentialsException(
71+
message=str(e),
72+
detail="Please check your Access Key, that you have created your Api Token and that you are using the right STAX REGION",
73+
)
74+
else:
75+
raise InvalidCredentialsException(
76+
f"Unexpected Client Error. Error details: {e}"
77+
)
6578
token = tokens["AuthenticationResult"]["IdToken"]
66-
else:
67-
token = jwt.encode({"sub": "unittest"}, "secret", algorithm="HS256")
6879
return token
6980

7081
def sts_from_cognito_identity_pool(self, token, cognito_client=None):

staxapp/exceptions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ def __init__(self, message):
3030

3131
class InvalidCredentialsException(Exception):
3232
def __init__(self, message, detail=""):
33+
logging.error(message)
3334
prefix = f"InvalidCredentialsException: "
3435
if detail:
3536
prefix = f"{prefix}{detail} - "

tests/test_api.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,8 @@ def testFailedApiException(self):
209209
)
210210
with self.assertRaises(ApiException):
211211
self.Api.get("/test/no/error")
212-
213-
# Test an exception which has no json in response
212+
213+
# Test an exception which has no json in response
214214
responses.add(
215215
responses.GET,
216216
f"{Config.api_base_url()}/test/invalid/json",
@@ -219,16 +219,14 @@ def testFailedApiException(self):
219219
)
220220
with self.assertRaises(ApiException):
221221
self.Api.get("/test/invalid/json")
222-
222+
223223
# Test an exception with no content
224224
responses.add(
225-
responses.GET,
226-
f"{Config.api_base_url()}/test/no/content",
227-
status=500,
225+
responses.GET, f"{Config.api_base_url()}/test/no/content", status=500,
228226
)
229227
with self.assertRaises(ApiException):
230228
self.Api.get("/test/no/content")
231-
229+
232230

233231
if __name__ == "__main__":
234232
unittest.main()

tests/test_auth.py

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@
1212

1313
from botocore import UNSIGNED
1414
from botocore.client import Config as BotoConfig
15-
from botocore.stub import Stubber
15+
from botocore.stub import Stubber, ANY
1616

1717
from staxapp.auth import StaxAuth
1818
from staxapp.exceptions import InvalidCredentialsException
1919

20+
2021
class StaxAuthTests(unittest.TestCase):
2122
"""
2223
Inherited class to run all unit tests for this module
@@ -30,8 +31,16 @@ def setUp(self):
3031
)
3132
self.cognito_stub = Stubber(self.cognito_client)
3233

34+
self.aws_srp_client = botocore.session.get_session().create_client(
35+
"cognito-idp",
36+
region_name="ap-southeast-2",
37+
config=BotoConfig(signature_version=UNSIGNED),
38+
)
39+
self.aws_srp_stubber = Stubber(self.aws_srp_client)
40+
3341
def tearDown(self):
3442
self.cognito_stub.deactivate()
43+
self.aws_srp_stubber.deactivate()
3544

3645
def testStaxAuthInit(self):
3746
"""
@@ -45,16 +54,58 @@ def testToken(self):
4554
Test valid JWT is returned
4655
"""
4756
sa = StaxAuth("ApiAuth")
48-
token = sa.id_token_from_cognito()
49-
jwt_token = jwt.decode(token, verify=False)
50-
self.assertIn("sub", jwt_token)
57+
self.stub_aws_srp(sa, "valid_username")
58+
token = sa.id_token_from_cognito(
59+
username="valid_username", password="correct", client=self.aws_srp_client
60+
)
61+
self.assertEqual(token, "valid_token")
62+
63+
def testCredentialErrors(self):
64+
"""
65+
Test that boto errors are caught and converted to InvalidCredentialExceptions
66+
"""
67+
68+
sa = StaxAuth("ApiAuth")
69+
# Test with invalid username password
70+
self.stub_aws_srp(sa, "bad_password", "UserNotFoundException")
71+
user_not_found_success = False
72+
try:
73+
sa.id_token_from_cognito(
74+
username="bad_password", password="wrong", client=self.aws_srp_client
75+
)
76+
except InvalidCredentialsException as e:
77+
self.assertIn("Please check your Secret Key is correct", e.message)
78+
user_not_found_success = True
79+
self.assertTrue(user_not_found_success)
80+
81+
# Test with no access
82+
self.stub_aws_srp(sa, "no_access", "NotAuthorizedException")
83+
no_access_success = False
84+
try:
85+
sa.id_token_from_cognito(
86+
username="no_access", password="wrong", client=self.aws_srp_client
87+
)
88+
except InvalidCredentialsException as e:
89+
self.assertIn(
90+
"Please check your Access Key, that you have created your Api Token and that you are using the right STAX REGION",
91+
e.message,
92+
)
93+
no_access_success = True
94+
self.assertTrue(no_access_success)
95+
96+
# Test Unknown Error
97+
self.stub_aws_srp(sa, "Unknown", "UnitTesting")
98+
with self.assertRaises(InvalidCredentialsException):
99+
sa.id_token_from_cognito(
100+
username="Unknown", password="wrong", client=self.aws_srp_client
101+
)
51102

52103
def testCreds(self):
53104
"""
54105
Test valid credentials are returned
55106
"""
56107
sa = StaxAuth("ApiAuth")
57-
token = sa.id_token_from_cognito()
108+
token = jwt.encode({"sub": "unittest"}, "secret", algorithm="HS256")
58109
jwt_token = jwt.decode(token, verify=False)
59110
self.stub_cognito_creds(jwt_token.get("sub"))
60111
creds = sa.sts_from_cognito_identity_pool(
@@ -63,19 +114,55 @@ def testCreds(self):
63114
self.assertIn("Credentials", creds)
64115
self.assertTrue(creds.get("IdentityId").startswith("ap-southeast-2"))
65116

66-
def testCredentialErrors(self):
67-
"""
117+
def testAuthErrors(self):
118+
"""
68119
Test that errors are thrown when keys are invalid
69120
"""
70-
sa = StaxAuth("ApiAuth")
71-
# Test with no username
72-
with self.assertRaises(InvalidCredentialsException):
73-
sa.requests_auth(username=None, password='valid')
74-
# Test with no username
75-
with self.assertRaises(InvalidCredentialsException):
76-
sa.requests_auth(username='valid', password=None)
77-
# Test with invalid username password
78-
# Todo
121+
sa = StaxAuth("ApiAuth")
122+
# Test with no username
123+
with self.assertRaises(InvalidCredentialsException):
124+
sa.requests_auth(username=None, password="valid")
125+
126+
# Test with no username
127+
with self.assertRaises(InvalidCredentialsException):
128+
sa.requests_auth(username="valid", password=None)
129+
130+
def stub_aws_srp(self, stax_auth, username, error_code=None):
131+
expected_parameters = {
132+
"AuthFlow": "USER_SRP_AUTH",
133+
"AuthParameters": {"SRP_A": ANY, "USERNAME": username},
134+
"ClientId": stax_auth.client_id,
135+
}
136+
if error_code:
137+
self.aws_srp_stubber.add_client_error(
138+
"initiate_auth",
139+
service_error_code=error_code,
140+
expected_params=expected_parameters,
141+
)
142+
else:
143+
self.aws_srp_stubber.add_response(
144+
"initiate_auth",
145+
{
146+
"ChallengeParameters": {
147+
"USER_ID_FOR_SRP": "user",
148+
"SALT": "4",
149+
"SRP_B": "5",
150+
"SECRET_BLOCK": "secblock",
151+
},
152+
"ChallengeName": "PASSWORD_VERIFIER",
153+
},
154+
expected_parameters,
155+
)
156+
self.aws_srp_stubber.add_response(
157+
"respond_to_auth_challenge",
158+
{"AuthenticationResult": {"IdToken": "valid_token"},},
159+
{
160+
"ClientId": stax_auth.client_id,
161+
"ChallengeName": ANY,
162+
"ChallengeResponses": ANY,
163+
},
164+
)
165+
self.aws_srp_stubber.activate()
79166

80167
def stub_cognito_creds(self, token: str):
81168
sa = StaxAuth("ApiAuth")

0 commit comments

Comments
 (0)