Search in sources :

Example 1 with MustChangePasswordException

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;
}
Also used : MustChangePasswordException(eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException) IdmAuthenticationException(eu.bcvsolutions.idm.core.security.api.exception.IdmAuthenticationException) LoginDto(eu.bcvsolutions.idm.core.security.api.dto.LoginDto) TwoFactorAuthenticationRequiredException(eu.bcvsolutions.idm.core.security.api.exception.TwoFactorAuthenticationRequiredException) MustChangePasswordException(eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException) IdmAuthenticationException(eu.bcvsolutions.idm.core.security.api.exception.IdmAuthenticationException) TwoFactorAuthenticationRequiredException(eu.bcvsolutions.idm.core.security.api.exception.TwoFactorAuthenticationRequiredException)

Example 2 with MustChangePasswordException

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;
    }
}
Also used : IdmTokenDto(eu.bcvsolutions.idm.core.api.dto.IdmTokenDto) Jwt(org.springframework.security.jwt.Jwt) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) GuardedString(eu.bcvsolutions.idm.core.security.api.domain.GuardedString) IOException(java.io.IOException) EntityNotFoundException(eu.bcvsolutions.idm.core.api.exception.EntityNotFoundException) CodeGenerationException(dev.samstevens.totp.exceptions.CodeGenerationException) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) EntityNotFoundException(eu.bcvsolutions.idm.core.api.exception.EntityNotFoundException) IOException(java.io.IOException) MustChangePasswordException(eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException) MustChangePasswordException(eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException) IdmPasswordDto(eu.bcvsolutions.idm.core.api.dto.IdmPasswordDto) IdmJwtAuthenticationDto(eu.bcvsolutions.idm.core.security.api.dto.IdmJwtAuthenticationDto) UUID(java.util.UUID) IdmIdentityDto(eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto) LoginDto(eu.bcvsolutions.idm.core.security.api.dto.LoginDto) Transactional(org.springframework.transaction.annotation.Transactional)

Example 3 with MustChangePasswordException

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;
    }
}
Also used : ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) GuardedString(eu.bcvsolutions.idm.core.security.api.domain.GuardedString) LinkedList(java.util.LinkedList) TwoFactorAuthenticationRequiredException(eu.bcvsolutions.idm.core.security.api.exception.TwoFactorAuthenticationRequiredException) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) MustChangePasswordException(eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException) MustChangePasswordException(eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException) ZonedDateTime(java.time.ZonedDateTime) IdmPasswordDto(eu.bcvsolutions.idm.core.api.dto.IdmPasswordDto) LoginDto(eu.bcvsolutions.idm.core.security.api.dto.LoginDto) IdmIdentityDto(eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto) DateTimeFormatter(java.time.format.DateTimeFormatter) Authenticator(eu.bcvsolutions.idm.core.security.api.authentication.Authenticator) TwoFactorAuthenticationRequiredException(eu.bcvsolutions.idm.core.security.api.exception.TwoFactorAuthenticationRequiredException)

Aggregations

LoginDto (eu.bcvsolutions.idm.core.security.api.dto.LoginDto)3 MustChangePasswordException (eu.bcvsolutions.idm.core.security.api.exception.MustChangePasswordException)3 IdmIdentityDto (eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto)2 IdmPasswordDto (eu.bcvsolutions.idm.core.api.dto.IdmPasswordDto)2 ResultCodeException (eu.bcvsolutions.idm.core.api.exception.ResultCodeException)2 GuardedString (eu.bcvsolutions.idm.core.security.api.domain.GuardedString)2 TwoFactorAuthenticationRequiredException (eu.bcvsolutions.idm.core.security.api.exception.TwoFactorAuthenticationRequiredException)2 CodeGenerationException (dev.samstevens.totp.exceptions.CodeGenerationException)1 IdmTokenDto (eu.bcvsolutions.idm.core.api.dto.IdmTokenDto)1 EntityNotFoundException (eu.bcvsolutions.idm.core.api.exception.EntityNotFoundException)1 Authenticator (eu.bcvsolutions.idm.core.security.api.authentication.Authenticator)1 IdmJwtAuthenticationDto (eu.bcvsolutions.idm.core.security.api.dto.IdmJwtAuthenticationDto)1 IdmAuthenticationException (eu.bcvsolutions.idm.core.security.api.exception.IdmAuthenticationException)1 IOException (java.io.IOException)1 ZonedDateTime (java.time.ZonedDateTime)1 DateTimeFormatter (java.time.format.DateTimeFormatter)1 LinkedList (java.util.LinkedList)1 UUID (java.util.UUID)1 Jwt (org.springframework.security.jwt.Jwt)1 Transactional (org.springframework.transaction.annotation.Transactional)1