Added activate user config. Fixed https issue (#2737)
* Added activate user config. Fixed https issue * Update OAuth2User.java Co-authored-by: Igor Kulikov <ikulikov82@gmail.com>
This commit is contained in:
		
							parent
							
								
									f29c9c9452
								
							
						
					
					
						commit
						9b18c408b2
					
				@ -204,11 +204,11 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
 | 
			
		||||
            http.oauth2Login()
 | 
			
		||||
                    .loginPage("/oauth2Login")
 | 
			
		||||
                    .loginProcessingUrl(oauth2Configuration.getLoginProcessingUrl())
 | 
			
		||||
                    .successHandler(oauth2AuthenticationSuccessHandler);
 | 
			
		||||
                    .successHandler(oauth2AuthenticationSuccessHandler)
 | 
			
		||||
                    .failureHandler(failureHandler);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    @ConditionalOnMissingBean(CorsFilter.class)
 | 
			
		||||
    public CorsFilter corsFilter(@Autowired MvcCorsProperties mvcCorsProperties) {
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,7 @@ import org.thingsboard.server.service.security.model.UserPrincipal;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtToken;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
 | 
			
		||||
import org.thingsboard.server.service.security.system.SystemSecurityService;
 | 
			
		||||
import org.thingsboard.server.utils.MiscUtils;
 | 
			
		||||
import ua_parser.Client;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
@ -170,7 +171,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
        try {
 | 
			
		||||
            String email = resetPasswordByEmailRequest.get("email").asText();
 | 
			
		||||
            UserCredentials userCredentials = userService.requestPasswordReset(TenantId.SYS_TENANT_ID, email);
 | 
			
		||||
            String baseUrl = constructBaseUrl(request);
 | 
			
		||||
            String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
            String resetUrl = String.format("%s/api/noauth/resetPassword?resetToken=%s", baseUrl,
 | 
			
		||||
                    userCredentials.getResetToken());
 | 
			
		||||
            
 | 
			
		||||
@ -218,7 +219,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
            User user = userService.findUserById(TenantId.SYS_TENANT_ID, credentials.getUserId());
 | 
			
		||||
            UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
 | 
			
		||||
            SecurityUser securityUser = new SecurityUser(user, credentials.isEnabled(), principal);
 | 
			
		||||
            String baseUrl = constructBaseUrl(request);
 | 
			
		||||
            String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
            String loginUrl = String.format("%s/login", baseUrl);
 | 
			
		||||
            String email = user.getEmail();
 | 
			
		||||
 | 
			
		||||
@ -265,7 +266,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
                User user = userService.findUserById(TenantId.SYS_TENANT_ID, userCredentials.getUserId());
 | 
			
		||||
                UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, user.getEmail());
 | 
			
		||||
                SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), principal);
 | 
			
		||||
                String baseUrl = constructBaseUrl(request);
 | 
			
		||||
                String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
                String loginUrl = String.format("%s/login", baseUrl);
 | 
			
		||||
                String email = user.getEmail();
 | 
			
		||||
                mailService.sendPasswordWasResetEmail(loginUrl, email);
 | 
			
		||||
 | 
			
		||||
@ -521,39 +521,6 @@ public abstract class BaseController {
 | 
			
		||||
        return ruleNode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected String constructBaseUrl(HttpServletRequest request) {
 | 
			
		||||
        String scheme = request.getScheme();
 | 
			
		||||
 | 
			
		||||
        String forwardedProto = request.getHeader("x-forwarded-proto");
 | 
			
		||||
        if (forwardedProto != null) {
 | 
			
		||||
            scheme = forwardedProto;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int serverPort = request.getServerPort();
 | 
			
		||||
        if (request.getHeader("x-forwarded-port") != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                serverPort = request.getIntHeader("x-forwarded-port");
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
            }
 | 
			
		||||
        } else if (forwardedProto != null) {
 | 
			
		||||
            switch (forwardedProto) {
 | 
			
		||||
                case "http":
 | 
			
		||||
                    serverPort = 80;
 | 
			
		||||
                    break;
 | 
			
		||||
                case "https":
 | 
			
		||||
                    serverPort = 443;
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        String baseUrl = String.format("%s://%s:%d",
 | 
			
		||||
                scheme,
 | 
			
		||||
                request.getServerName(),
 | 
			
		||||
                serverPort);
 | 
			
		||||
        return baseUrl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected <I extends EntityId> I emptyId(EntityType entityType) {
 | 
			
		||||
        return (I) EntityIdFactory.getByTypeAndUuid(entityType, ModelConstants.NULL_UUID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -52,6 +52,7 @@ import org.thingsboard.server.service.security.model.token.JwtToken;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Operation;
 | 
			
		||||
import org.thingsboard.server.service.security.permission.Resource;
 | 
			
		||||
import org.thingsboard.server.utils.MiscUtils;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
 | 
			
		||||
@ -148,7 +149,7 @@ public class UserController extends BaseController {
 | 
			
		||||
            if (sendEmail) {
 | 
			
		||||
                SecurityUser authUser = getCurrentUser();
 | 
			
		||||
                UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), savedUser.getId());
 | 
			
		||||
                String baseUrl = constructBaseUrl(request);
 | 
			
		||||
                String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
                String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl,
 | 
			
		||||
                        userCredentials.getActivateToken());
 | 
			
		||||
                String email = savedUser.getEmail();
 | 
			
		||||
@ -188,7 +189,7 @@ public class UserController extends BaseController {
 | 
			
		||||
 | 
			
		||||
            UserCredentials userCredentials = userService.findUserCredentialsByUserId(getCurrentUser().getTenantId(), user.getId());
 | 
			
		||||
            if (!userCredentials.isEnabled()) {
 | 
			
		||||
                String baseUrl = constructBaseUrl(request);
 | 
			
		||||
                String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
                String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl,
 | 
			
		||||
                        userCredentials.getActivateToken());
 | 
			
		||||
                mailService.sendActivationEmail(activateUrl, email);
 | 
			
		||||
@ -213,7 +214,7 @@ public class UserController extends BaseController {
 | 
			
		||||
            SecurityUser authUser = getCurrentUser();
 | 
			
		||||
            UserCredentials userCredentials = userService.findUserCredentialsByUserId(authUser.getTenantId(), user.getId());
 | 
			
		||||
            if (!userCredentials.isEnabled()) {
 | 
			
		||||
                String baseUrl = constructBaseUrl(request);
 | 
			
		||||
                String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
                String activateUrl = String.format(ACTIVATE_URL_PATTERN, baseUrl,
 | 
			
		||||
                        userCredentials.getActivateToken());
 | 
			
		||||
                return activateUrl;
 | 
			
		||||
 | 
			
		||||
@ -63,7 +63,7 @@ public abstract class AbstractOAuth2ClientMapper {
 | 
			
		||||
 | 
			
		||||
    private final Lock userCreationLock = new ReentrantLock();
 | 
			
		||||
 | 
			
		||||
    protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, boolean allowUserCreation) {
 | 
			
		||||
    protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, boolean allowUserCreation, boolean activateUser) {
 | 
			
		||||
        UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, oauth2User.getEmail());
 | 
			
		||||
 | 
			
		||||
        User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, oauth2User.getEmail());
 | 
			
		||||
@ -93,8 +93,10 @@ public abstract class AbstractOAuth2ClientMapper {
 | 
			
		||||
                    user.setFirstName(oauth2User.getFirstName());
 | 
			
		||||
                    user.setLastName(oauth2User.getLastName());
 | 
			
		||||
                    user = userService.saveUser(user);
 | 
			
		||||
                    UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());
 | 
			
		||||
                    userService.activateUserCredentials(user.getTenantId(), userCredentials.getActivateToken(), passwordEncoder.encode(""));
 | 
			
		||||
                    if (activateUser) {
 | 
			
		||||
                        UserCredentials userCredentials = userService.findUserCredentialsByUserId(user.getTenantId(), user.getId());
 | 
			
		||||
                        userService.activateUserCredentials(user.getTenantId(), userCredentials.getActivateToken(), passwordEncoder.encode(""));
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                log.error("Can't get or create security user from oauth2 user", e);
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,8 @@ public class BasicOAuth2ClientMapper extends AbstractOAuth2ClientMapper implemen
 | 
			
		||||
            String customerName = sub.replace(config.getBasic().getCustomerNamePattern());
 | 
			
		||||
            oauth2User.setCustomerName(customerName);
 | 
			
		||||
        }
 | 
			
		||||
        return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.getBasic().isAllowUserCreation());
 | 
			
		||||
 | 
			
		||||
        return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String getTenantName(Map<String, Object> attributes, OAuth2ClientMapperConfig config) {
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ public class CustomOAuth2ClientMapper extends AbstractOAuth2ClientMapper impleme
 | 
			
		||||
    @Override
 | 
			
		||||
    public SecurityUser getOrCreateUserByClientPrincipal(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig config) {
 | 
			
		||||
        OAuth2User oauth2User = getOAuth2User(token, config.getCustom());
 | 
			
		||||
        return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.getBasic().isAllowUserCreation());
 | 
			
		||||
        return getOrCreateSecurityUserFromOAuth2User(oauth2User, config.isAllowUserCreation(), config.isActivateUser());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private synchronized OAuth2User getOAuth2User(OAuth2AuthenticationToken token, OAuth2ClientMapperConfig.CustomOAuth2ClientMapperConfig custom) {
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtToken;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
 | 
			
		||||
import org.thingsboard.server.utils.MiscUtils;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
@ -65,6 +66,7 @@ public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationS
 | 
			
		||||
        JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
 | 
			
		||||
        JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
 | 
			
		||||
 | 
			
		||||
        getRedirectStrategy().sendRedirect(request, response, "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken());
 | 
			
		||||
        String baseUrl = MiscUtils.constructBaseUrl(request);
 | 
			
		||||
        getRedirectStrategy().sendRedirect(request, response, baseUrl + "/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -18,8 +18,8 @@ package org.thingsboard.server.utils;
 | 
			
		||||
import com.google.common.hash.HashFunction;
 | 
			
		||||
import com.google.common.hash.Hashing;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
import java.util.Random;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -47,4 +47,36 @@ public class MiscUtils {
 | 
			
		||||
                throw new IllegalArgumentException("Can't find hash function with name " + name);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static String constructBaseUrl(HttpServletRequest request) {
 | 
			
		||||
        String scheme = request.getScheme();
 | 
			
		||||
 | 
			
		||||
        String forwardedProto = request.getHeader("x-forwarded-proto");
 | 
			
		||||
        if (forwardedProto != null) {
 | 
			
		||||
            scheme = forwardedProto;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int serverPort = request.getServerPort();
 | 
			
		||||
        if (request.getHeader("x-forwarded-port") != null) {
 | 
			
		||||
            try {
 | 
			
		||||
                serverPort = request.getIntHeader("x-forwarded-port");
 | 
			
		||||
            } catch (NumberFormatException e) {
 | 
			
		||||
            }
 | 
			
		||||
        } else if (forwardedProto != null) {
 | 
			
		||||
            switch (forwardedProto) {
 | 
			
		||||
                case "http":
 | 
			
		||||
                    serverPort = 80;
 | 
			
		||||
                    break;
 | 
			
		||||
                case "https":
 | 
			
		||||
                    serverPort = 443;
 | 
			
		||||
                    break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        String baseUrl = String.format("%s://%s:%d",
 | 
			
		||||
                scheme,
 | 
			
		||||
                request.getServerName(),
 | 
			
		||||
                serverPort);
 | 
			
		||||
        return baseUrl;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -127,11 +127,13 @@ security:
 | 
			
		||||
        userInfoUri: "${SECURITY_OAUTH2_DEFAULT_USER_INFO_URI:}"
 | 
			
		||||
        userNameAttributeName: "${SECURITY_OAUTH2_DEFAULT_USER_NAME_ATTRIBUTE_NAME:email}"
 | 
			
		||||
        mapperConfig:
 | 
			
		||||
          # Allows to create user if it not exists
 | 
			
		||||
          allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_ALLOW_USER_CREATION:true}"
 | 
			
		||||
          # Allows user to setup ThingsBoard internal password and login over default Login window
 | 
			
		||||
          activateUser: "${SECURITY_OAUTH2_DEFAULT_MAPPER_ACTIVATE_USER:false}"
 | 
			
		||||
          # Mapper type of converter from external user into internal - 'basic' or 'custom'
 | 
			
		||||
          type: "${SECURITY_OAUTH2_DEFAULT_MAPPER_TYPE:basic}"
 | 
			
		||||
          basic:
 | 
			
		||||
            # Allows to create user if it not exists
 | 
			
		||||
            allowUserCreation: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_ALLOW_USER_CREATION:true}"
 | 
			
		||||
            # Key from attributes of external user object to use as email
 | 
			
		||||
            emailAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_EMAIL_ATTRIBUTE_KEY:email}"
 | 
			
		||||
            firstNameAttributeKey: "${SECURITY_OAUTH2_DEFAULT_MAPPER_BASIC_FIRST_NAME_ATTRIBUTE_KEY:}"
 | 
			
		||||
 | 
			
		||||
@ -20,13 +20,14 @@ import lombok.Data;
 | 
			
		||||
@Data
 | 
			
		||||
public class OAuth2ClientMapperConfig {
 | 
			
		||||
 | 
			
		||||
    private boolean allowUserCreation;
 | 
			
		||||
    private boolean activateUser;
 | 
			
		||||
    private String type;
 | 
			
		||||
    private BasicOAuth2ClientMapperConfig basic;
 | 
			
		||||
    private CustomOAuth2ClientMapperConfig custom;
 | 
			
		||||
 | 
			
		||||
    @Data
 | 
			
		||||
    public static class BasicOAuth2ClientMapperConfig {
 | 
			
		||||
        private boolean allowUserCreation;
 | 
			
		||||
        private String emailAttributeKey;
 | 
			
		||||
        private String firstNameAttributeKey;
 | 
			
		||||
        private String lastNameAttributeKey;
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user