diff --git a/cmd/cashierd/main.go b/cmd/cashierd/main.go
index e71c126a41b7365b249a032cec3d07ca1dedade0..6e52ddfaed056420fb1e7d53c62d6cceb3c1eedc 100644
--- a/cmd/cashierd/main.go
+++ b/cmd/cashierd/main.go
@@ -15,6 +15,7 @@ import (
 	"net"
 	"net/http"
 	"os"
+	"strconv"
 	"strings"
 
 	"golang.org/x/oauth2"
@@ -231,20 +232,24 @@ func listAllCertsHandler(a *appContext, w http.ResponseWriter, r *http.Request)
 	if !a.isLoggedIn(w, r) {
 		return a.login(w, r)
 	}
-	certs, err := a.certstore.List()
-	if err != nil {
-		return http.StatusInternalServerError, err
+	tmpl := template.Must(template.New("certs.html").Parse(templates.Certs))
+	tmpl.Execute(w, map[string]interface{}{
+		csrf.TemplateTag: csrf.TemplateField(r),
+	})
+	return http.StatusOK, nil
+}
+
+func listCertsJSONHandler(a *appContext, w http.ResponseWriter, r *http.Request) (int, error) {
+	if !a.isLoggedIn(w, r) {
+		return http.StatusUnauthorized, errors.New(http.StatusText(http.StatusUnauthorized))
 	}
-	page := struct {
-		Certs []*store.CertRecord
-		CSRF  template.HTML
-	}{
-		Certs: certs,
-		CSRF:  csrf.TemplateField(r),
+	includeExpired, _ := strconv.ParseBool(r.URL.Query().Get("all"))
+	certs, err := a.certstore.List(includeExpired)
+	j, err := json.Marshal(certs)
+	if err != nil {
+		return http.StatusInternalServerError, errors.New(http.StatusText(http.StatusInternalServerError))
 	}
-
-	tmpl := template.Must(template.New("certs.html").Parse(templates.Certs))
-	tmpl.Execute(w, page)
+	w.Write(j)
 	return http.StatusOK, nil
 }
 
@@ -397,6 +402,7 @@ func main() {
 	r.Methods("GET").Path("/revoked").Handler(appHandler{ctx, listRevokedCertsHandler})
 	r.Methods("POST").Path("/admin/revoke").Handler(CSRF(appHandler{ctx, revokeCertHandler}))
 	r.Methods("GET").Path("/admin/certs").Handler(CSRF(appHandler{ctx, listAllCertsHandler}))
+	r.Methods("GET").Path("/admin/certs.json").Handler(appHandler{ctx, listCertsJSONHandler})
 	r.PathPrefix("/").Handler(http.FileServer(static.FS(false)))
 	h := handlers.LoggingHandler(logfile, r)
 
diff --git a/server/static/js/table.js b/server/static/js/table.js
new file mode 100644
index 0000000000000000000000000000000000000000..da0da3999c713001ef5a754e10e14abb277d0573
--- /dev/null
+++ b/server/static/js/table.js
@@ -0,0 +1,49 @@
+function reqListener() {
+  var recs = JSON.parse(this.responseText);
+  var table = document.querySelector('#cert-table');
+  var tbody = table.querySelector("#list");
+  while (tbody.rows.length > 0) {
+    tbody.deleteRow(0);
+  }
+  issuedList.clear();
+  recs.forEach(function makeTable(el, i, arr) {
+    var row = tbody.insertRow(-1);
+    row.insertCell(0).innerHTML = el.key_id;
+    row.insertCell(1).innerHTML = el.created_at;
+    row.insertCell(2).innerHTML = el.expires;
+    row.insertCell(3).innerHTML = el.principals;
+    row.insertCell(4).innerHTML = el.revoked;
+    // Index keyid and principals.
+    row.cells[0].classList = ["keyid"];
+    row.cells[3].classList = ["principals"];
+    if (el.revoked) {
+      row.insertCell(5).innerHTML = '<input style="margin:0;" type="checkbox" value="'+ el.key_id + '" name="cert_id" id="cert_id" />';
+    }
+    tbody.appendChild(row);
+  });
+  issuedList.reIndex();
+}
+
+function loadCerts(all) {
+  var r = new XMLHttpRequest();
+  var endpoint = '/admin/certs.json';
+  if (all) {
+    endpoint += '?all=true';
+  }
+  r.open('GET', endpoint);
+  r.addEventListener('load', reqListener);
+  r.send()
+}
+
+var SHOW_ALL = false;
+
+function toggleExpired() {
+  var button = document.querySelector("#toggle-certs");
+  SHOW_ALL = !SHOW_ALL;
+  loadCerts(SHOW_ALL);
+  if (SHOW_ALL == false) {
+    button.innerHTML = "Show Expired";
+  } else {
+    button.innerHTML = "Hide Expired";
+  }
+}
diff --git a/server/static/static.go b/server/static/static.go
index 16f1c72325eab283cdd901ef24024e9ca20558e8..28719caefcd81c932dd5a8ee96af5a485706db43 100644
--- a/server/static/static.go
+++ b/server/static/static.go
@@ -296,7 +296,7 @@ AAD//7viGWrCLAAA
 	"/static/js/list.min.js": {
 		local:   "server/static/js/list.min.js",
 		size:    15785,
-		modtime: 1472412760,
+		modtime: 1472414777,
 		compressed: `
 H4sIAAAJbogA/6x7bZPbNpLwX5H4uLRABHGkxMnuksaovI5TT65i++rsvS8UvQUCIMUxRcokNGOfxP3t
 V3gjQYrjnezlywzx1mh0N/oNrXl6KqnIq3JGQIIoYvDc9XCQoT085ymY0yiL9Veivu5JPcuxZ6d6GIuv
@@ -389,6 +389,26 @@ FG1iGP5vAAAA//84G4UUqT0AAA==
 `,
 	},
 
+	"/static/js/table.js": {
+		local:   "server/static/js/table.js",
+		size:    1414,
+		modtime: 1473620952,
+		compressed: `
+H4sIAAAJbogA/3xU3W4aPRC95ynm21ysUYghX9qb0k1VRai0Io0UkFopipBZD+Bi7I3t5UcV717Zy/4k
+0N4g1j5n5szxzMxzlTqhFRh8GQnrUKEhbfjdAtgwAwZTCwl8Gz98pxkzFolbCksN2kwrixPcuXb/iHVs
+JhES4DrN16gcfcnR7McoMXXakPgiReOuAiquSTPN95AU5DeM6EIK66KA3S6FRCABTo3eWipRLdwSbqFX
+yIUiFuUo0eGj3pJeYB5aAMLaHLmvj6YSmSHhxhdH59oMWLoklRFrtsKJV0NQdkB0gBlTZgiW6K3XG3IJ
+ZdE4n+vqOoQEf308vkMpSa9NhVJohpP7ESSAkq5wPxX8LPj6BJwaZA75lLmzhP9PCLjLhEF7Fn1zgs6M
+UKnImDxPeHdCMLjRKzyq73bhq+K4gxXuBQemONQBaRUwRSntU++ZppJZ6x8BEniKAil67r/B3bzF1SFL
+sJgDqbWUb3Oi/v1r9fFHobLcgXV7iUm0ZmYh1IdePwK3zzCJ0iWmq5neRbBhMsckii/r54JLiCNQbO2B
+aNxU8AgEb3x0b+NC3aHRiyzLUPG7pZCcGL0t+jH8NjrSYHDR9+Sh1ar6UGrG79A4S5iUjYmEBBRu4ef9
+aOhc9ogvOVpHqoFCxTMtlPcu7jK+FqrrNVr6y2oVJHr7qpBQEy4TiD8xKRNncozL0TFUZ6hI/GUwiTsV
+uJgfyjgfbFC5anPEXnXcaW6TI9Si4qTtK/Qqx8OHH9PPI/8ucyYt9huFO71YSByERuaNXTTLndPq7wsm
+uiiYV6HeYm008vxX/vfntbnlabu0pqYctZVGFflf9VQ0XuotHKVGwTJAafEfjKHg+JrROrT+BAAA//+v
+G1KqhgUAAA==
+`,
+	},
+
 	"/": {
 		isDir: true,
 		local: "server",
diff --git a/server/store/mem.go b/server/store/mem.go
index e63d00a2ef26db7888ccf63e5bec097abf84dcd3..54aa9655d011794bb4446d788129ba7a6740097e 100644
--- a/server/store/mem.go
+++ b/server/store/mem.go
@@ -40,7 +40,7 @@ func (ms *memoryStore) List(includeExpired bool) ([]*CertRecord, error) {
 	defer ms.Unlock()
 
 	for _, value := range ms.certs {
-		if !includeExpired && value.Expires.After(time.Now().UTC()) {
+		if !includeExpired && value.Expires.Before(time.Now().UTC()) {
 			continue
 		}
 		records = append(records, value)
@@ -62,7 +62,9 @@ func (ms *memoryStore) GetRevoked() ([]*CertRecord, error) {
 	var revoked []*CertRecord
 	all, _ := ms.List(false)
 	for _, r := range all {
-		revoked = append(revoked, r)
+		if r.Revoked {
+			revoked = append(revoked, r)
+		}
 	}
 	return revoked, nil
 }
diff --git a/server/store/store_test.go b/server/store/store_test.go
index 3552d1c069e73426cea617ddd2ca8d8d56338c3e..594da37168fba2abf7caa9fdc76ecd6ccdf7d31c 100644
--- a/server/store/store_test.go
+++ b/server/store/store_test.go
@@ -49,7 +49,7 @@ func testStore(t *testing.T, db CertStorer) {
 	if err := db.SetRecord(r); err != nil {
 		t.Error(err)
 	}
-	if _, err := db.List(); err != nil {
+	if _, err := db.List(true); err != nil {
 		t.Error(err)
 	}
 
diff --git a/server/templates/certs.go b/server/templates/certs.go
index 89ec5a1d5c24c4e9dd4dfded261c2d487e92eb43..0aa2b7cd5f1e415aad02e6c666482e12326bec15 100644
--- a/server/templates/certs.go
+++ b/server/templates/certs.go
@@ -13,7 +13,7 @@ const Certs = `
 	<link rel="stylesheet" href="/static/css/skeleton.css">
 	<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro" rel="stylesheet">
 </head>
-<body>
+<body onload="loadCerts()">
 	<div class="container">
 		<div class="page-header">
 			<h2>Issued SSH Certificates</h2>
@@ -21,8 +21,9 @@ const Certs = `
 
 		<div id="issued">
 			<input class="u-full-width search" type="text" placeholder="Search" id="q" />
+			<button class="button-primary" id="toggle-certs" onclick="toggleExpired()">Show Expired</button>
 			<form action="/admin/revoke" method="post" id="form_revoke">
-			{{ .CSRF }}
+			{{ .csrfField }}
 			<table id="cert-table">
 				<thead>
 				<tr>
@@ -34,17 +35,15 @@ const Certs = `
 					<th>Revoke</th>
 				</tr>
 				</thead>
-				<tbody class="list">
-				{{range .Certs}}
-					<tr>
-					<td class="keyid">{{.KeyID}}</td>
-					<td>{{.CreatedAt}}</td>
-					<td>{{.Expires}}</td>
-					<td class="principals">{{.Principals}}</td>
-					<td>{{.Revoked}}</td>
-					<td>{{if not .Revoked}}<input style="margin:0;" type="checkbox" value="{{.KeyID}}" name="cert_id" id="cert_id" />{{end}}</td>
+				<tbody id="list" class="list">
+				<tr>
+					<td class="keyid"></td>
+					<td></td>
+					<td></td>
+					<td class="principals"></td>
+					<td></td>
+					<td></td>
 					</tr>
-				{{ end }}
 				</tbody>
 			</table>
 			</form>
@@ -59,5 +58,6 @@ var options = {
 }
 var issuedList = new List('issued', options);
 </script>
+<script src="/static/js/table.js"></script>
 </html>
 `