diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 721e871ade1c92271bb8ac77dfe89e9761859265..a764413300fef3763c965cfc4b4a0ec38c07d104 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -87,7 +87,10 @@ grpc_credentials *grpc_credentials_ref(grpc_credentials *creds) {
 
 void grpc_credentials_unref(grpc_credentials *creds) {
   if (creds == NULL) return;
-  if (gpr_unref(&creds->refcount)) creds->vtable->destroy(creds);
+  if (gpr_unref(&creds->refcount)) {
+    creds->vtable->destruct(creds);
+    gpr_free(creds);
+  }
 }
 
 void grpc_credentials_release(grpc_credentials *creds) {
@@ -135,9 +138,26 @@ grpc_security_status grpc_credentials_create_security_connector(
       creds, target, args, request_metadata_creds, sc, new_args);
 }
 
-void grpc_server_credentials_release(grpc_server_credentials *creds) {
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds) {
   if (creds == NULL) return;
-  creds->vtable->destroy(creds);
+  if (gpr_unref(&creds->refcount)) {
+    creds->vtable->destruct(creds);
+    if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+      creds->processor.destroy(creds->processor.state);
+    }
+    gpr_free(creds);
+  }
+}
+
+void grpc_server_credentials_release(grpc_server_credentials *creds) {
+  grpc_server_credentials_unref(creds);
 }
 
 grpc_security_status grpc_server_credentials_create_security_connector(
@@ -158,25 +178,16 @@ void grpc_server_credentials_set_auth_metadata_processor(
   creds->processor = processor;
 }
 
-void grpc_server_credentials_destroy(grpc_server_credentials *creds) {
-  if (creds == NULL) return;
-  if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
-    creds->processor.destroy(creds->processor.state);
-  }
-  gpr_free(creds);
-}
-
 /* -- Ssl credentials. -- */
 
-static void ssl_destroy(grpc_credentials *creds) {
+static void ssl_destruct(grpc_credentials *creds) {
   grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
   if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
   if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
-  gpr_free(creds);
 }
 
-static void ssl_server_destroy(grpc_server_credentials *creds) {
+static void ssl_server_destruct(grpc_server_credentials *creds) {
   grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
   size_t i;
   for (i = 0; i < c->config.num_key_cert_pairs; i++) {
@@ -196,7 +207,6 @@ static void ssl_server_destroy(grpc_server_credentials *creds) {
     gpr_free(c->config.pem_cert_chains_sizes);
   }
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
-  grpc_server_credentials_destroy(creds);
 }
 
 static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
@@ -242,11 +252,11 @@ static grpc_security_status ssl_server_create_security_connector(
 }
 
 static grpc_credentials_vtable ssl_vtable = {
-    ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
+    ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
     ssl_create_security_connector};
 
 static grpc_server_credentials_vtable ssl_server_vtable = {
-    ssl_server_destroy, ssl_server_create_security_connector};
+    ssl_server_destruct, ssl_server_create_security_connector};
 
 static void ssl_copy_key_material(const char *input, unsigned char **output,
                                   size_t *output_size) {
@@ -327,9 +337,9 @@ grpc_server_credentials *grpc_ssl_server_credentials_create(
   grpc_ssl_server_credentials *c =
       gpr_malloc(sizeof(grpc_ssl_server_credentials));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_credentials));
   memset(c, 0, sizeof(grpc_ssl_server_credentials));
   c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
+  gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &ssl_server_vtable;
   ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
                           num_key_cert_pairs, force_client_auth, &c->config);
@@ -350,13 +360,12 @@ static void jwt_reset_cache(grpc_service_account_jwt_access_credentials *c) {
   c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
 }
 
-static void jwt_destroy(grpc_credentials *creds) {
+static void jwt_destruct(grpc_credentials *creds) {
   grpc_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   grpc_auth_json_key_destruct(&c->key);
   jwt_reset_cache(c);
   gpr_mu_destroy(&c->cache_mu);
-  gpr_free(c);
 }
 
 static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -421,7 +430,7 @@ static void jwt_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable jwt_vtable = {
-    jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
+    jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
     jwt_get_request_metadata, NULL};
 
 grpc_credentials *
@@ -453,13 +462,12 @@ grpc_credentials *grpc_service_account_jwt_access_credentials_create(
 
 /* -- Oauth2TokenFetcher credentials -- */
 
-static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
+static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
   gpr_mu_destroy(&c->mu);
   grpc_httpcli_context_destroy(&c->httpcli_context);
-  gpr_free(c);
 }
 
 static int oauth2_token_fetcher_has_request_metadata(
@@ -632,7 +640,7 @@ static void init_oauth2_token_fetcher(grpc_oauth2_token_fetcher_credentials *c,
 /* -- GoogleComputeEngine credentials. -- */
 
 static grpc_credentials_vtable compute_engine_vtable = {
-    oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata,
+    oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
     oauth2_token_fetcher_has_request_metadata_only,
     oauth2_token_fetcher_get_request_metadata, NULL};
 
@@ -663,15 +671,15 @@ grpc_credentials *grpc_google_compute_engine_credentials_create(
 
 /* -- GoogleRefreshToken credentials. -- */
 
-static void refresh_token_destroy(grpc_credentials *creds) {
+static void refresh_token_destruct(grpc_credentials *creds) {
   grpc_google_refresh_token_credentials *c =
       (grpc_google_refresh_token_credentials *)creds;
   grpc_auth_refresh_token_destruct(&c->refresh_token);
-  oauth2_token_fetcher_destroy(&c->base.base);
+  oauth2_token_fetcher_destruct(&c->base.base);
 }
 
 static grpc_credentials_vtable refresh_token_vtable = {
-    refresh_token_destroy, oauth2_token_fetcher_has_request_metadata,
+    refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
     oauth2_token_fetcher_has_request_metadata_only,
     oauth2_token_fetcher_get_request_metadata, NULL};
 
@@ -724,10 +732,9 @@ grpc_credentials *grpc_google_refresh_token_credentials_create(
 
 /* -- Metadata-only credentials. -- */
 
-static void md_only_test_destroy(grpc_credentials *creds) {
+static void md_only_test_destruct(grpc_credentials *creds) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
   grpc_credentials_md_store_unref(c->md_store);
-  gpr_free(c);
 }
 
 static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
@@ -768,7 +775,7 @@ static void md_only_test_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable md_only_test_vtable = {
-    md_only_test_destroy, md_only_test_has_request_metadata,
+    md_only_test_destruct, md_only_test_has_request_metadata,
     md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
     NULL};
 
@@ -789,10 +796,9 @@ grpc_credentials *grpc_md_only_test_credentials_create(const char *md_key,
 
 /* -- Oauth2 Access Token credentials. -- */
 
-static void access_token_destroy(grpc_credentials *creds) {
+static void access_token_destruct(grpc_credentials *creds) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
-  gpr_free(c);
 }
 
 static int access_token_has_request_metadata(const grpc_credentials *creds) {
@@ -814,7 +820,7 @@ static void access_token_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable access_token_vtable = {
-    access_token_destroy, access_token_has_request_metadata,
+    access_token_destruct, access_token_has_request_metadata,
     access_token_has_request_metadata_only, access_token_get_request_metadata,
     NULL};
 
@@ -838,14 +844,14 @@ grpc_credentials *grpc_access_token_credentials_create(const char *access_token,
 
 /* -- Fake transport security credentials. -- */
 
-static void fake_transport_security_credentials_destroy(
+static void fake_transport_security_credentials_destruct(
     grpc_credentials *creds) {
-  gpr_free(creds);
+  /* Nothing to do here. */
 }
 
-static void fake_transport_security_server_credentials_destroy(
+static void fake_transport_security_server_credentials_destruct(
     grpc_server_credentials *creds) {
-  grpc_server_credentials_destroy(creds);
+  /* Nothing to do here. */
 }
 
 static int fake_transport_security_has_request_metadata(
@@ -874,14 +880,14 @@ fake_transport_security_server_create_security_connector(
 }
 
 static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
-    fake_transport_security_credentials_destroy,
+    fake_transport_security_credentials_destruct,
     fake_transport_security_has_request_metadata,
     fake_transport_security_has_request_metadata_only, NULL,
     fake_transport_security_create_security_connector};
 
 static grpc_server_credentials_vtable
     fake_transport_security_server_credentials_vtable = {
-        fake_transport_security_server_credentials_destroy,
+        fake_transport_security_server_credentials_destruct,
         fake_transport_security_server_create_security_connector};
 
 grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
@@ -898,6 +904,7 @@ grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
   grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
   memset(c, 0, sizeof(grpc_server_credentials));
   c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+  gpr_ref_init(&c->refcount, 1);
   c->vtable = &fake_transport_security_server_credentials_vtable;
   return c;
 }
@@ -914,14 +921,13 @@ typedef struct {
   grpc_credentials_metadata_cb cb;
 } grpc_composite_credentials_metadata_context;
 
-static void composite_destroy(grpc_credentials *creds) {
+static void composite_destruct(grpc_credentials *creds) {
   grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
   size_t i;
   for (i = 0; i < c->inner.num_creds; i++) {
     grpc_credentials_unref(c->inner.creds_array[i]);
   }
   gpr_free(c->inner.creds_array);
-  gpr_free(creds);
 }
 
 static int composite_has_request_metadata(const grpc_credentials *creds) {
@@ -1037,7 +1043,7 @@ static grpc_security_status composite_create_security_connector(
 }
 
 static grpc_credentials_vtable composite_credentials_vtable = {
-    composite_destroy, composite_has_request_metadata,
+    composite_destruct, composite_has_request_metadata,
     composite_has_request_metadata_only, composite_get_request_metadata,
     composite_create_security_connector};
 
@@ -1136,10 +1142,9 @@ grpc_credentials *grpc_credentials_contains_type(
 
 /* -- IAM credentials. -- */
 
-static void iam_destroy(grpc_credentials *creds) {
+static void iam_destruct(grpc_credentials *creds) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
   grpc_credentials_md_store_unref(c->iam_md);
-  gpr_free(c);
 }
 
 static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -1159,7 +1164,7 @@ static void iam_get_request_metadata(grpc_credentials *creds,
 }
 
 static grpc_credentials_vtable iam_vtable = {
-    iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only,
+    iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
     iam_get_request_metadata, NULL};
 
 grpc_credentials *grpc_google_iam_credentials_create(
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index d9bd53adc27667c6a213e914c079b40e6b590cd5..8e4fed7615f4ea4d917a4d7c9be972e244d84c86 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -129,7 +129,7 @@ typedef void (*grpc_credentials_metadata_cb)(void *user_data,
                                              grpc_credentials_status status);
 
 typedef struct {
-  void (*destroy)(grpc_credentials *c);
+  void (*destruct)(grpc_credentials *c);
   int (*has_request_metadata)(const grpc_credentials *c);
   int (*has_request_metadata_only)(const grpc_credentials *c);
   void (*get_request_metadata)(grpc_credentials *c, grpc_pollset *pollset,
@@ -210,20 +210,28 @@ grpc_credentials *grpc_refresh_token_credentials_create_from_auth_refresh_token(
 /* --- grpc_server_credentials. --- */
 
 typedef struct {
-  void (*destroy)(grpc_server_credentials *c);
+  void (*destruct)(grpc_server_credentials *c);
   grpc_security_status (*create_security_connector)(
       grpc_server_credentials *c, grpc_security_connector **sc);
 } grpc_server_credentials_vtable;
 
+
+/* TODO(jboeuf): Add a refcount. */
 struct grpc_server_credentials {
   const grpc_server_credentials_vtable *vtable;
   const char *type;
+  gpr_refcount refcount;
   grpc_auth_metadata_processor processor;
 };
 
 grpc_security_status grpc_server_credentials_create_security_connector(
     grpc_server_credentials *creds, grpc_security_connector **sc);
 
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds);
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds);
+
 /* -- Ssl credentials. -- */
 
 typedef struct {
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 96ca4cbd76342bbae35112aaecb42ab59cab98a9..4749f5f516525326d5c999e7e480eadd41dc9f25 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -61,7 +61,7 @@ typedef struct grpc_server_secure_state {
   grpc_server *server;
   grpc_tcp_server *tcp;
   grpc_security_connector *sc;
-  grpc_auth_metadata_processor processor;
+  grpc_server_credentials *creds;
   tcp_endpoint_list *handshaking_tcp_endpoints;
   int is_shutdown;
   gpr_mu mu;
@@ -79,9 +79,7 @@ static void state_unref(grpc_server_secure_state *state) {
     gpr_mu_unlock(&state->mu);
     /* clean up */
     GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server");
-    if (state->processor.state != NULL && state->processor.destroy != NULL) {
-      state->processor.destroy(state->processor.state);
-    }
+    grpc_server_credentials_unref(state->creds);
     gpr_free(state);
   }
 }
@@ -94,7 +92,8 @@ static void setup_transport(void *statep, grpc_transport *transport,
   grpc_channel_args *args_copy;
   grpc_arg args_to_add[2];
   args_to_add[0] = grpc_security_connector_to_arg(state->sc);
-  args_to_add[1] = grpc_auth_metadata_processor_to_arg(&state->processor);
+  args_to_add[1] =
+      grpc_auth_metadata_processor_to_arg(&state->creds->processor);
   args_copy = grpc_channel_args_copy_and_add(
       grpc_server_get_channel_args(state->server), args_to_add,
       GPR_ARRAY_SIZE(args_to_add));
@@ -265,12 +264,7 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
   state->server = server;
   state->tcp = tcp;
   state->sc = sc;
-
-  /* Transfer ownership of the processor. */
-  state->processor = creds->processor;
-  creds->processor.state = NULL;
-  creds->processor.destroy =  NULL;
-  creds->processor.process = NULL;
+  state->creds = grpc_server_credentials_ref(creds);
 
   state->handshaking_tcp_endpoints = NULL;
   state->is_shutdown = 0;