Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import java.time.Instant;

import tools.jackson.core.Version;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.cfg.MapperBuilder;
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;

import org.springframework.security.authentication.AnonymousAuthenticationToken;
Expand Down Expand Up @@ -101,7 +99,6 @@ public void configurePolymorphicTypeValidator(BasicPolymorphicTypeValidator.Buil

@Override
public void setupModule(SetupContext context) {
((MapperBuilder<?, ?>) context.getOwner()).enable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS);
context.setMixIn(AnonymousAuthenticationToken.class, AnonymousAuthenticationTokenMixin.class);
context.setMixIn(RememberMeAuthenticationToken.class, RememberMeAuthenticationTokenMixin.class);
context.setMixIn(SimpleGrantedAuthority.class, SimpleGrantedAuthorityMixin.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

Expand All @@ -44,7 +45,10 @@ abstract class FactorGrantedAuthorityMixin {
*/
@JsonCreator
FactorGrantedAuthorityMixin(@JsonProperty("authority") String authority,
@JsonProperty("issuedAt") Instant issuedAt) {
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt) {
}

@JsonFormat(shape = JsonFormat.Shape.NUMBER)
abstract Instant getIssuedAt();

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
import org.json.JSONException;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.FactorGrantedAuthority;
Expand Down Expand Up @@ -57,4 +60,41 @@ void deserializeGrantedAuthorityTest() {
assertThat(authority.getIssuedAt()).isEqualTo(this.issuedAt);
}

@Test
void serializeWhenWriteDatesAsTimestampsDisabledThenStillUsesTimestamps() throws JSONException {
ClassLoader loader = getClass().getClassLoader();
JsonMapper customMapper = JsonMapper.builder()
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
.build();
GrantedAuthority authority = FactorGrantedAuthority.withAuthority("FACTOR_PASSWORD")
.issuedAt(this.issuedAt)
.build();
String json = customMapper.writeValueAsString(authority);
JSONAssert.assertEquals(AUTHORITY_JSON, json, true);
}

@Test
void deserializeWhenWriteDatesAsTimestampsDisabledThenStillDeserializesTimestamps() {
ClassLoader loader = getClass().getClassLoader();
JsonMapper customMapper = JsonMapper.builder()
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
.build();
FactorGrantedAuthority authority = (FactorGrantedAuthority) customMapper.readValue(AUTHORITY_JSON, Object.class);
assertThat(authority).isNotNull();
assertThat(authority.getAuthority()).isEqualTo("FACTOR_PASSWORD");
assertThat(authority.getIssuedAt()).isEqualTo(this.issuedAt);
}

@Test
void serializeDoesNotOverrideGlobalDateTimeFeature() {
ClassLoader loader = getClass().getClassLoader();
JsonMapper customMapper = JsonMapper.builder()
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
.build();
assertThat(customMapper.isEnabled(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)).isFalse();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import tools.jackson.databind.annotation.JsonDeserialize;
Expand All @@ -45,8 +46,10 @@ abstract class OAuth2AccessTokenMixin {
OAuth2AccessTokenMixin(
@JsonProperty("tokenType") @JsonDeserialize(
converter = StdConverters.AccessTokenTypeConverter.class) OAuth2AccessToken.TokenType tokenType,
@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt,
@JsonProperty("expiresAt") Instant expiresAt, @JsonProperty("scopes") Set<String> scopes) {
@JsonProperty("tokenValue") String tokenValue,
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt,
@JsonProperty("expiresAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant expiresAt,
@JsonProperty("scopes") Set<String> scopes) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

Expand All @@ -40,7 +41,8 @@
abstract class OAuth2RefreshTokenMixin {

@JsonCreator
OAuth2RefreshTokenMixin(@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt) {
OAuth2RefreshTokenMixin(@JsonProperty("tokenValue") String tokenValue,
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

Expand All @@ -41,8 +42,10 @@
abstract class OidcIdTokenMixin {

@JsonCreator
OidcIdTokenMixin(@JsonProperty("tokenValue") String tokenValue, @JsonProperty("issuedAt") Instant issuedAt,
@JsonProperty("expiresAt") Instant expiresAt, @JsonProperty("claims") Map<String, Object> claims) {
OidcIdTokenMixin(@JsonProperty("tokenValue") String tokenValue,
@JsonProperty("issuedAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant issuedAt,
@JsonProperty("expiresAt") @JsonFormat(shape = JsonFormat.Shape.NUMBER) Instant expiresAt,
@JsonProperty("claims") Map<String, Object> claims) {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;
import tools.jackson.core.JacksonException;
import tools.jackson.databind.cfg.DateTimeFeature;
import tools.jackson.databind.json.JsonMapper;
import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator;

import org.springframework.security.jackson.SecurityJacksonModules;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
Expand Down Expand Up @@ -107,6 +109,47 @@ public void serializeWhenRequiredAttributesOnlyThenSerializes() throws Exception
JSONAssert.assertEquals(expectedJson, json, true);
}

@Test
public void serializeWhenWriteDatesAsTimestampsDisabledThenTokenDatesStillUseTimestamps() throws Exception {
ClassLoader loader = getClass().getClassLoader();
JsonMapper customMapper = JsonMapper.builder()
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
.build();
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(),
this.principalName, this.accessToken, this.refreshToken);
String expectedJson = asJson(authorizedClient);
String json = customMapper.writeValueAsString(authorizedClient);
JSONAssert.assertEquals(expectedJson, json, true);
}

@Test
public void deserializeWhenWriteDatesAsTimestampsDisabledThenTokenDatesStillDeserialize() throws Exception {
ClassLoader loader = getClass().getClassLoader();
JsonMapper customMapper = JsonMapper.builder()
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
.build();
OAuth2AuthorizedClient expectedAuthorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(),
this.principalName, this.accessToken, this.refreshToken);
String json = asJson(expectedAuthorizedClient);
OAuth2AuthorizedClient authorizedClient = customMapper.readValue(json, OAuth2AuthorizedClient.class);
assertThat(authorizedClient.getAccessToken().getIssuedAt()).isEqualTo(this.accessToken.getIssuedAt());
assertThat(authorizedClient.getAccessToken().getExpiresAt()).isEqualTo(this.accessToken.getExpiresAt());
assertThat(authorizedClient.getRefreshToken()).isNotNull();
assertThat(authorizedClient.getRefreshToken().getIssuedAt()).isEqualTo(this.refreshToken.getIssuedAt());
}

@Test
public void setupWhenWriteDatesAsTimestampsDisabledThenSettingIsNotOverridden() {
ClassLoader loader = getClass().getClassLoader();
JsonMapper customMapper = JsonMapper.builder()
.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)
.addModules(SecurityJacksonModules.getModules(loader, BasicPolymorphicTypeValidator.builder()))
.build();
assertThat(customMapper.isEnabled(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS)).isFalse();
}

@Test
public void deserializeWhenMixinNotRegisteredThenThrowJsonProcessingException() {
OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient(this.clientRegistrationBuilder.build(),
Expand Down