spring-bootjacksonspring-data-redisspring-session

OAuth2Authentication token serializing by spring session with redis


I am using spring session for redis for my oauth2 login. I have implemented a custom principal.

@Data
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public final class CustomUserOidcPrincipal extends CustomUserPrincipal implements OidcUser {



    @JsonIgnore
    private String name;

    @JsonIgnore
    private Map<String, Object> claims;

    @JsonIgnore
    private OidcIdToken idToken;


    @JsonIgnore
    private OidcUserInfo userInfo;

    @JsonIgnore
    private Map<String, Object> attributes;



    //oidc principal constructor..
    public CustomUserOidcPrincipal(String id, String email, String password,
                                   String username,
                                   Boolean isOidcLogin,
                                   Set<GrantedAuthority> roles,
                                   Boolean mfaEnabled,
                                   Boolean disabled, Boolean locked,
                                   String name,
                                   Map<String, Object> claims,
                                   OidcIdToken idToken, OidcUserInfo userInfo,Map<String,Object> attributes
    ) {

        super(id, email, password, username, isOidcLogin, roles, mfaEnabled, !disabled, !locked);
        this.name = name;
        this.claims = claims;
        this.idToken = idToken;
        this.userInfo = userInfo;
        this.attributes = attributes;


    }


    @JsonIgnore
    @Override
    public Map<String, Object> getAttributes() {
        return this.attributes;
    }


    @JsonIgnore
    @Override
    public String getName() {
        return this.name;
    }

    @JsonIgnore
    @Override
    public Map<String, Object> getClaims() {
        return this.claims;
    }

    @JsonIgnore
    @Override
    public OidcUserInfo getUserInfo() {
        return this.userInfo;
    }

    @JsonIgnore
    @Override
    public OidcIdToken getIdToken() {
        return this.idToken;
    }
}

Now before using spring session I was using default httpSession, and the oauth2 login was working perfectly fine. But now the there is an issue, the fields which i have put @JsonIgnore is not getting serialized, but the attributes in that fields, like in OidcUserInfo, there are fields like email, familyName etc.., they are getting serialized. This is my serialized json.

{
   "@class":"org.springframework.security.core.context.SecurityContextImpl",
   "authentication":{
      "@class":"org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken",
      "principal":{
         "@class":"com.test.mmt.configuration.security.authentication.principal.CustomUserOidcPrincipal",
         "id":"01JWQSJ8GVQ8RVB1ERC9S4JY7G",
         "email":"test@gmail.com",
         "username":"test@gmail.com",
         "isOidcLogin":true,
         "authorities":[
            "java.util.HashSet",
            [
               {
                  "@class":"org.springframework.security.core.authority.SimpleGrantedAuthority",
                  "authority":"ROLE_USER"
               },
               {
                  "@class":"org.springframework.security.core.authority.SimpleGrantedAuthority",
                  "authority":"ROLE_ADMIN"
               }
            ]
         ],
         "mfaEnabled":true,
         "locked":false,
         "isMfaAuthenticated":false,
         "isAdminAuthenticated":false,
         "nonce":"CilzMtqiAKIyaH35XemvykUQQmEKUXoa8JVGYXW8xx0",
         "subject":"100812923335268714792",
         "authenticationContextClass":null,
         "authenticationMethods":null,
         "authorizationCodeHash":null,
         "authenticatedAt":null,
         "authorizedParty":"101205211125502-6qs23n3dmq6xascaa.apps.googleusercontent.com",
         "accessTokenHash":"xxxxx",
         "audience":[
            "java.util.ArrayList",
            [
               "10120211125502-6qsn3dmq6sd1ssxc34sxkddtos.apps.googleusercontent.com"
            ]
         ],
         "issuedAt":"2025-06-12T12:05:56Z",
         "expiresAt":"2025-06-12T13:05:56Z",
         "givenName":"Allen",
         "address":{
            "@class":"org.springframework.security.oauth2.core.oidc.DefaultAddressStandardClaim",
            "formatted":null,
            "streetAddress":null,
            "locality":null,
            "region":null,
            "postalCode":null,
            "country":null
         },
         "locale":null,
         "zoneInfo":null,
         "fullName":"Allen Bastian",
         "preferredUsername":null,
         "emailVerified":true,
         "phoneNumberVerified":null,
         "familyName":"Bastian",
         "middleName":null,
         "nickName":null,
         "picture":"https://random-c",
         "website":null,
         "gender":null,
         "birthdate":null,
         "phoneNumber":null,
         "updatedAt":null,
         "profile":null
      },
      "authorities":[
         "java.util.Collections$UnmodifiableRandomAccessList",
         [
            {
               "@class":"org.springframework.security.core.authority.SimpleGrantedAuthority",
               "authority":"ROLE_USER"
            },
            {
               "@class":"org.springframework.security.core.authority.SimpleGrantedAuthority",
               "authority":"ROLE_ADMIN"
            }
         ]
      ],
      "authorizedClientRegistrationId":"01JWXSQ642SZC4V142Y3Z92DMS",
      "details":{
         "@class":"org.springframework.security.web.authentication.WebAuthenticationDetails",
         "remoteAddress":"0:0:0:0:0:0:0:1",
         "sessionId":"01JWQSHTR0KV0GGZSVC2PPATCE-b4f3196e-c25a-4673-9a36-0618dbfc2cfc"
      }
   }
}

When tried to deserialize it gets thrown this exception, (I tried without @JsonIgnoreProperties) too.

org.springframework.data.redis.serializer.SerializationException: Could not read JSON:Problem deserializing 'setterless' property ("audience"): no way to handle typed deser with setterless yet

This is my redis serializer config (i am using seperate ObjectMapper for this case)

    private ObjectMapper objectMapper() {
        ObjectMapper mapper = this.mapper.copy();
        mapper.addMixIn(CustomUserPrincipal.class,CustomUserPrincipalMixin.class);
        mapper.addMixIn(CustomUserOidcPrincipal.class, CustomUserOidcPrincipalMixin.class);
        mapper.addMixIn(HashSet.class, HashSetMixin.class);
        mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));

        return mapper;
    }

please help on this issue, i still dont get why every field is getting flatMapped when serialized.


Solution

  • So i fixed this problem by configuring objectmapper to use field only, instead of setters or getters.

    
       private ObjectMapper objectMapper() {
            ObjectMapper mapper = this.mapper.copy();
            mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
            mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
            mapper.addMixIn(CustomUserPrincipal.class, CustomUserPrincipalMixin.class);
            mapper.addMixIn(CustomOidcUserPrincipal.class, CustomOidcUserPrincipalMixin.class);
            mapper.addMixIn(HashSet.class, HashSetMixin.class);
            mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));
            return mapper;
        }
    

    So i guess the ObjectMapper was serializing based on OidcUser interface, and it called all the getters inside that also OidcIdToken,OidcUserInfo so on. If anyone can give a proper explanation on why this happened or give some reference, it would be appreciated.