All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openmetadata.service.security.auth.BasicAuthenticator Maven / Gradle / Ivy

There is a newer version: 1.5.11
Show newest version
/*
 *  Copyright 2021 Collate
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  http://www.apache.org/licenses/LICENSE-2.0
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.openmetadata.service.security.auth;

import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED;
import static org.openmetadata.common.utils.CommonUtil.nullOrEmpty;
import static org.openmetadata.schema.api.teams.CreateUser.CreatePasswordType.ADMIN_CREATE;
import static org.openmetadata.schema.auth.ChangePasswordRequest.RequestType.SELF;
import static org.openmetadata.schema.auth.ChangePasswordRequest.RequestType.USER;
import static org.openmetadata.schema.auth.TokenType.EMAIL_VERIFICATION;
import static org.openmetadata.schema.auth.TokenType.PASSWORD_RESET;
import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.BASIC;
import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_EXISTS;
import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_SENDING_ISSUE;
import static org.openmetadata.service.exception.CatalogExceptionMessage.FAILED_SEND_EMAIL;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INCORRECT_OLD_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_TOKEN;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USERNAME_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USER_OR_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT;
import static org.openmetadata.service.exception.CatalogExceptionMessage.PASSWORD_RESET_TOKEN_EXPIRED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_DISABLED_MESSAGE;
import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_NOT_ENABLED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.TOKEN_EXPIRED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.TOKEN_EXPIRY_ERROR;
import static org.openmetadata.service.resources.teams.UserResource.USER_PROTECTED_FIELDS;
import static org.openmetadata.service.util.EmailUtil.getSmtpSettings;
import static org.openmetadata.service.util.UserUtil.getRoleListFromUser;
import static org.openmetadata.service.util.UserUtil.getUser;

import at.favre.lib.crypto.bcrypt.BCrypt;
import freemarker.template.TemplateException;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.core.UriInfo;
import lombok.extern.slf4j.Slf4j;
import org.openmetadata.common.utils.CommonUtil;
import org.openmetadata.schema.TokenInterface;
import org.openmetadata.schema.api.security.AuthorizerConfiguration;
import org.openmetadata.schema.api.teams.CreateUser;
import org.openmetadata.schema.auth.BasicAuthMechanism;
import org.openmetadata.schema.auth.ChangePasswordRequest;
import org.openmetadata.schema.auth.EmailVerificationToken;
import org.openmetadata.schema.auth.JWTAuthMechanism;
import org.openmetadata.schema.auth.LoginRequest;
import org.openmetadata.schema.auth.PasswordResetRequest;
import org.openmetadata.schema.auth.PasswordResetToken;
import org.openmetadata.schema.auth.RefreshToken;
import org.openmetadata.schema.auth.RegistrationRequest;
import org.openmetadata.schema.auth.ServiceTokenType;
import org.openmetadata.schema.auth.TokenRefreshRequest;
import org.openmetadata.schema.email.SmtpSettings;
import org.openmetadata.schema.entity.teams.AuthenticationMechanism;
import org.openmetadata.schema.entity.teams.User;
import org.openmetadata.service.Entity;
import org.openmetadata.service.OpenMetadataApplicationConfig;
import org.openmetadata.service.auth.JwtResponse;
import org.openmetadata.service.exception.CustomExceptionMessage;
import org.openmetadata.service.jdbi3.TokenRepository;
import org.openmetadata.service.jdbi3.UserRepository;
import org.openmetadata.service.security.AuthenticationException;
import org.openmetadata.service.security.SecurityUtil;
import org.openmetadata.service.security.jwt.JWTTokenGenerator;
import org.openmetadata.service.util.EmailUtil;
import org.openmetadata.service.util.EntityUtil;
import org.openmetadata.service.util.JsonUtils;
import org.openmetadata.service.util.PasswordUtil;
import org.openmetadata.service.util.RestUtil.PutResponse;
import org.openmetadata.service.util.TokenUtil;

@Slf4j
public class BasicAuthenticator implements AuthenticatorHandler {
  // No of cycles to perform hashing, increasing too much slows the algorithm
  private static final int HASHING_COST = 12;
  private UserRepository userRepository;
  private TokenRepository tokenRepository;
  private LoginAttemptCache loginAttemptCache;
  private AuthorizerConfiguration authorizerConfiguration;
  private boolean isEmailServiceEnabled;
  private boolean isSelfSignUpAvailable;

  @Override
  public void init(OpenMetadataApplicationConfig config) {
    this.userRepository = (UserRepository) Entity.getEntityRepository(Entity.USER);
    this.tokenRepository = Entity.getTokenRepository();
    this.authorizerConfiguration = config.getAuthorizerConfiguration();
    this.loginAttemptCache = new LoginAttemptCache();
    SmtpSettings smtpSettings = config.getSmtpSettings();
    this.isEmailServiceEnabled = smtpSettings != null && smtpSettings.getEnableSmtpServer();
    this.isSelfSignUpAvailable = config.getAuthenticationConfiguration().getEnableSelfSignup();
  }

  private boolean isEmailServiceEnabled() {
    return getSmtpSettings().getEnableSmtpServer();
  }

  @Override
  public User registerUser(RegistrationRequest newRegistrationRequest) {
    if (isSelfSignUpAvailable) {
      String newRegistrationRequestEmail = newRegistrationRequest.getEmail();
      String[] tokens = newRegistrationRequest.getEmail().split("@");
      String emailDomain = tokens[1];
      Set allowedDomains = authorizerConfiguration.getAllowedEmailRegistrationDomains();
      if (!allowedDomains.contains("all") && !allowedDomains.contains(emailDomain)) {
        LOG.error("Email with this Domain not allowed: " + newRegistrationRequestEmail);
        throw new BadRequestException(
            "Email with the given domain is not allowed. Contact Administrator");
      }
      validateEmailAlreadyExists(newRegistrationRequestEmail);
      PasswordUtil.validatePassword(newRegistrationRequest.getPassword());
      LOG.info("Trying to register new user [" + newRegistrationRequestEmail + "]");
      User newUser = getUserFromRegistrationRequest(newRegistrationRequest);
      // remove auth mechanism from the user
      User registeredUser = userRepository.create(null, newUser);
      registeredUser.setAuthenticationMechanism(null);
      return registeredUser;
    } else {
      throw new CustomExceptionMessage(
          NOT_IMPLEMENTED, SELF_SIGNUP_NOT_ENABLED, SELF_SIGNUP_DISABLED_MESSAGE);
    }
  }

  @Override
  public void confirmEmailRegistration(UriInfo uriInfo, String emailToken) {
    EmailVerificationToken emailVerificationToken =
        (EmailVerificationToken) tokenRepository.findByToken(emailToken);
    User registeredUser =
        userRepository.get(
            null, emailVerificationToken.getUserId(), userRepository.getFieldsWithUserAuth("*"));
    if (Boolean.TRUE.equals(registeredUser.getIsEmailVerified())) {
      LOG.info("User [{}] already registered.", emailToken);
      return;
    }

    // verify Token Expiry
    if (emailVerificationToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) {
      throw new CustomExceptionMessage(
          INTERNAL_SERVER_ERROR,
          TOKEN_EXPIRED,
          String.format(TOKEN_EXPIRY_ERROR, emailVerificationToken.getToken()));
    }

    // Update the user
    registeredUser.setIsEmailVerified(true);
    userRepository.createOrUpdate(uriInfo, registeredUser);

    // deleting the entry for the token from the Database
    tokenRepository.deleteTokenByUserAndType(registeredUser.getId(), EMAIL_VERIFICATION.toString());
  }

  @Override
  public void resendRegistrationToken(UriInfo uriInfo, User registeredUser) throws IOException {
    tokenRepository.deleteTokenByUserAndType(registeredUser.getId(), EMAIL_VERIFICATION.toString());
    sendEmailVerification(uriInfo, registeredUser);
  }

  @Override
  public void sendEmailVerification(UriInfo uriInfo, User user) throws IOException {
    if (isEmailServiceEnabled()) {
      UUID mailVerificationToken = UUID.randomUUID();
      EmailVerificationToken emailVerificationToken =
          TokenUtil.getEmailVerificationToken(user.getId(), mailVerificationToken);
      LOG.info("Generated Email verification token [" + mailVerificationToken + "]");
      String emailVerificationLink =
          String.format(
              "%s/users/registrationConfirmation?user=%s&token=%s",
              getSmtpSettings().getOpenMetadataUrl(),
              user.getFullyQualifiedName(),
              mailVerificationToken);
      try {
        EmailUtil.sendEmailVerification(emailVerificationLink, user);
      } catch (TemplateException e) {
        LOG.error("Error in sending mail to the User : {}", e.getMessage(), e);
        throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
      }
      // insert the token
      tokenRepository.insertToken(emailVerificationToken);
    }
  }

  @Override
  public void sendPasswordResetLink(
      UriInfo uriInfo, User user, String subject, String templateFilePath) throws IOException {
    UUID mailVerificationToken = UUID.randomUUID();
    PasswordResetToken resetToken =
        TokenUtil.getPasswordResetToken(user.getId(), mailVerificationToken);
    LOG.info("Generated Password Reset verification token [" + mailVerificationToken + "]");
    String passwordResetLink =
        String.format(
            "%s/users/password/reset?user=%s&token=%s",
            getSmtpSettings().getOpenMetadataUrl(),
            URLEncoder.encode(user.getName(), StandardCharsets.UTF_8),
            mailVerificationToken);
    try {
      EmailUtil.sendPasswordResetLink(passwordResetLink, user, subject, templateFilePath);
    } catch (TemplateException e) {
      LOG.error("Error in sending mail to the User : {}", e.getMessage(), e);
      throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
    }
    // don't persist tokens delete existing
    tokenRepository.deleteTokenByUserAndType(user.getId(), PASSWORD_RESET.toString());
    tokenRepository.insertToken(resetToken);
  }

  @Override
  public void resetUserPasswordWithToken(UriInfo uriInfo, PasswordResetRequest request)
      throws IOException {
    String tokenID = request.getToken();
    PasswordResetToken passwordResetToken =
        (PasswordResetToken) tokenRepository.findByToken(tokenID);
    Set fields = userRepository.getAllowedFieldsCopy();
    fields.add(USER_PROTECTED_FIELDS);
    User storedUser =
        userRepository.getByName(
            uriInfo,
            request.getUsername(),
            new EntityUtil.Fields(fields, String.join(",", fields)));
    // token validity
    if (!passwordResetToken.getUserId().equals(storedUser.getId())) {
      throw new CustomExceptionMessage(BAD_REQUEST, INVALID_TOKEN, "Invalid Token.");
    }
    verifyPasswordResetTokenExpiry(passwordResetToken);
    // passwords validity
    if (!request.getPassword().equals(request.getConfirmPassword())) {
      throw new IllegalArgumentException("Password and Confirm Password should match");
    }
    PasswordUtil.validatePassword(request.getPassword());

    String newHashedPwd =
        BCrypt.withDefaults().hashToString(HASHING_COST, request.getPassword().toCharArray());
    BasicAuthMechanism newAuthForUser = new BasicAuthMechanism().withPassword(newHashedPwd);

    storedUser.setAuthenticationMechanism(
        new AuthenticationMechanism().withAuthType(BASIC).withConfig(newAuthForUser));

    userRepository.createOrUpdate(uriInfo, storedUser);

    // delete the user's all password reset token as well , since already updated
    tokenRepository.deleteTokenByUserAndType(storedUser.getId(), PASSWORD_RESET.toString());

    // Update user about Password Change
    try {
      EmailUtil.sendAccountStatus(storedUser, "Update Password", "Change Successful");
    } catch (TemplateException ex) {
      LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex);
      throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
    }
    loginAttemptCache.recordSuccessfulLogin(request.getUsername());
  }

  @Override
  public void changeUserPwdWithOldPwd(
      UriInfo uriInfo, String userName, ChangePasswordRequest request) throws IOException {
    // passwords validity
    if (!request.getNewPassword().equals(request.getConfirmPassword())) {
      throw new IllegalArgumentException("Password and Confirm Password should match");
    }
    PasswordUtil.validatePassword(request.getNewPassword());

    // Fetch user
    User storedUser =
        userRepository.getByName(uriInfo, userName, userRepository.getFieldsWithUserAuth("*"));

    // when basic auth is enabled and the user is created through the API without password, the
    // stored auth mechanism for the user is null
    if (storedUser.getAuthenticationMechanism() == null) {
      storedUser.setAuthenticationMechanism(
          new AuthenticationMechanism()
              .withAuthType(BASIC)
              .withConfig(new BasicAuthMechanism().withPassword("")));
    }

    BasicAuthMechanism storedBasicAuthMechanism =
        JsonUtils.convertValue(
            storedUser.getAuthenticationMechanism().getConfig(), BasicAuthMechanism.class);

    String storedHashPassword = storedBasicAuthMechanism.getPassword();
    String newHashedPassword =
        BCrypt.withDefaults().hashToString(HASHING_COST, request.getNewPassword().toCharArray());

    if (request.getRequestType() == SELF
        && !BCrypt.verifyer()
            .verify(request.getOldPassword().toCharArray(), storedHashPassword)
            .verified) {
      throw new CustomExceptionMessage(
          BAD_REQUEST, INCORRECT_OLD_PASSWORD, "Old Password is not correct");
    }

    storedBasicAuthMechanism.setPassword(newHashedPassword);
    storedUser.getAuthenticationMechanism().setConfig(storedBasicAuthMechanism);
    PutResponse response = userRepository.createOrUpdate(uriInfo, storedUser);
    // remove login/details from cache
    loginAttemptCache.recordSuccessfulLogin(userName);

    // in case admin updates , send email to user
    if (request.getRequestType() == USER && isEmailServiceEnabled()) {
      // Send mail
      sendInviteMailToUser(
          uriInfo,
          response.getEntity(),
          String.format("%s: Password Update", EmailUtil.getEmailingEntity()),
          ADMIN_CREATE,
          request.getNewPassword());
    }
  }

  @Override
  public void sendInviteMailToUser(
      UriInfo uriInfo,
      User user,
      String subject,
      CreateUser.CreatePasswordType requestType,
      String pwd)
      throws IOException {
    switch (requestType) {
      case ADMIN_CREATE -> {
        Map templatePopulator = new HashMap<>();
        templatePopulator.put(EmailUtil.ENTITY, EmailUtil.getEmailingEntity());
        templatePopulator.put(EmailUtil.SUPPORT_URL, EmailUtil.getSupportUrl());
        templatePopulator.put(EmailUtil.USERNAME, user.getName());
        templatePopulator.put(EmailUtil.PASSWORD, pwd);
        templatePopulator.put(EmailUtil.APPLICATION_LOGIN_LINK, EmailUtil.getOMUrl());
        try {
          EmailUtil.sendMail(
              subject, templatePopulator, user.getEmail(), EmailUtil.INVITE_RANDOM_PWD, true);
        } catch (TemplateException ex) {
          LOG.error(
              "Failed in sending Mail to user [{}]. Reason : {}",
              user.getEmail(),
              ex.getMessage(),
              ex);
        }
      }
      case USER_CREATE -> sendPasswordResetLink(
          uriInfo, user, subject, EmailUtil.INVITE_CREATE_PWD);
      default -> LOG.error("Invalid Password Create Type");
    }
  }

  @Override
  public RefreshToken createRefreshTokenForLogin(UUID currentUserId) {
    // just delete the existing token
    RefreshToken newRefreshToken = TokenUtil.getRefreshToken(currentUserId, UUID.randomUUID());
    // save Refresh Token in Database
    tokenRepository.insertToken(newRefreshToken);

    return newRefreshToken;
  }

  @Override
  public JwtResponse getNewAccessToken(TokenRefreshRequest request) {
    if (CommonUtil.nullOrEmpty(request.getRefreshToken())) {
      throw new BadRequestException("Token Cannot be Null or Empty String");
    }
    TokenInterface tokenInterface = tokenRepository.findByToken(request.getRefreshToken());
    User storedUser =
        userRepository.get(
            null, tokenInterface.getUserId(), userRepository.getFieldsWithUserAuth("*"));
    if (storedUser.getIsBot() != null && storedUser.getIsBot()) {
      throw new IllegalArgumentException("User are only allowed to login");
    }
    RefreshToken refreshToken = validateAndReturnNewRefresh(storedUser.getId(), request);
    JWTAuthMechanism jwtAuthMechanism =
        JWTTokenGenerator.getInstance()
            .generateJWTToken(
                storedUser.getName(),
                getRoleListFromUser(storedUser),
                !nullOrEmpty(storedUser.getIsAdmin()) && storedUser.getIsAdmin(),
                storedUser.getEmail(),
                SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime(),
                false,
                ServiceTokenType.OM_USER);
    JwtResponse response = new JwtResponse();
    response.setTokenType("Bearer");
    response.setAccessToken(jwtAuthMechanism.getJWTToken());
    response.setRefreshToken(refreshToken.getToken().toString());
    response.setExpiryDuration(jwtAuthMechanism.getJWTTokenExpiresAt());

    return response;
  }

  public void verifyPasswordResetTokenExpiry(PasswordResetToken token) {
    if (token.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) {
      throw new CustomExceptionMessage(
          INTERNAL_SERVER_ERROR,
          PASSWORD_RESET_TOKEN_EXPIRED,
          String.format(
              "Password Reset Token %s Expired token. Please issue a new request",
              token.getToken()));
    }
    if (Boolean.FALSE.equals(token.getIsActive())) {
      throw new CustomExceptionMessage(
          INTERNAL_SERVER_ERROR,
          PASSWORD_RESET_TOKEN_EXPIRED,
          String.format("Password Reset Token %s Token was marked inactive", token.getToken()));
    }
  }

  public RefreshToken validateAndReturnNewRefresh(
      UUID currentUserId, TokenRefreshRequest tokenRefreshRequest) {
    String requestRefreshToken = tokenRefreshRequest.getRefreshToken();
    RefreshToken storedRefreshToken =
        (RefreshToken) tokenRepository.findByToken(requestRefreshToken);
    if (storedRefreshToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) {
      throw new CustomExceptionMessage(
          BAD_REQUEST,
          PASSWORD_RESET_TOKEN_EXPIRED,
          "Expired token. Please login again : " + storedRefreshToken.getToken().toString());
    }
    // TODO: currently allow single login from a place, later multiple login can be added
    // just delete the existing token
    tokenRepository.deleteToken(requestRefreshToken);
    // we use rotating refresh token , generate new token
    RefreshToken newRefreshToken = TokenUtil.getRefreshToken(currentUserId, UUID.randomUUID());
    // save Refresh Token in Database
    tokenRepository.insertToken(newRefreshToken);
    return newRefreshToken;
  }

  private User getUserFromRegistrationRequest(RegistrationRequest create) {
    String username = create.getEmail().split("@")[0];
    String hashedPwd =
        BCrypt.withDefaults().hashToString(HASHING_COST, create.getPassword().toCharArray());

    BasicAuthMechanism newAuthMechanism = new BasicAuthMechanism().withPassword(hashedPwd);
    return getUser(
            username,
            new CreateUser()
                .withName(username)
                .withEmail(create.getEmail())
                .withDisplayName(String.format("%s%s", create.getFirstName(), create.getLastName()))
                .withIsBot(false)
                .withIsAdmin(false))
        .withAuthenticationMechanism(
            new AuthenticationMechanism()
                .withAuthType(AuthenticationMechanism.AuthType.BASIC)
                .withConfig(newAuthMechanism));
  }

  public void validateEmailAlreadyExists(String email) {
    if (userRepository.checkEmailAlreadyExists(email)) {
      throw new CustomExceptionMessage(BAD_REQUEST, EMAIL_EXISTS, "User with Email Already Exists");
    }
  }

  @Override
  public JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException {
    String userName = loginRequest.getEmail();
    checkIfLoginBlocked(userName);
    User storedUser = lookUserInProvider(userName);
    validatePassword(userName, storedUser, loginRequest.getPassword());
    return getJwtResponse(storedUser, SecurityUtil.getLoginConfiguration().getJwtTokenExpiryTime());
  }

  @Override
  public void checkIfLoginBlocked(String userName) {
    if (loginAttemptCache.isLoginBlocked(userName)) {
      throw new AuthenticationException(MAX_FAILED_LOGIN_ATTEMPT);
    }
  }

  @Override
  public void recordFailedLoginAttempt(String providedIdentity, User storedUser)
      throws TemplateException, IOException {
    loginAttemptCache.recordFailedLogin(providedIdentity);
    int failedLoginAttempt = loginAttemptCache.getUserFailedLoginCount(providedIdentity);
    if (failedLoginAttempt == SecurityUtil.getLoginConfiguration().getMaxLoginFailAttempts()) {
      EmailUtil.sendAccountStatus(
          storedUser,
          "Multiple Failed Login Attempts.",
          String.format(
              "Someone is trying to access your account. Login is Blocked for %s minutes. Please change your password.",
              SecurityUtil.getLoginConfiguration().getAccessBlockTime()));
    }
  }

  public void validatePassword(String providedIdentity, User storedUser, String reqPassword)
      throws TemplateException, IOException {
    // when basic auth is enabled and the user is created through the API without password, the
    // stored auth mechanism
    // for the user is null
    if (storedUser.getAuthenticationMechanism() == null) {
      throw new AuthenticationException(INVALID_USERNAME_PASSWORD);
    }
    @SuppressWarnings("unchecked")
    LinkedHashMap storedData =
        (LinkedHashMap) storedUser.getAuthenticationMechanism().getConfig();
    String storedHashPassword = storedData.get("password");
    if (!BCrypt.verifyer().verify(reqPassword.toCharArray(), storedHashPassword).verified) {
      // record Failed Login Attempts
      recordFailedLoginAttempt(providedIdentity, storedUser);
      throw new AuthenticationException(INVALID_USERNAME_PASSWORD);
    }
  }

  @Override
  public User lookUserInProvider(String userName) {
    User storedUser = null;
    try {
      if (userName.contains("@")) {
        // lookup by User Email
        storedUser =
            userRepository.getByEmail(
                null,
                userName,
                new EntityUtil.Fields(
                    Set.of(USER_PROTECTED_FIELDS, "roles"), "authenticationMechanism,roles"));
      }
    } catch (Exception ignored) {

    }

    if (storedUser == null || Boolean.TRUE.equals(storedUser.getIsBot())) {
      throw new CustomExceptionMessage(
          BAD_REQUEST, INVALID_USER_OR_PASSWORD, INVALID_USERNAME_PASSWORD);
    }

    return storedUser;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy