diff --git a/src/eduid/webapp/jsconfig/tests/data/config.yaml b/src/eduid/webapp/jsconfig/tests/data/config.yaml index 6d628b5cc..4494eed3b 100644 --- a/src/eduid/webapp/jsconfig/tests/data/config.yaml +++ b/src/eduid/webapp/jsconfig/tests/data/config.yaml @@ -22,8 +22,8 @@ eduid: login_service_url: 'https://idp.example.com/services/idp' lookup_mobile_proofing_service_url: 'https://dashboard.example.com/services/mobile-proofing' orcid_service_url: 'https://dashboard.example.com/services/orcid' - password_entropy: 12 - password_length: 10 + password_entropy: 25 + password_length: 12 personal_data_service_url: 'https://dashboard.example.com/services/pdata' phone_service_url: 'https://dashboard.example.com/services/phone' reset_password_link: 'https://example.com/reset-password' diff --git a/src/eduid/webapp/jsconfig/tests/test_app.py b/src/eduid/webapp/jsconfig/tests/test_app.py index c379f4bb5..11980dd1a 100644 --- a/src/eduid/webapp/jsconfig/tests/test_app.py +++ b/src/eduid/webapp/jsconfig/tests/test_app.py @@ -47,8 +47,8 @@ def update_config(self, config: dict[str, Any]) -> dict[str, Any]: "login_service_url": "https://idp.example.com/services/idp", "lookup_mobile_proofing_service_url": "https://dashboard.example.com/services/mobile-proofing", "orcid_service_url": "https://dashboard.example.com/services/orcid", - "password_entropy": 12, - "password_length": 10, + "password_entropy": 25, + "password_length": 12, "personal_data_service_url": "https://dashboard.example.com/services/pdata", "phone_service_url": "https://dashboard.example.com/services/phone", "reset_password_link": "https://example.com/reset-password", diff --git a/src/eduid/webapp/signup/schemas.py b/src/eduid/webapp/signup/schemas.py index a59944365..80004f4e3 100644 --- a/src/eduid/webapp/signup/schemas.py +++ b/src/eduid/webapp/signup/schemas.py @@ -44,8 +44,8 @@ class Captcha(EduidSchema): class Credentials(EduidSchema): completed = fields.Boolean(required=True) - generated_password = fields.String(required=False) - custom_password = fields.String(required=False) + generated_password = fields.String(required=True, default=None) + custom_password = fields.Boolean(required=True, default=False) # TODO: implement webauthn signup already_signed_up = fields.Boolean(required=True) diff --git a/src/eduid/webapp/signup/settings/common.py b/src/eduid/webapp/signup/settings/common.py index 2c95602da..51468dde5 100644 --- a/src/eduid/webapp/signup/settings/common.py +++ b/src/eduid/webapp/signup/settings/common.py @@ -36,7 +36,7 @@ class SignupConfig( signup_url: str dashboard_url: str - password_length: int = 10 + password_length: int = 12 throttle_resend: timedelta = Field(default=timedelta(minutes=5)) email_verification_code_length: int = 6 email_verification_max_bad_attempts: int = 3 diff --git a/src/eduid/webapp/signup/tests/test_app.py b/src/eduid/webapp/signup/tests/test_app.py index e2403d54e..465786724 100644 --- a/src/eduid/webapp/signup/tests/test_app.py +++ b/src/eduid/webapp/signup/tests/test_app.py @@ -544,6 +544,8 @@ def _create_user( "use_suggested_password": True, "use_webauthn": False, } + if custom_password is not None: + _data["custom_password"] = custom_password if data is not None: _data.update(data) @@ -563,10 +565,8 @@ def _create_user( assert self.get_response_payload(response)["state"]["email"]["completed"] is True assert self.get_response_payload(response)["state"]["credentials"]["completed"] is True if custom_password: - assert ( - self.get_response_payload(response)["state"]["credentials"]["custom_password"] - == custom_password - ) + assert self.get_response_payload(response)["state"]["credentials"]["custom_password"] is True + assert self.get_response_payload(response)["state"]["credentials"]["generated_password"] is None else: assert ( self.get_response_payload(response)["state"]["credentials"]["generated_password"] @@ -848,7 +848,7 @@ def test_get_state_initial(self): assert state == { "already_signed_up": False, "captcha": {"completed": False}, - "credentials": {"completed": False, "generated_password": None}, + "credentials": {"completed": False, "custom_password": False, "generated_password": None}, "email": {"address": None, "bad_attempts": 0, "bad_attempts_max": 3, "completed": False, "sent_at": None}, "invite": {"completed": False, "finish_url": None, "initiated_signup": False}, "name": {"given_name": None, "surname": None}, @@ -863,7 +863,7 @@ def test_get_state_initial_logged_in(self): assert state == { "already_signed_up": True, "captcha": {"completed": False}, - "credentials": {"completed": False, "generated_password": None}, + "credentials": {"completed": False, "custom_password": False, "generated_password": None}, "email": {"address": None, "bad_attempts": 0, "bad_attempts_max": 3, "completed": False, "sent_at": None}, "invite": {"completed": False, "finish_url": None, "initiated_signup": False}, "name": {"given_name": None, "surname": None}, @@ -1249,10 +1249,9 @@ def test_create_user_with_custom_password(self): self._prepare_for_create_user(given_name=given_name, surname=surname, email=email) data = { "use_suggested_password": False, - "custom_password": "9MbKxTHhCDK3Y9hhn6", "use_webauthn": False, } - response = self._create_user(data=data, expect_success=True) + response = self._create_user(data=data, custom_password="9MbKxTHhCDK3Y9hhn6", expect_success=True) assert response.reached_state == SignupState.S6_CREATE_USER with self.session_cookie_anon(self.browser) as client: @@ -1272,10 +1271,11 @@ def test_create_user_with_weak_custom_password(self): self._prepare_for_create_user(given_name=given_name, surname=surname, email=email) data = { "use_suggested_password": True, - "custom_password": "abc123", "use_webauthn": False, } - response = self._create_user(data=data, expect_success=False, expected_message=SignupMsg.weak_custom_password) + response = self._create_user( + data=data, custom_password="abc123", expect_success=False, expected_message=SignupMsg.weak_custom_password + ) assert response.reached_state == SignupState.S6_CREATE_USER def test_create_user_out_of_sync(self): @@ -1382,7 +1382,7 @@ def test_get_state_after_accept_invite(self): assert normalised_data(state, exclude_keys=["expires_time_left", "throttle_time_left", "sent_at"]) == { "already_signed_up": False, "captcha": {"completed": False}, - "credentials": {"completed": False, "generated_password": None}, + "credentials": {"completed": False, "custom_password": False, "generated_password": None}, "email": { "address": "dummy@example.com", "bad_attempts": 0, diff --git a/src/eduid/webapp/signup/views.py b/src/eduid/webapp/signup/views.py index 4242de227..31b68871e 100644 --- a/src/eduid/webapp/signup/views.py +++ b/src/eduid/webapp/signup/views.py @@ -324,12 +324,14 @@ def create_user(use_suggested_password: bool, use_webauthn: bool, custom_passwor session.signup.user_created = True session.signup.credentials.completed = True session.common.eppn = signup_user.eppn - # create payload before clearing passwords + # create payload before clearing generated password state = session.signup.to_dict() - state["credentials"]["custom_password"] = custom_password + if custom_password is not None: + state["credentials"]["custom_password"] = True + state["credentials"]["generated_password"] = None # clear passwords from session and namespace - session.signup.credentials.generated_password = None del custom_password + session.signup.credentials.generated_password = None # clear signup session if the user is done if not session.signup.invite.initiated_signup: del session.signup