use of eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException in project CzechIdMng by bcvsolutions.
the class BasicIdmAuthenticationFilter method authorize.
@Override
public boolean authorize(String token, HttpServletRequest req, HttpServletResponse res) {
try {
LoginDto loginDto = createLoginDto(getBasicCredentials(token));
authManager.authenticate(loginDto);
LOG.debug("User [{}] successfully logged in.", loginDto.getUsername());
return true;
} catch (MustChangePasswordException | TwoFactorAuthenticationRequiredException ex) {
// publish additional authentication requirement
throw ex;
} catch (IdmAuthenticationException e) {
LOG.warn("Authentication exception raised during basic authentication: [{}].", e.getMessage());
} catch (Exception e) {
LOG.warn("Exception was raised during basic authentication: [{}].", e.getMessage());
}
return false;
}
use of eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException in project CzechIdMng by bcvsolutions.
the class DefaultTwoFactorAuthenticationManager method authenticate.
@Override
@Transactional
public LoginDto authenticate(LoginDto loginTwoFactorRequestDto) {
Assert.notNull(loginTwoFactorRequestDto, "Login request is required.");
//
IdmJwtAuthenticationDto claims = null;
String loggedAction = siemLogger.buildAction(SiemLoggerManager.LOGIN_LEVEL_KEY);
String targetName = loginTwoFactorRequestDto.getUsername();
String targetUuid = null;
try {
Optional<Jwt> jwt = HttpFilterUtils.parseToken(loginTwoFactorRequestDto.getToken());
if (!jwt.isPresent()) {
throw new ResultCodeException(CoreResultCode.AUTH_FAILED, "Verification code must be filled");
}
HttpFilterUtils.verifyToken(jwt.get(), jwtAuthenticationMapper.getVerifier());
// authentication dto from request
try {
claims = jwtAuthenticationMapper.getClaims(jwt.get());
targetName = claims.getCurrentUsername();
targetUuid = Objects.toString(claims.getCurrentIdentityId(), "");
} catch (IOException ex) {
throw new ResultCodeException(CoreResultCode.TOKEN_READ_FAILED, ex);
}
// we need to check expiration, before current (automatically prolonged) token is used by mapper
if (claims.getExpiration() != null && claims.getExpiration().isBefore(ZonedDateTime.now())) {
throw new ResultCodeException(CoreResultCode.AUTH_EXPIRED);
}
UUID identityId = claims.getCurrentIdentityId();
IdmIdentityDto identity = identityService.get(identityId);
if (identity == null) {
throw new EntityNotFoundException(IdmIdentityDto.class, identityId);
}
IdmPasswordDto password = passwordService.findOneByIdentity(identityId);
if (password == null) {
throw new EntityNotFoundException(IdmPasswordDto.class, identityId);
}
if (!verifyCode(password, loginTwoFactorRequestDto.getPassword())) {
throw new ResultCodeException(CoreResultCode.TWO_FACTOR_VERIFICATION_CODE_FAILED);
}
//
if (password.isMustChange() && !loginTwoFactorRequestDto.isSkipMustChange()) {
throw new MustChangePasswordException(claims.getCurrentUsername());
}
// set token verified
IdmTokenDto token = tokenManager.getToken(claims.getId());
token.setSecretVerified(true);
// and login - new login dto new to be constructed to preserve original login metadata
LoginDto loginDto = new LoginDto();
loginDto.setUsername(claims.getCurrentUsername());
loginDto.setAuthenticationModule(claims.getFromModule());
//
LoginDto resultLoginDto = jwtAuthenticationService.createJwtAuthenticationAndAuthenticate(loginDto, identity, token);
siemLogger.log(loggedAction, SiemLoggerManager.SUCCESS_ACTION_STATUS, targetName, targetUuid, null, null, null, null);
return resultLoginDto;
} catch (Exception e) {
siemLogger.log(loggedAction, SiemLoggerManager.FAILED_ACTION_STATUS, targetName, targetUuid, null, null, null, e.getMessage());
throw e;
}
}
use of eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException in project CzechIdMng by bcvsolutions.
the class DefaultAuthenticationManager method authenticate.
@Override
public LoginDto authenticate(LoginDto loginDto) {
List<LoginDto> resultsList = new LinkedList<>();
RuntimeException firstFailure = null;
String logAction = siemLogger.buildAction(SiemLoggerManager.LOGIN_LEVEL_KEY, SiemLoggerManager.LOGIN_SUBLEVEL_KEY);
IdmIdentityDto identity = identityService.getByUsername(loginDto.getUsername());
if (identity == null) {
// just for logging purpose
identity = new IdmIdentityDto();
identity.setUsername(loginDto.getUsername());
}
// check if user can log in and hasn't administrator permission
try {
IdmPasswordDto passwordDto = passwordService.findOrCreateByIdentity(loginDto.getUsername());
if (passwordDto == null) {
throw new ResultCodeException(CoreResultCode.AUTH_FAILED, "Invalid login or password.");
}
if (passwordDto.getBlockLoginDate() != null && passwordDto.getBlockLoginDate().isAfter(ZonedDateTime.now())) {
LOG.info("Identity {} has blocked login to IdM.", loginDto.getUsername());
IdmIdentityDto identityDto = DtoUtils.getEmbedded(passwordDto, IdmPassword_.identity);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(configurationService.getDateTimeSecondsFormat());
ZonedDateTime blockLoginDate = passwordDto.getBlockLoginDate();
String dateAsString = blockLoginDate.format(formatter);
// Block login date can be set manually by password metadata,
// so block login date can be more than int amount.
long blockMillies = blockLoginDate.toInstant().toEpochMilli();
long nowMillis = ZonedDateTime.now().toInstant().toEpochMilli();
long different = blockMillies - nowMillis;
different = different / 1000;
throw new ResultCodeException(CoreResultCode.AUTH_BLOCKED, ImmutableMap.of("username", identityDto.getUsername(), "date", dateAsString, "seconds", different, "unsuccessfulAttempts", passwordDto.getUnsuccessfulAttempts()));
}
//
for (Authenticator authenticator : getEnabledAuthenticators()) {
LOG.debug("AuthenticationManager call authenticate by [{}].", authenticator.getName());
try {
LoginDto result = authenticator.authenticate(cloneLoginDto(loginDto));
if (result == null) {
// continue, authenticator is not implemented or etc.
continue;
}
if (authenticator.getExceptedResult() == AuthenticationResponseEnum.SUFFICIENT) {
checkAdditionalAuthenticationRequirements(passwordDto, result);
passwordDto = passwordService.setLastSuccessfulLogin(passwordDto);
siemLogger.log(logAction, SiemLoggerManager.SUCCESS_ACTION_STATUS, identity, null, null, null);
return result;
}
// if otherwise add result too list and continue
resultsList.add(result);
} catch (MustChangePasswordException | TwoFactorAuthenticationRequiredException ex) {
// publish additional authentication requirement
throw ex;
} catch (RuntimeException e) {
// if excepted response is REQUISITE exit immediately with error
if (authenticator.getExceptedResult() == AuthenticationResponseEnum.REQUISITE) {
blockLogin(passwordDto, loginDto);
//
throw e;
}
// if otherwise save first failure into exception
if (firstFailure == null) {
firstFailure = e;
}
}
}
// authenticator is sorted by implement ordered, return first success authenticate authenticator, if don't exist any otherwise throw first failure
if (resultsList.isEmpty()) {
blockLogin(passwordDto, loginDto);
throw firstFailure;
}
//
LoginDto result = resultsList.get(0);
checkAdditionalAuthenticationRequirements(passwordDto, result);
passwordDto = passwordService.setLastSuccessfulLogin(passwordDto);
//
siemLogger.log(logAction, SiemLoggerManager.SUCCESS_ACTION_STATUS, identity, null, null, null);
return result;
} catch (TwoFactorAuthenticationRequiredException tfaEx) {
// skip logging, 2FA is needed, result will be logged there
throw tfaEx;
} catch (Exception e) {
siemLogger.log(logAction, SiemLoggerManager.FAILED_ACTION_STATUS, identity, null, null, e.getMessage());
throw e;
}
}
Aggregations