Skip to content

Commit 93044f7

Browse files
committed
feat: modify logic to block token issue after repeated attempts
Signed-off-by: ImMin5 <[email protected]>
1 parent 4bab2d3 commit 93044f7

File tree

1 file changed

+39
-24
lines changed

1 file changed

+39
-24
lines changed

src/spaceone/identity/service/token_service.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import copy
12
import logging
23
from typing import List, Tuple
34
from collections import OrderedDict
@@ -72,6 +73,7 @@ def issue(self, params: TokenIssueRequest) -> Union[TokenResponse, dict]:
7273
timeout = params.timeout
7374
verify_code = params.verify_code
7475
credentials = params.credentials
76+
auth_type = params.auth_type
7577

7678
private_jwk = self.domain_secret_mgr.get_domain_private_key(domain_id=domain_id)
7779
refresh_private_jwk = self.domain_secret_mgr.get_domain_refresh_private_key(
@@ -82,12 +84,12 @@ def issue(self, params: TokenIssueRequest) -> Union[TokenResponse, dict]:
8284
self._check_domain_state(domain_id)
8385

8486
try:
85-
token_mgr = TokenManager.get_token_manager_by_auth_type(params.auth_type)
87+
token_mgr = TokenManager.get_token_manager_by_auth_type(auth_type)
8688
token_mgr.authenticate(
8789
domain_id, verify_code=verify_code, credentials=credentials
8890
)
8991
except Exception as e:
90-
self._increment_issue_attempts(domain_id, credentials)
92+
self._increment_issue_attempts(domain_id, credentials, auth_type)
9193
raise e
9294

9395
user_vo = token_mgr.user
@@ -97,11 +99,8 @@ def issue(self, params: TokenIssueRequest) -> Union[TokenResponse, dict]:
9799

98100
mfa_user_id = user_vo.user_id
99101

100-
if self._check_login_protocol_with_user_auth_type(params.auth_type, domain_id):
101-
if (
102-
user_mfa.get("state", "DISABLED") == "ENABLED"
103-
and params.auth_type != "MFA"
104-
):
102+
if self._check_login_protocol_with_user_auth_type(auth_type, domain_id):
103+
if user_mfa.get("state", "DISABLED") == "ENABLED" and auth_type != "MFA":
105104
mfa_manager = MFAManager.get_manager_by_mfa_type(mfa_type)
106105
if mfa_type == "EMAIL":
107106
mfa_email = user_mfa["options"].get("email")
@@ -137,7 +136,7 @@ def issue(self, params: TokenIssueRequest) -> Union[TokenResponse, dict]:
137136
permissions=permissions,
138137
)
139138

140-
self._clear_issue_attempts(domain_id, credentials)
139+
self._clear_issue_attempts(domain_id, credentials, auth_type)
141140

142141
return TokenResponse(**token_info)
143142

@@ -435,42 +434,58 @@ def _check_login_protocol_with_user_auth_type(
435434

436435
return True
437436

438-
@staticmethod
439-
def _check_user_required_actions(required_actions: list, user_id: str) -> None:
440-
if required_actions:
441-
for required_action in required_actions:
442-
if required_action == "UPDATE_PASSWORD":
443-
raise ERROR_UPDATE_PASSWORD_REQUIRED(user_id=user_id)
437+
def _load_conf(self):
438+
identity_conf = config.get_global("IDENTITY") or {}
439+
token_conf = identity_conf.get("token", {})
440+
441+
self.ISSUE_BLOCK_TIME = token_conf.get("issue_block_time", 300)
442+
self.MAX_ISSUE_ATTEMPTS = token_conf.get("max_issue_attempts", 10)
443+
444+
def _increment_issue_attempts(
445+
self, domain_id: str, credentials: dict, auth_type: str
446+
) -> None:
444447

445-
def _increment_issue_attempts(self, domain_id: str, credentials: dict) -> None:
446448
if cache.is_set():
447-
ordered_credentials = OrderedDict(sorted(credentials.items()))
449+
copied_credentials = self._get_credentials_without_password(
450+
credentials, auth_type
451+
)
452+
453+
ordered_credentials = OrderedDict(sorted(copied_credentials.items()))
448454
hashed_credentials = utils.dict_to_hash(ordered_credentials)
449455
cache_key = f"identity:token:issue-attempt:{domain_id}:{hashed_credentials}"
450456

451457
issue_attempts: int = cache.get(cache_key) or 0
452458

453459
if issue_attempts == 0:
454460
cache.set(cache_key, value=0, expire=self.ISSUE_BLOCK_TIME)
461+
elif issue_attempts < self.MAX_ISSUE_ATTEMPTS:
462+
_LOGGER.debug(f"[_increment_login_attempts] {issue_attempts} attempts")
455463
elif issue_attempts == self.MAX_ISSUE_ATTEMPTS:
456464
cache.set(cache_key, value=issue_attempts, expire=self.ISSUE_BLOCK_TIME)
457-
_LOGGER.debug(f"[_increment_login_attempts] {issue_attempts} attempts")
458465
elif issue_attempts > self.MAX_ISSUE_ATTEMPTS:
459466
raise ERROR_LOGIN_BLOCKED()
460467

461468
cache.increment(cache_key)
462469

463-
@staticmethod
464-
def _clear_issue_attempts(domain_id: str, credentials: dict) -> None:
470+
def _clear_issue_attempts(
471+
self, domain_id: str, credentials: dict, auth_type: str
472+
) -> None:
465473
if cache.is_set():
474+
credentials = self._get_credentials_without_password(credentials, auth_type)
466475
ordered_credentials = OrderedDict(sorted(credentials.items()))
467476
hashed_credentials = utils.dict_to_hash(ordered_credentials)
468477
cache_key = f"identity:token:issue-attempt:{domain_id}:{hashed_credentials}"
469478
cache.delete(cache_key)
470479

471-
def _load_conf(self):
472-
identity_conf = config.get_global("IDENTITY") or {}
473-
token_conf = identity_conf.get("token", {})
480+
@staticmethod
481+
def _check_user_required_actions(required_actions: list, user_id: str) -> None:
482+
if required_actions:
483+
for required_action in required_actions:
484+
if required_action == "UPDATE_PASSWORD":
485+
raise ERROR_UPDATE_PASSWORD_REQUIRED(user_id=user_id)
474486

475-
self.ISSUE_BLOCK_TIME = token_conf.get("issue_block_time", 300)
476-
self.MAX_ISSUE_ATTEMPTS = token_conf.get("max_issue_attempts", 10)
487+
@staticmethod
488+
def _get_credentials_without_password(credentials: dict, auth_type: str) -> dict:
489+
if auth_type == "LOCAL":
490+
credentials.pop("password", None)
491+
return credentials

0 commit comments

Comments
 (0)