Fix token sessionId calculation
This commit is contained in:
		
							parent
							
								
									bf5d99fab1
								
							
						
					
					
						commit
						5e2a4a73b7
					
				@ -15,7 +15,6 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		||||
import io.swagger.v3.oas.annotations.Parameter;
 | 
			
		||||
import jakarta.servlet.http.HttpServletRequest;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
@ -34,8 +33,8 @@ import org.springframework.web.bind.annotation.RequestParam;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.ResponseStatus;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.rule.engine.api.MailService;
 | 
			
		||||
import org.thingsboard.server.cache.limits.RateLimitService;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
 | 
			
		||||
@ -49,7 +48,6 @@ import org.thingsboard.server.common.data.security.model.JwtPair;
 | 
			
		||||
import org.thingsboard.server.common.data.security.model.SecuritySettings;
 | 
			
		||||
import org.thingsboard.server.common.data.security.model.UserPasswordPolicy;
 | 
			
		||||
import org.thingsboard.server.config.annotations.ApiOperation;
 | 
			
		||||
import org.thingsboard.server.cache.limits.RateLimitService;
 | 
			
		||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.security.auth.rest.RestAuthenticationDetails;
 | 
			
		||||
import org.thingsboard.server.service.security.model.ActivateUserRequest;
 | 
			
		||||
@ -105,9 +103,8 @@ public class AuthController extends BaseController {
 | 
			
		||||
    @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
 | 
			
		||||
    @RequestMapping(value = "/auth/changePassword", method = RequestMethod.POST)
 | 
			
		||||
    @ResponseStatus(value = HttpStatus.OK)
 | 
			
		||||
    public ObjectNode changePassword(
 | 
			
		||||
            @Parameter(description = "Change Password Request")
 | 
			
		||||
            @RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException {
 | 
			
		||||
    public JwtPair changePassword(@Parameter(description = "Change Password Request")
 | 
			
		||||
                                  @RequestBody ChangePasswordRequest changePasswordRequest) throws ThingsboardException {
 | 
			
		||||
        String currentPassword = changePasswordRequest.getCurrentPassword();
 | 
			
		||||
        String newPassword = changePasswordRequest.getNewPassword();
 | 
			
		||||
        SecurityUser securityUser = getCurrentUser();
 | 
			
		||||
@ -123,10 +120,7 @@ public class AuthController extends BaseController {
 | 
			
		||||
        userService.replaceUserCredentials(securityUser.getTenantId(), userCredentials);
 | 
			
		||||
 | 
			
		||||
        eventPublisher.publishEvent(new UserCredentialsInvalidationEvent(securityUser.getId()));
 | 
			
		||||
        ObjectNode response = JacksonUtil.newObjectNode();
 | 
			
		||||
        response.put("token", tokenFactory.createAccessJwtToken(securityUser).getToken());
 | 
			
		||||
        response.put("refreshToken", tokenFactory.createRefreshToken(securityUser).getToken());
 | 
			
		||||
        return response;
 | 
			
		||||
        return tokenFactory.createTokenPair(securityUser);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiOperation(value = "Get the current User password policy (getUserPasswordPolicy)",
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,8 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.service.security.model;
 | 
			
		||||
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
import lombok.Setter;
 | 
			
		||||
import org.springframework.security.core.GrantedAuthority;
 | 
			
		||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
@ -30,9 +32,12 @@ public class SecurityUser extends User {
 | 
			
		||||
    private static final long serialVersionUID = -797397440703066079L;
 | 
			
		||||
 | 
			
		||||
    private Collection<GrantedAuthority> authorities;
 | 
			
		||||
    @Getter @Setter
 | 
			
		||||
    private boolean enabled;
 | 
			
		||||
    @Getter @Setter
 | 
			
		||||
    private UserPrincipal userPrincipal;
 | 
			
		||||
    private String sessionId;
 | 
			
		||||
    @Getter @Setter
 | 
			
		||||
    private String sessionId = UUID.randomUUID().toString();
 | 
			
		||||
 | 
			
		||||
    public SecurityUser() {
 | 
			
		||||
        super();
 | 
			
		||||
@ -46,7 +51,6 @@ public class SecurityUser extends User {
 | 
			
		||||
        super(user);
 | 
			
		||||
        this.enabled = enabled;
 | 
			
		||||
        this.userPrincipal = userPrincipal;
 | 
			
		||||
        this.sessionId = UUID.randomUUID().toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Collection<GrantedAuthority> getAuthorities() {
 | 
			
		||||
@ -58,27 +62,4 @@ public class SecurityUser extends User {
 | 
			
		||||
        return authorities;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean isEnabled() {
 | 
			
		||||
        return enabled;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public UserPrincipal getUserPrincipal() {
 | 
			
		||||
        return userPrincipal;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setEnabled(boolean enabled) {
 | 
			
		||||
        this.enabled = enabled;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setUserPrincipal(UserPrincipal userPrincipal) {
 | 
			
		||||
        this.userPrincipal = userPrincipal;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getSessionId() {
 | 
			
		||||
        return sessionId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setSessionId(String sessionId) {
 | 
			
		||||
        this.sessionId = sessionId;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -232,6 +232,7 @@ public class JwtTokenFactory {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public JwtPair createTokenPair(SecurityUser securityUser) {
 | 
			
		||||
        securityUser.setSessionId(UUID.randomUUID().toString());
 | 
			
		||||
        JwtToken accessToken = createAccessJwtToken(securityUser);
 | 
			
		||||
        JwtToken refreshToken = createRefreshToken(securityUser);
 | 
			
		||||
        return new JwtPair(accessToken.getToken(), refreshToken.getToken());
 | 
			
		||||
 | 
			
		||||
@ -73,16 +73,7 @@ public class JwtTokenFactoryTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateAndParseAccessJwtToken() {
 | 
			
		||||
        SecurityUser securityUser = new SecurityUser();
 | 
			
		||||
        securityUser.setId(new UserId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setEmail("tenant@thingsboard.org");
 | 
			
		||||
        securityUser.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        securityUser.setTenantId(new TenantId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setEnabled(true);
 | 
			
		||||
        securityUser.setFirstName("A");
 | 
			
		||||
        securityUser.setLastName("B");
 | 
			
		||||
        securityUser.setUserPrincipal(new UserPrincipal(UserPrincipal.Type.USER_NAME, securityUser.getEmail()));
 | 
			
		||||
        securityUser.setCustomerId(new CustomerId(UUID.randomUUID()));
 | 
			
		||||
        SecurityUser securityUser = createSecurityUser();
 | 
			
		||||
 | 
			
		||||
        testCreateAndParseAccessJwtToken(securityUser);
 | 
			
		||||
 | 
			
		||||
@ -111,18 +102,12 @@ public class JwtTokenFactoryTest {
 | 
			
		||||
        assertThat(parsedSecurityUser.getCustomerId()).isEqualTo(securityUser.getCustomerId());
 | 
			
		||||
        assertThat(parsedSecurityUser.getFirstName()).isEqualTo(securityUser.getFirstName());
 | 
			
		||||
        assertThat(parsedSecurityUser.getLastName()).isEqualTo(securityUser.getLastName());
 | 
			
		||||
        assertThat(parsedSecurityUser.getSessionId()).isNotNull().isEqualTo(securityUser.getSessionId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateAndParseRefreshJwtToken() {
 | 
			
		||||
        SecurityUser securityUser = new SecurityUser();
 | 
			
		||||
        securityUser.setId(new UserId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setEmail("tenant@thingsboard.org");
 | 
			
		||||
        securityUser.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        securityUser.setUserPrincipal(new UserPrincipal(UserPrincipal.Type.USER_NAME, securityUser.getEmail()));
 | 
			
		||||
        securityUser.setEnabled(true);
 | 
			
		||||
        securityUser.setTenantId(new TenantId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setCustomerId(new CustomerId(UUID.randomUUID()));
 | 
			
		||||
        SecurityUser securityUser = createSecurityUser();
 | 
			
		||||
 | 
			
		||||
        JwtToken refreshToken = tokenFactory.createRefreshToken(securityUser);
 | 
			
		||||
        checkExpirationTime(refreshToken, jwtSettings.getRefreshTokenExpTime());
 | 
			
		||||
@ -138,15 +123,7 @@ public class JwtTokenFactoryTest {
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreateAndParsePreVerificationJwtToken() {
 | 
			
		||||
        SecurityUser securityUser = new SecurityUser();
 | 
			
		||||
        securityUser.setId(new UserId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setEmail("tenant@thingsboard.org");
 | 
			
		||||
        securityUser.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        securityUser.setUserPrincipal(new UserPrincipal(UserPrincipal.Type.USER_NAME, securityUser.getEmail()));
 | 
			
		||||
        securityUser.setEnabled(true);
 | 
			
		||||
        securityUser.setTenantId(new TenantId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setCustomerId(new CustomerId(UUID.randomUUID()));
 | 
			
		||||
 | 
			
		||||
        SecurityUser securityUser = createSecurityUser();
 | 
			
		||||
        int tokenLifetime = (int) TimeUnit.MINUTES.toSeconds(30);
 | 
			
		||||
        JwtToken preVerificationToken = tokenFactory.createPreVerificationToken(securityUser, tokenLifetime);
 | 
			
		||||
        checkExpirationTime(preVerificationToken, tokenLifetime);
 | 
			
		||||
@ -162,6 +139,34 @@ public class JwtTokenFactoryTest {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testSessionId() {
 | 
			
		||||
        SecurityUser securityUser = createSecurityUser();
 | 
			
		||||
        String sessionId = securityUser.getSessionId();
 | 
			
		||||
 | 
			
		||||
        String accessToken = tokenFactory.createAccessJwtToken(securityUser).getToken();
 | 
			
		||||
        securityUser = tokenFactory.parseAccessJwtToken(accessToken);
 | 
			
		||||
        assertThat(securityUser.getSessionId()).isNotNull().isEqualTo(sessionId);
 | 
			
		||||
 | 
			
		||||
        String newAccessToken = tokenFactory.createTokenPair(securityUser).getToken();
 | 
			
		||||
        securityUser = tokenFactory.parseAccessJwtToken(newAccessToken);
 | 
			
		||||
        assertThat(securityUser.getSessionId()).isNotNull().isNotEqualTo(sessionId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private SecurityUser createSecurityUser() {
 | 
			
		||||
        SecurityUser securityUser = new SecurityUser();
 | 
			
		||||
        securityUser.setId(new UserId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setEmail("tenant@thingsboard.org");
 | 
			
		||||
        securityUser.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        securityUser.setTenantId(new TenantId(UUID.randomUUID()));
 | 
			
		||||
        securityUser.setEnabled(true);
 | 
			
		||||
        securityUser.setFirstName("A");
 | 
			
		||||
        securityUser.setLastName("B");
 | 
			
		||||
        securityUser.setUserPrincipal(new UserPrincipal(UserPrincipal.Type.USER_NAME, securityUser.getEmail()));
 | 
			
		||||
        securityUser.setCustomerId(new CustomerId(UUID.randomUUID()));
 | 
			
		||||
        return securityUser;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void mockJwtSettings(JwtSettings settings) {
 | 
			
		||||
        AdminSettings adminJwtSettings = new AdminSettings();
 | 
			
		||||
        adminJwtSettings.setJsonValue(JacksonUtil.valueToTree(settings));
 | 
			
		||||
 | 
			
		||||
@ -18,17 +18,17 @@ package org.thingsboard.server.common.data;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import com.fasterxml.jackson.core.JsonProcessingException;
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.thingsboard.server.common.data.id.UUIDBased;
 | 
			
		||||
import org.thingsboard.server.common.data.validation.NoXss;
 | 
			
		||||
 | 
			
		||||
import java.io.ByteArrayInputStream;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
import java.util.function.Function;
 | 
			
		||||
import java.util.function.Supplier;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -64,6 +64,23 @@ public abstract class BaseDataWithAdditionalInfo<I extends UUIDBased> extends Ba
 | 
			
		||||
        setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setAdditionalInfoField(String field, JsonNode value) {
 | 
			
		||||
        JsonNode additionalInfo = getAdditionalInfo();
 | 
			
		||||
        if (!(additionalInfo instanceof ObjectNode)) {
 | 
			
		||||
            additionalInfo = mapper.createObjectNode();
 | 
			
		||||
        }
 | 
			
		||||
        ((ObjectNode) additionalInfo).set(field, value);
 | 
			
		||||
        setAdditionalInfo(additionalInfo);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public <T> T getAdditionalInfoField(String field, Function<JsonNode, T> mapper, T defaultValue) {
 | 
			
		||||
        JsonNode additionalInfo = getAdditionalInfo();
 | 
			
		||||
        if (additionalInfo != null && additionalInfo.has(field)) {
 | 
			
		||||
            return mapper.apply(additionalInfo.get(field));
 | 
			
		||||
        }
 | 
			
		||||
        return defaultValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean equals(Object o) {
 | 
			
		||||
        if (this == o) return true;
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.common.data.security.model;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonInclude;
 | 
			
		||||
import io.swagger.v3.oas.annotations.media.Schema;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
@ -25,6 +26,7 @@ import java.io.Serializable;
 | 
			
		||||
@Schema(description = "JWT Pair")
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@JsonInclude(JsonInclude.Include.NON_NULL)
 | 
			
		||||
public class JwtPair implements Serializable {
 | 
			
		||||
 | 
			
		||||
    @Schema(description = "The JWT Access Token. Used to perform API calls.", example = "AAB254FF67D..")
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user