open-contracting / credere-backend

A tool that facilitates the participation of Micro, Small, and Medium businesses (MSMEs) in the Colombian public procurement market.
https://credere.readthedocs.io
BSD 3-Clause "New" or "Revised" License
5 stars 0 forks source link

Add MFA tests #391

Closed jpmckinney closed 1 month ago

jpmckinney commented 2 months ago

Some errors had been logged to Sentry, so I had wanted to add tests to confirm behavior.

Moto doesn't presently support MFA setup.

See my open issues and draft PR: https://github.com/getmoto/moto/issues/created_by/jpmckinney

Here's a patch for a start to some tests once Moto is updated.

```diff diff --git a/tests/__init__.py b/tests/__init__.py index 948c3ca..c8b30c6 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -72,6 +72,14 @@ def create_user(session, aws_client, *, email, **kwargs): Username=email, UserAttributes=[{"Name": "email_verified", "Value": "true"}], ) + assert response.get("ChallengeName") == "MFA_SETUP", response + response = aws_client.cognito.associate_software_token(Session=response["Session"]) + + # setup_mfa() + aws_client.cognito.verify_software_token(Session=response["Session"], UserCode="123456") + + # login() + response = aws_client.initiate_auth(email, "12345-UPPER-lower") return {"Authorization": "Bearer " + response["AuthenticationResult"]["AccessToken"]} diff --git a/tests/routers/test_users.py b/tests/routers/test_users.py index 5cf91a6..c04c69e 100644 --- a/tests/routers/test_users.py +++ b/tests/routers/test_users.py @@ -64,6 +64,21 @@ def test_duplicate_user(client, admin_header, user_payload): assert response.json() == {"detail": _("User with that email already exists")} +def test_login(client, admin_header, admin_email): + client.get("/users/logout", headers=admin_header) + + response = client.post( + "/users/login", + json={ + "username": admin_email, + "password": "12345-UPPER-lower", + }, + ) + + assert response.json() == {} + assert response.status_code == status.HTTP_200_OK + + def test_login_invalid_username(client): response = client.post("/users/login", json={"username": "nonexistent"}) @@ -71,6 +86,16 @@ def test_login_invalid_username(client): assert response.json() == {"detail": "Invalid username or password"} +def test_login_invalid_password(client): + pass + # TODO + + +def test_login_invalid_mfa(client): + pass + # TODO + + def test_logout(client, admin_header): response = client.get("/users/logout", headers=admin_header) ```
jpmckinney commented 2 months ago

Moto did recently add in 5.0.12 3 weeks ago https://github.com/getmoto/moto/blob/master/CHANGELOG.md#5012

CognitoIDP: initiate_auth() now supports USERNAME_PASSWORD_AUTH and SMS/Software Token MFA

So, we can probably mock a user with MFA a different way (e.g. opt-in the user via set_user_mfa_preference or admin_set_user_mfa_preference), instead of trying to test the full lifecycle of setting up MFA and then logging in.

On one hand, we'd be more confident if we could mock the full cycle. On the other hand, moto isn't AWS, so we need to trust that moto has the same behavior as AWS regardless.