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