Index: java/net/deterlab/abac/Context.java
===================================================================
--- java/net/deterlab/abac/Context.java	(revision 2405adf87c53199fcb7f3d52c6f97d0a8a2b11e5)
+++ java/net/deterlab/abac/Context.java	(revision 7f614c15cc77b4a8d54a9633b446742d7450c7ee)
@@ -515,4 +515,8 @@
      */
     protected void addIdentity(Identity id) { 
+	if (m_identities.contains(id)) {
+	    //XXX keep more recent
+	    return;
+	}
 	m_identities.add(id);
 	if (id.getName() != null && id.getKeyID() != null) {
Index: java/net/deterlab/abac/Credential.java
===================================================================
--- java/net/deterlab/abac/Credential.java	(revision 2405adf87c53199fcb7f3d52c6f97d0a8a2b11e5)
+++ java/net/deterlab/abac/Credential.java	(revision 7f614c15cc77b4a8d54a9633b446742d7450c7ee)
@@ -30,4 +30,6 @@
     /** The identity that issued the certificate */
     protected Identity id;
+    /** The expiration time of the credential */
+    protected Date m_expiration;
 
     /**
@@ -37,4 +39,5 @@
 	m_head = m_tail = null;
 	id = null;
+	m_expiration = null;
     }
     /**
@@ -50,4 +53,5 @@
         m_tail = tail;
 	id = null;
+	m_expiration = null;
     }
 
@@ -163,4 +167,9 @@
 
     /**
+     * Get the expiration Date of the credential.
+     */
+    public Date expiration() { return m_expiration; }
+
+    /**
      * Return an untranslated string form of the credential. The format is head
      * &lt;- tail. For example: A.r1 &lt;- B.r2.r3.  Principal names are key
Index: java/net/deterlab/abac/GENICredential.java
===================================================================
--- java/net/deterlab/abac/GENICredential.java	(revision 2405adf87c53199fcb7f3d52c6f97d0a8a2b11e5)
+++ java/net/deterlab/abac/GENICredential.java	(revision 7f614c15cc77b4a8d54a9633b446742d7450c7ee)
@@ -88,7 +88,6 @@
      */
     public GENICredential() {
-	m_head = m_tail = null;
+	super();
 	doc = null;
-	id = null;
     }
     /**
@@ -101,8 +100,6 @@
      */
     public GENICredential(Role head, Role tail) {
-        m_head = head;
-        m_tail = tail;
+	super(head, tail);
 	doc = null; 
-	id = null;
     }
 
@@ -282,8 +279,9 @@
 		throw new BadSignatureException("bad signature");
 
-	    Date exp = getTime(doc, "expires");
-
-	    if ( exp.before(new Date()))
-		throw new CertInvalidException("Certificate Expired " + exp);
+	    m_expiration = getTime(doc, "expires");
+
+	    if ( m_expiration.before(new Date()))
+		throw new CertInvalidException("Certificate Expired " + 
+			m_expiration);
 
 	    load_roles();
Index: java/net/deterlab/abac/GENIPrivCredential.java
===================================================================
--- java/net/deterlab/abac/GENIPrivCredential.java	(revision 2405adf87c53199fcb7f3d52c6f97d0a8a2b11e5)
+++ java/net/deterlab/abac/GENIPrivCredential.java	(revision 7f614c15cc77b4a8d54a9633b446742d7450c7ee)
@@ -41,7 +41,6 @@
      */
     public GENIPrivCredential() {
-	m_head = m_tail = null;
+	super();
 	doc = null;
-	id = null;
     }
     /**
@@ -53,9 +52,11 @@
      * @param tail the Role at the tail of the credential
      */
-    public GENIPrivCredential(Role head, Role tail, Document d, Identity i) {
+    public GENIPrivCredential(Role head, Role tail, Document d, Identity i,
+	    Date e) {
         m_head = head;
         m_tail = tail;
 	doc = null; 
 	id = null;
+	m_expiration = e;
     }
 
@@ -174,10 +175,10 @@
 				new Role(issuer.getKeyID() + ".speaks_for_" +
 				    owner.getKeyID()),
-				new Role(owner.getKeyID()), d, issuer));
+				new Role(owner.getKeyID()), d, issuer, exp));
 		    rv.add(new GENIPrivCredential(
 				new Role(issuer.getKeyID() + ".speaks_for_" +
 				    owner.getKeyID()),
 				new Role(owner.getKeyID() + ".speaks_for_" +
-				    owner.getKeyID()), d, issuer));
+				    owner.getKeyID()), d, issuer, exp));
 		}
 
@@ -187,5 +188,5 @@
 				target.getKeyID()),
 			    new Role(issuer.getKeyID() + ".speaks_for_" +
-				owner.getKeyID()), d, issuer));
+				owner.getKeyID()), d, issuer, exp));
 		if (cd ) {
 		    /* The rules for delegation, if necessary */
@@ -196,9 +197,9 @@
 				    + pname + "_" + target.getKeyID() + 
 				    "." + pname + "_" + target.getKeyID()), 
-				d, issuer));
+				d, issuer, exp));
 		    rv.add(new GENIPrivCredential(
 				new Role(issuer.getKeyID() + 
 				    ".can_delegate_" + pname),
-				new Role(owner.getKeyID()), d, issuer));
+				new Role(owner.getKeyID()), d, issuer, exp));
 		}
 	    }
Index: java/net/deterlab/abac/X509Credential.java
===================================================================
--- java/net/deterlab/abac/X509Credential.java	(revision 2405adf87c53199fcb7f3d52c6f97d0a8a2b11e5)
+++ java/net/deterlab/abac/X509Credential.java	(revision 7f614c15cc77b4a8d54a9633b446742d7450c7ee)
@@ -38,7 +38,6 @@
      */
     public X509Credential() {
-	m_head = m_tail = null;
+	super();
 	ac = null;
-	id = null;
     }
     /**
@@ -51,8 +50,6 @@
      */
     public X509Credential(Role head, Role tail) {
-        m_head = head;
-        m_tail = tail;
+	super(head, tail);
 	ac = null; 
-	id = null;
     }
 
@@ -97,4 +94,5 @@
 	if (id == null) throw new MissingIssuerException("Unknown identity");
 
+	m_expiration = ac.getNotAfter();
         load_roles();
 
