Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Island: Include refresh token into responses #3180

Merged
merged 5 commits into from
Mar 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions monkey/monkey_island/cc/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,7 @@
from monkey_island.cc.services.authentication_service.configure_flask_security import (
configure_flask_security,
)
from monkey_island.cc.services.authentication_service.token import (
TokenGenerator,
TokenValidator,
)
from monkey_island.cc.services.authentication_service.token import TokenGenerator, TokenValidator
from monkey_island.cc.services.representations import output_json

HOME_FILE = "index.html"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
from monkey_island.cc.flask_utils import AbstractResource, responses

from ..authentication_facade import AuthenticationFacade
from .utils import get_username_password_from_request, include_auth_token
from .utils import (
add_refresh_token_to_response,
get_username_password_from_request,
include_auth_token,
)

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -38,9 +42,8 @@ def post(self):
try:
username, password = get_username_password_from_request(request)
response: ResponseValue = login()
# TODO send these back
_tokens = self._authentication_facade.generate_refresh_token(current_user)
del _tokens
refresh_token = self._authentication_facade.generate_refresh_token(current_user)
response = add_refresh_token_to_response(response, refresh_token)
except Exception:
return responses.make_response_to_invalid_request()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
from monkey_island.cc.flask_utils import AbstractResource, responses

from ..authentication_facade import AuthenticationFacade
from .utils import get_username_password_from_request, include_auth_token
from .utils import (
add_refresh_token_to_response,
get_username_password_from_request,
include_auth_token,
)

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -37,9 +41,8 @@ def post(self):
}, HTTPStatus.CONFLICT
username, password = get_username_password_from_request(request)
response: ResponseValue = register()
# TODO send these back
_tokens = self._authentication_facade.generate_refresh_token(current_user)
del _tokens
refresh_token = self._authentication_facade.generate_refresh_token(current_user)
response = add_refresh_token_to_response(response, refresh_token)
except Exception:
return responses.make_response_to_invalid_request()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import json
from copy import deepcopy
from functools import wraps
from typing import Tuple

from flask import Request, request
from flask import Request, Response, request
from werkzeug.datastructures import ImmutableMultiDict

from monkey_island.cc.services.authentication_service.token import Token


def get_username_password_from_request(_request: Request) -> Tuple[str, str]:
"""
Expand Down Expand Up @@ -35,3 +38,17 @@ def decorated_function(*args, **kwargs):
return func(*args, **kwargs)

return decorated_function


def add_refresh_token_to_response(response: Response, refresh_token: Token) -> Response:
"""
Returns a copy of the response object with the refresh token added to it

:param response: A Flask Response object
:param refresh_token: Refresh token to add to the response
:return: A Flask Response object
"""
new_data = deepcopy(response.json)
new_data["response"]["user"]["refresh_token"] = refresh_token
response.data = json.dumps(new_data).encode()
return response
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@
RegistrationStatus,
)

REFRESH_TOKEN = "refresh_token"


@pytest.fixture
def mock_authentication_facade():
mock_service = MagicMock(spec=AuthenticationFacade)
mock_service.generate_refresh_token = MagicMock()
mock_service.generate_refresh_token.return_value = REFRESH_TOKEN

return mock_service

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import pytest
from flask import Response
from tests.unit_tests.monkey_island.cc.services.authentication_service.conftest import REFRESH_TOKEN

from monkey_island.cc.services.authentication_service.authentication_facade import (
AuthenticationFacade,
Expand All @@ -13,6 +14,14 @@
PASSWORD = "test_password"
TEST_REQUEST = f'{{"username": "{USERNAME}", "password": "{PASSWORD}"}}'
FLASK_LOGIN_IMPORT = "monkey_island.cc.services.authentication_service.flask_resources.login.login"
LOGIN_RESPONSE_DATA = (
b'{"response": {"user": {"authentication_token": "abcdefg"}, "csrf_token": "hijklmnop"}}'
)
LOGIN_RESPONSE = Response(
response=LOGIN_RESPONSE_DATA,
status=HTTPStatus.OK,
mimetype="application/json",
)


@pytest.fixture
Expand All @@ -28,12 +37,7 @@ def inner(request_body):
def test_credential_parsing(
monkeypatch, make_login_request, mock_authentication_facade: AuthenticationFacade
):
monkeypatch.setattr(
FLASK_LOGIN_IMPORT,
lambda: Response(
status=HTTPStatus.OK,
),
)
monkeypatch.setattr(FLASK_LOGIN_IMPORT, lambda: LOGIN_RESPONSE)

make_login_request(TEST_REQUEST)
mock_authentication_facade.handle_successful_login.assert_called_with(USERNAME, PASSWORD)
Expand All @@ -45,16 +49,12 @@ def test_empty_credentials(make_login_request, mock_authentication_facade: Authe


def test_login_successful(make_login_request, monkeypatch):
monkeypatch.setattr(
FLASK_LOGIN_IMPORT,
lambda: Response(
status=HTTPStatus.OK,
),
)
monkeypatch.setattr(FLASK_LOGIN_IMPORT, lambda: LOGIN_RESPONSE)

response = make_login_request(TEST_REQUEST)

assert response.status_code == HTTPStatus.OK
assert response.json["response"]["user"]["refresh_token"] == REFRESH_TOKEN


def test_login_failure(
Expand Down Expand Up @@ -104,12 +104,7 @@ def test_login_invalid_request(
def test_login_error(
monkeypatch, make_login_request, mock_authentication_facade: AuthenticationFacade
):
monkeypatch.setattr(
FLASK_LOGIN_IMPORT,
lambda: Response(
status=HTTPStatus.OK,
),
)
monkeypatch.setattr(FLASK_LOGIN_IMPORT, lambda: LOGIN_RESPONSE)
mock_authentication_facade.handle_successful_login = MagicMock(side_effect=Exception())

response = make_login_request(TEST_REQUEST)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import pytest
from flask import Response
from tests.unit_tests.monkey_island.cc.services.authentication_service.conftest import REFRESH_TOKEN

from monkey_island.cc.services.authentication_service.authentication_facade import (
AuthenticationFacade,
Expand All @@ -15,6 +16,14 @@
FLASK_REGISTER_IMPORT = (
"monkey_island.cc.services.authentication_service.flask_resources.register.register"
)
REGISTER_RESPONSE_DATA = (
b'{"response": {"user": {"authentication_token": "abcdefg"}, "csrf_token": "hijklmnop"}}'
)
REGISTER_RESPONSE = Response(
response=REGISTER_RESPONSE_DATA,
status=HTTPStatus.OK,
mimetype="application/json",
)


@pytest.fixture
Expand Down Expand Up @@ -50,16 +59,12 @@ def test_register__already_registered(
def test_register_successful(
monkeypatch, make_registration_request, mock_authentication_facade: AuthenticationFacade
):
monkeypatch.setattr(
FLASK_REGISTER_IMPORT,
lambda: Response(
status=HTTPStatus.OK,
),
)
monkeypatch.setattr(FLASK_REGISTER_IMPORT, lambda: REGISTER_RESPONSE)

response = make_registration_request(TEST_REQUEST)

assert response.status_code == HTTPStatus.OK
assert response.json["response"]["user"]["refresh_token"] == REFRESH_TOKEN
mock_authentication_facade.handle_successful_registration.assert_called_with(USERNAME, PASSWORD)


Expand Down Expand Up @@ -94,10 +99,7 @@ def test_register_invalid_request(
def test_register_error(
monkeypatch, make_registration_request, mock_authentication_facade: AuthenticationFacade
):
monkeypatch.setattr(
FLASK_REGISTER_IMPORT,
lambda: Response(status=HTTPStatus.OK),
)
monkeypatch.setattr(FLASK_REGISTER_IMPORT, lambda: REGISTER_RESPONSE)

mock_authentication_facade.handle_successful_registration = MagicMock(side_effect=Exception())

Expand Down