diff --git a/src/sso/test/Makefile.am b/src/sso/test/Makefile.am
index 56096ad0c5699abb1efb3f60372ef066c3cbb761..babef4e45a4a52e0ea86d320e10c973e2f682ff3 100644
--- a/src/sso/test/Makefile.am
+++ b/src/sso/test/Makefile.am
@@ -1,5 +1,7 @@
 include $(top_srcdir)/Makefile.defs
 
+AUTOMAKE_OPTIONS = serial-tests
+
 check_PROGRAMS = \
 	sso_unittest \
 	tweetnacl_unittest
diff --git a/src/sso/test/fuzz_signed.c b/src/sso/test/fuzz_signed.c
index b5e025b7abf1376fe6c78cc8dcfbefea7277cc54..f567bd44f325e2c6d7b95f447abcb8e9a6ded8bd 100644
--- a/src/sso/test/fuzz_signed.c
+++ b/src/sso/test/fuzz_signed.c
@@ -32,6 +32,8 @@ static inline const unsigned char *get_secret_key() {
   return secret_key;
 }
 
+static char *static_groups[] = {"g1", "g2", NULL};
+
 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
   unsigned char *buf;
   unsigned char *b64buf;
@@ -52,6 +54,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 
   r = sso_ticket_open(&tkt, (const char *)b64buf, get_public_key());
   if (r == SSO_OK) {
+    sso_validate(tkt, "svc", "domain", NULL, static_groups);
     sso_ticket_free(tkt);
   }
 
diff --git a/src/sso/test/sso_unittest.cc b/src/sso/test/sso_unittest.cc
index 4c668574fe31c5c41e6d8051f63495c6c4a6edda..f3a721bb0682967e3f0a7f0fe7bbf4ec0978a6ef 100644
--- a/src/sso/test/sso_unittest.cc
+++ b/src/sso/test/sso_unittest.cc
@@ -98,13 +98,19 @@ protected:
   char *sign_ticket(sso_ticket_t t) {
     char buf[1024];
     EXPECT_EQ(0, sso_ticket_sign(t, secret_key, buf, sizeof(buf)));
+    return strdup(buf);
+  }
+
+  // Return a signed ticket, for test data generation.
+  char *sign_and_free_ticket(sso_ticket_t t) {
+    char *res = sign_ticket(t);
     // No further use for the original ticket.
     sso_ticket_free(t);
-    return strdup(buf);
+    return res;
   }
 
   // Sign a ticket with a random secret key.
-  char *sign_ticket_with_random_key(sso_ticket_t t) {
+  char *sign_and_free_ticket_with_random_key(sso_ticket_t t) {
     unsigned char pk[SSO_PUBLIC_KEY_SIZE], sk[SSO_SECRET_KEY_SIZE];
     sso_generate_keys(pk, sk);
     char buf[1024];
@@ -177,20 +183,20 @@ struct open_testdata {
 TEST_F(SSO, Open) {
   const char *groups[] = {"users", "wheel", "daemon", NULL};
   struct open_testdata td[] = {
-      {sign_ticket(
+      {sign_and_free_ticket(
            sso_ticket_new("user", "service/", "domain", NULL, NULL, 7200)),
        0},
-      {sign_ticket(
+      {sign_and_free_ticket(
            sso_ticket_new("user", "service/", "domain", NULL, groups, 7200)),
        0},
-      {sign_ticket(sso_ticket_new("user", "", "", NULL, NULL, 7200)), 0},
+      {sign_and_free_ticket(sso_ticket_new("user", "", "", NULL, NULL, 7200)), 0},
 
       {sign_string("5|user|service/|domain|1414402999|"),
        SSO_ERR_UNSUPPORTED_VERSION},
       {sign_string("4|definitely not a ticket"), SSO_ERR_DESERIALIZATION},
       {sign_string("4||||||"), 0},
 
-      {sign_ticket_with_random_key(
+      {sign_and_free_ticket_with_random_key(
            sso_ticket_new("user", "service/", "domain", NULL, NULL, 7200)),
        SSO_ERR_BAD_SIGNATURE},
 
@@ -332,6 +338,43 @@ TEST_F(SSO, Validation) {
   }
 }
 
+static bool is_ticket_equal(sso_ticket_t a, sso_ticket_t b) {
+  return (!strcmp(a->user, b->user) &&
+          !strcmp(a->service, b->service) &&
+          !strcmp(a->domain, b->domain) &&
+          !strcmp(a->nonce ?: "NULL", b->nonce ?: "NULL") &&
+          a->expires == b->expires);
+}
+
+TEST_F(SSO, Serialization) {
+  const char *groups_ok[] = {"users", "admins", NULL};
+  const char *groups_fail[] = {"users", "others", NULL};
+
+  sso_ticket_t td[] = {
+     sso_ticket_new("user", "service/", "domain", NULL, groups_ok, 7200),
+     sso_ticket_new("user", "service/", "domain", NULL, NULL, 7200),
+     sso_ticket_new("user", "service/", "domain", NULL, groups_fail, 7200),
+     sso_ticket_new("user", "service/", "other", NULL, groups_ok, 7200),
+     sso_ticket_new("user", "other/", "domain", NULL, groups_ok, 7200),
+     sso_ticket_new("user", "service/", "domain", NULL, NULL, -1000),
+     sso_ticket_new("user", "service/", "domain", "testnonce", NULL, 7200),
+     sso_ticket_new("user", "service/", "domain", "badnonce", NULL, 7200),
+     sso_ticket_new("user", "service/", "domain", NULL, NULL, 7200),
+     NULL,
+  };
+
+  for (sso_ticket_t *tdp = td; *tdp; tdp++) {
+    sso_ticket_t cur = *tdp, deserialized = NULL;
+    char *serialized;
+
+    serialized = sign_ticket(cur);
+    EXPECT_EQ(SSO_OK, sso_ticket_open(&deserialized, serialized, public_key));
+    EXPECT_NE(cur, deserialized);
+    EXPECT_EQ(true, is_ticket_equal(cur, deserialized));
+    free(serialized);
+  }
+}
+
 } // namespace
 
 int main(int argc, char **argv) {