Search in sources :

Example 1 with AccountInactiveException

use of io.gravitee.am.common.exception.authentication.AccountInactiveException in project gravitee-access-management by gravitee-io.

the class UserServiceImpl method forgotPassword.

@Override
public Completable forgotPassword(ForgotPasswordParameters params, Client client, io.gravitee.am.identityprovider.api.User principal) {
    final String email = params.getEmail();
    if (email != null && !emailValidator.validate(email)) {
        return Completable.error(new EmailFormatInvalidException(email));
    }
    return userService.findByDomainAndCriteria(domain.getId(), params.buildCriteria()).flatMap(users -> {
        List<User> foundUsers = new ArrayList<>(users);
        // narrow users
        if (users.size() > 1) {
            // filter by identity provider
            if (client.getIdentityProviders() != null && !client.getIdentityProviders().isEmpty()) {
                foundUsers = users.stream().flatMap(u -> client.getIdentityProviders().stream().map(appIdp -> entry(u, appIdp.getIdentity()))).filter(entry -> {
                    var user = entry.getKey();
                    var identity = entry.getValue();
                    return Objects.equals(user.getSource(), identity);
                }).map(Entry::getKey).collect(toList());
            }
            if (foundUsers.size() > 1) {
                // try to filter by latest application used
                List<User> filteredSourceUsers = users.stream().filter(u -> u.getClient() == null || client.getId().equals(u.getClient())).collect(toList());
                if (!filteredSourceUsers.isEmpty()) {
                    foundUsers = new ArrayList<>(filteredSourceUsers);
                }
            }
        }
        // If multiple results, check if ConfirmIdentity isn't required before returning the first User.
        if (foundUsers.size() == 1 || (foundUsers.size() > 1 && !params.isConfirmIdentityEnabled())) {
            User user = foundUsers.get(0);
            // check if user can update its password according to its identity provider type
            return identityProviderManager.getUserProvider(user.getSource()).switchIfEmpty(Single.error(new UserInvalidException("User [ " + user.getUsername() + " ] cannot be updated because its identity provider does not support user provisioning"))).flatMap(userProvider -> {
                // if user registration is not completed and force registration option is disabled throw invalid account exception
                if (user.isInactive() && !forceUserRegistration(domain, client)) {
                    return Single.error(new AccountInactiveException("User [ " + user.getUsername() + " ] needs to complete the activation process"));
                }
                // fetch latest information from the identity provider and return the user
                return userProvider.findByUsername(user.getUsername()).map(Optional::ofNullable).defaultIfEmpty(Optional.empty()).flatMapSingle(optUser -> {
                    if (optUser.isEmpty()) {
                        return Single.just(user);
                    }
                    return userService.update(enhanceUser(user, optUser.get()));
                });
            });
        }
        if (foundUsers.size() > 1) {
            throw new EnforceUserIdentityException();
        }
        // fallback to registered user providers if user has never been authenticated
        if (client.getIdentityProviders() == null || client.getIdentityProviders().isEmpty()) {
            return Single.error(new UserNotFoundException(email));
        }
        if (Strings.isNullOrEmpty(params.getEmail()) & StringUtils.isEmpty(params.getUsername())) {
            // no user found using criteria. email & username are missing, unable to search the user through UserProvider
            return Single.error(new UserNotFoundException(email));
        }
        // email used in priority for backward compatibility
        return Observable.fromIterable(client.getIdentityProviders()).flatMapMaybe(authProvider -> identityProviderManager.getUserProvider(authProvider.getIdentity()).flatMap(userProvider -> {
            final String username = params.getUsername();
            final Maybe<io.gravitee.am.identityprovider.api.User> findQuery = Strings.isNullOrEmpty(email) ? userProvider.findByUsername(username) : userProvider.findByEmail(email);
            return findQuery.map(user -> Optional.of(new UserAuthentication(user, authProvider.getIdentity()))).defaultIfEmpty(Optional.empty()).onErrorReturnItem(Optional.empty());
        }).defaultIfEmpty(Optional.empty())).takeUntil((Predicate<? super Optional<UserAuthentication>>) Optional::isPresent).lastOrError().flatMap(optional -> {
            // be sure to not duplicate an existing user
            if (optional.isEmpty()) {
                return Single.error(new UserNotFoundException());
            }
            final UserAuthentication idpUser = optional.get();
            return userService.findByDomainAndUsernameAndSource(domain.getId(), idpUser.getUser().getUsername(), idpUser.getSource()).switchIfEmpty(Maybe.defer(() -> userService.findByDomainAndExternalIdAndSource(domain.getId(), idpUser.getUser().getId(), idpUser.getSource()))).map(Optional::ofNullable).defaultIfEmpty(Optional.empty()).flatMapSingle(optEndUser -> {
                if (optEndUser.isEmpty()) {
                    return userService.create(convert(idpUser.getUser(), idpUser.getSource()));
                }
                return userService.update(enhanceUser(optEndUser.get(), idpUser.getUser()));
            });
        }).onErrorResumeNext(Single.error(new UserNotFoundException(email != null ? email : params.getUsername())));
    }).doOnSuccess(user -> new Thread(() -> emailService.send(Template.RESET_PASSWORD, user, client)).start()).doOnSuccess(user1 -> {
        // reload principal
        io.gravitee.am.identityprovider.api.User principal1 = reloadPrincipal(principal, user1);
        auditService.report(AuditBuilder.builder(UserAuditBuilder.class).domain(domain.getId()).client(client).principal(principal1).type(EventType.FORGOT_PASSWORD_REQUESTED));
    }).doOnError(throwable -> auditService.report(AuditBuilder.builder(UserAuditBuilder.class).domain(domain.getId()).client(client).principal(principal).type(EventType.FORGOT_PASSWORD_REQUESTED).throwable(throwable))).ignoreElement();
}
Also used : java.util(java.util) Client(io.gravitee.am.model.oidc.Client) AccountInactiveException(io.gravitee.am.common.exception.authentication.AccountInactiveException) IdentityProviderManager(io.gravitee.am.gateway.handler.common.auth.idp.IdentityProviderManager) UserService(io.gravitee.am.gateway.handler.root.service.user.UserService) Autowired(org.springframework.beans.factory.annotation.Autowired) ConstantKeys(io.gravitee.am.common.utils.ConstantKeys) EmailService(io.gravitee.am.gateway.handler.common.email.EmailService) AuditService(io.gravitee.am.service.AuditService) DefaultUser(io.gravitee.am.identityprovider.api.DefaultUser) ForgotPasswordParameters(io.gravitee.am.gateway.handler.root.service.user.model.ForgotPasswordParameters) io.gravitee.am.service.exception(io.gravitee.am.service.exception) Strings(com.google.common.base.Strings) EnrolledFactor(io.gravitee.am.model.factor.EnrolledFactor) AuditBuilder(io.gravitee.am.service.reporter.builder.AuditBuilder) JWTService(io.gravitee.am.gateway.handler.common.jwt.JWTService) Qualifier(org.springframework.beans.factory.annotation.Qualifier) CredentialService(io.gravitee.am.service.CredentialService) Observable(io.reactivex.Observable) Objects.isNull(java.util.Objects.isNull) ClientSyncService(io.gravitee.am.gateway.handler.common.client.ClientSyncService) Map.entry(java.util.Map.entry) io.reactivex(io.reactivex) LoginAttemptService(io.gravitee.am.service.LoginAttemptService) FALSE(java.lang.Boolean.FALSE) JWTParser(io.gravitee.am.jwt.JWTParser) StandardClaims(io.gravitee.am.common.oidc.StandardClaims) Optional.ofNullable(java.util.Optional.ofNullable) ResetPasswordResponse(io.gravitee.am.gateway.handler.root.service.response.ResetPasswordResponse) EventType(io.gravitee.am.common.audit.EventType) Predicate(io.reactivex.functions.Predicate) RandomString(io.gravitee.am.common.utils.RandomString) io.gravitee.am.model(io.gravitee.am.model) TokenService(io.gravitee.am.service.TokenService) LoginAttemptCriteria(io.gravitee.am.repository.management.api.search.LoginAttemptCriteria) Collectors.toList(java.util.stream.Collectors.toList) UserToken(io.gravitee.am.gateway.handler.root.service.user.model.UserToken) UserAuditBuilder(io.gravitee.am.service.reporter.builder.management.UserAuditBuilder) EmailValidator(io.gravitee.am.service.validators.email.EmailValidator) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) UserValidator(io.gravitee.am.service.validators.user.UserValidator) Entry(java.util.Map.Entry) RegistrationResponse(io.gravitee.am.gateway.handler.root.service.response.RegistrationResponse) Objects.nonNull(java.util.Objects.nonNull) AccountSettings(io.gravitee.am.model.account.AccountSettings) StringUtils(org.springframework.util.StringUtils) DefaultUser(io.gravitee.am.identityprovider.api.DefaultUser) RandomString(io.gravitee.am.common.utils.RandomString) UserAuditBuilder(io.gravitee.am.service.reporter.builder.management.UserAuditBuilder) Predicate(io.reactivex.functions.Predicate) Entry(java.util.Map.Entry) AccountInactiveException(io.gravitee.am.common.exception.authentication.AccountInactiveException)

Example 2 with AccountInactiveException

use of io.gravitee.am.common.exception.authentication.AccountInactiveException in project gravitee-access-management by gravitee-io.

the class UserServiceImpl method resetPassword.

@Override
public Single<ResetPasswordResponse> resetPassword(Client client, User user, io.gravitee.am.identityprovider.api.User principal) {
    // get account settings
    final AccountSettings accountSettings = AccountSettings.getInstance(domain, client);
    // if user registration is not completed and force registration option is disabled throw invalid account exception
    if (user.isInactive() && !forceUserRegistration(domain, client)) {
        return Single.error(new AccountInactiveException("User needs to complete the activation process"));
    }
    // only idp manage password, find user idp and update its password
    return identityProviderManager.getUserProvider(user.getSource()).switchIfEmpty(Maybe.error(new UserProviderNotFoundException(user.getSource()))).flatMapSingle(userProvider -> userProvider.findByUsername(user.getUsername()).switchIfEmpty(Maybe.error(new UserNotFoundException(user.getUsername()))).flatMapSingle(idpUser -> {
        // set password
        ((DefaultUser) idpUser).setCredentials(user.getPassword());
        return userProvider.update(idpUser.getId(), idpUser);
    }).onErrorResumeNext(ex -> {
        if (ex instanceof UserNotFoundException) {
            // idp user not found, create its account
            return userProvider.create(convert(user));
        }
        return Single.error(ex);
    })).flatMap(idpUser -> {
        // if user was in pre-registration mode, end the registration process
        if (user.isPreRegistration()) {
            user.setRegistrationCompleted(true);
            user.setEnabled(true);
        }
        user.setAccountNonLocked(true);
        user.setAccountLockedAt(null);
        user.setAccountLockedUntil(null);
        user.setPassword(null);
        user.setExternalId(idpUser.getId());
        user.setLastPasswordReset(new Date());
        user.setUpdatedAt(new Date());
        // additional information
        extractAdditionalInformation(user, idpUser.getAdditionalInformation());
        // set login information
        if (accountSettings != null && accountSettings.isAutoLoginAfterResetPassword()) {
            user.setLoggedAt(new Date());
            user.setLoginsCount(user.getLoginsCount() + 1);
        }
        return userService.update(user);
    }).flatMap(user1 -> {
        LoginAttemptCriteria criteria = new LoginAttemptCriteria.Builder().domain(user1.getReferenceId()).client(user1.getClient()).username(user1.getUsername()).build();
        return loginAttemptService.reset(criteria).andThen(Single.just(user1));
    }).flatMap(user1 -> {
        if (accountSettings != null && accountSettings.isDeletePasswordlessDevicesAfterResetPassword()) {
            return credentialService.deleteByUserId(user1.getReferenceType(), user1.getReferenceId(), user1.getId()).andThen(Single.just(user1));
        }
        return Single.just(user1);
    }).flatMap(userService::enhance).map(user1 -> new ResetPasswordResponse(user1, accountSettings != null ? accountSettings.getRedirectUriAfterResetPassword() : null, accountSettings != null ? accountSettings.isAutoLoginAfterResetPassword() : false)).doOnSuccess(response -> auditService.report(AuditBuilder.builder(UserAuditBuilder.class).domain(domain.getId()).client(client).principal(principal).type(EventType.USER_PASSWORD_RESET).user(user))).doOnError(throwable -> auditService.report(AuditBuilder.builder(UserAuditBuilder.class).domain(domain.getId()).client(client).principal(principal).type(EventType.USER_PASSWORD_RESET).user(user).throwable(throwable)));
}
Also used : AccountSettings(io.gravitee.am.model.account.AccountSettings) java.util(java.util) Client(io.gravitee.am.model.oidc.Client) AccountInactiveException(io.gravitee.am.common.exception.authentication.AccountInactiveException) IdentityProviderManager(io.gravitee.am.gateway.handler.common.auth.idp.IdentityProviderManager) UserService(io.gravitee.am.gateway.handler.root.service.user.UserService) Autowired(org.springframework.beans.factory.annotation.Autowired) ConstantKeys(io.gravitee.am.common.utils.ConstantKeys) EmailService(io.gravitee.am.gateway.handler.common.email.EmailService) AuditService(io.gravitee.am.service.AuditService) DefaultUser(io.gravitee.am.identityprovider.api.DefaultUser) ForgotPasswordParameters(io.gravitee.am.gateway.handler.root.service.user.model.ForgotPasswordParameters) io.gravitee.am.service.exception(io.gravitee.am.service.exception) Strings(com.google.common.base.Strings) EnrolledFactor(io.gravitee.am.model.factor.EnrolledFactor) AuditBuilder(io.gravitee.am.service.reporter.builder.AuditBuilder) JWTService(io.gravitee.am.gateway.handler.common.jwt.JWTService) Qualifier(org.springframework.beans.factory.annotation.Qualifier) CredentialService(io.gravitee.am.service.CredentialService) Observable(io.reactivex.Observable) Objects.isNull(java.util.Objects.isNull) ClientSyncService(io.gravitee.am.gateway.handler.common.client.ClientSyncService) Map.entry(java.util.Map.entry) io.reactivex(io.reactivex) LoginAttemptService(io.gravitee.am.service.LoginAttemptService) FALSE(java.lang.Boolean.FALSE) JWTParser(io.gravitee.am.jwt.JWTParser) StandardClaims(io.gravitee.am.common.oidc.StandardClaims) Optional.ofNullable(java.util.Optional.ofNullable) ResetPasswordResponse(io.gravitee.am.gateway.handler.root.service.response.ResetPasswordResponse) EventType(io.gravitee.am.common.audit.EventType) Predicate(io.reactivex.functions.Predicate) RandomString(io.gravitee.am.common.utils.RandomString) io.gravitee.am.model(io.gravitee.am.model) TokenService(io.gravitee.am.service.TokenService) LoginAttemptCriteria(io.gravitee.am.repository.management.api.search.LoginAttemptCriteria) Collectors.toList(java.util.stream.Collectors.toList) UserToken(io.gravitee.am.gateway.handler.root.service.user.model.UserToken) UserAuditBuilder(io.gravitee.am.service.reporter.builder.management.UserAuditBuilder) EmailValidator(io.gravitee.am.service.validators.email.EmailValidator) ExpiredJWTException(io.gravitee.am.common.exception.jwt.ExpiredJWTException) UserValidator(io.gravitee.am.service.validators.user.UserValidator) Entry(java.util.Map.Entry) RegistrationResponse(io.gravitee.am.gateway.handler.root.service.response.RegistrationResponse) Objects.nonNull(java.util.Objects.nonNull) AccountSettings(io.gravitee.am.model.account.AccountSettings) StringUtils(org.springframework.util.StringUtils) ResetPasswordResponse(io.gravitee.am.gateway.handler.root.service.response.ResetPasswordResponse) LoginAttemptCriteria(io.gravitee.am.repository.management.api.search.LoginAttemptCriteria) AccountInactiveException(io.gravitee.am.common.exception.authentication.AccountInactiveException)

Aggregations

Strings (com.google.common.base.Strings)2 EventType (io.gravitee.am.common.audit.EventType)2 AccountInactiveException (io.gravitee.am.common.exception.authentication.AccountInactiveException)2 ExpiredJWTException (io.gravitee.am.common.exception.jwt.ExpiredJWTException)2 StandardClaims (io.gravitee.am.common.oidc.StandardClaims)2 ConstantKeys (io.gravitee.am.common.utils.ConstantKeys)2 RandomString (io.gravitee.am.common.utils.RandomString)2 IdentityProviderManager (io.gravitee.am.gateway.handler.common.auth.idp.IdentityProviderManager)2 ClientSyncService (io.gravitee.am.gateway.handler.common.client.ClientSyncService)2 EmailService (io.gravitee.am.gateway.handler.common.email.EmailService)2 JWTService (io.gravitee.am.gateway.handler.common.jwt.JWTService)2 RegistrationResponse (io.gravitee.am.gateway.handler.root.service.response.RegistrationResponse)2 ResetPasswordResponse (io.gravitee.am.gateway.handler.root.service.response.ResetPasswordResponse)2 UserService (io.gravitee.am.gateway.handler.root.service.user.UserService)2 ForgotPasswordParameters (io.gravitee.am.gateway.handler.root.service.user.model.ForgotPasswordParameters)2 UserToken (io.gravitee.am.gateway.handler.root.service.user.model.UserToken)2 DefaultUser (io.gravitee.am.identityprovider.api.DefaultUser)2 JWTParser (io.gravitee.am.jwt.JWTParser)2 io.gravitee.am.model (io.gravitee.am.model)2 AccountSettings (io.gravitee.am.model.account.AccountSettings)2