Commit d58c7566 authored by Sietse Ringers's avatar Sietse Ringers

feat: support passing issuance time in revocation command to select a single credential

parent 2723a725
...@@ -139,8 +139,8 @@ func (s *Server) CancelSession(token string) error { ...@@ -139,8 +139,8 @@ func (s *Server) CancelSession(token string) error {
return nil return nil
} }
func (s *Server) Revoke(credid irma.CredentialTypeIdentifier, key string) error { func (s *Server) Revoke(credid irma.CredentialTypeIdentifier, key string, issued time.Time) error {
return s.conf.IrmaConfiguration.Revocation.Revoke(credid, key) return s.conf.IrmaConfiguration.Revocation.Revoke(credid, key, issued)
} }
func ParsePath(path string) (token, noun string, arg []string, err error) { func ParsePath(path string) (token, noun string, arg []string, err error) {
......
...@@ -59,7 +59,7 @@ func TestRevocationAll(t *testing.T) { ...@@ -59,7 +59,7 @@ func TestRevocationAll(t *testing.T) {
// revoke cred0 // revoke cred0
logger.Info("step 2") logger.Info("step 2")
require.NoError(t, revocationServer.Revoke(revocationTestCred, "cred0")) require.NoError(t, revocationServer.Revoke(revocationTestCred, "cred0", time.Time{}))
// perform another disclosure session with nonrevocation proof to see that cred1 still works // perform another disclosure session with nonrevocation proof to see that cred1 still works
// client updates its witness to the new accumulator first // client updates its witness to the new accumulator first
...@@ -70,7 +70,7 @@ func TestRevocationAll(t *testing.T) { ...@@ -70,7 +70,7 @@ func TestRevocationAll(t *testing.T) {
// revoke cred1 // revoke cred1
logger.Info("step 4") logger.Info("step 4")
require.NoError(t, revocationServer.Revoke(revocationTestCred, "cred1")) require.NoError(t, revocationServer.Revoke(revocationTestCred, "cred1", time.Time{}))
// try to perform session with revoked credential // try to perform session with revoked credential
// client notices that his credential is revoked and aborts // client notices that his credential is revoked and aborts
...@@ -334,7 +334,7 @@ func TestRevocationAll(t *testing.T) { ...@@ -334,7 +334,7 @@ func TestRevocationAll(t *testing.T) {
ValidUntil: time.Now().Add(-1 * time.Hour).UnixNano(), ValidUntil: time.Now().Add(-1 * time.Hour).UnixNano(),
})) }))
// Check existence of insterted record // Check existence of insterted record
rec, err := rev.IssuanceRecords(revocationTestCred, "1") rec, err := rev.IssuanceRecords(revocationTestCred, "1", time.Time{})
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, rec) require.NotEmpty(t, rec)
...@@ -342,7 +342,7 @@ func TestRevocationAll(t *testing.T) { ...@@ -342,7 +342,7 @@ func TestRevocationAll(t *testing.T) {
revocationConfiguration.IrmaConfiguration.Scheduler.RunAll() revocationConfiguration.IrmaConfiguration.Scheduler.RunAll()
// Check that issuance record is gone // Check that issuance record is gone
rec, err = rev.IssuanceRecords(revocationTestCred, "1") rec, err = rev.IssuanceRecords(revocationTestCred, "1", time.Time{})
require.Equal(t, gorm.ErrRecordNotFound, err) require.Equal(t, gorm.ErrRecordNotFound, err)
}) })
} }
...@@ -395,7 +395,7 @@ func revoke(t *testing.T, key string, conf *irma.RevocationStorage, acc *revocat ...@@ -395,7 +395,7 @@ func revoke(t *testing.T, key string, conf *irma.RevocationStorage, acc *revocat
Issued: time.Now().UnixNano(), Issued: time.Now().UnixNano(),
ValidUntil: time.Now().Add(1 * time.Hour).UnixNano(), ValidUntil: time.Now().Add(1 * time.Hour).UnixNano(),
})) }))
require.NoError(t, conf.Revoke(revocationTestCred, key)) require.NoError(t, conf.Revoke(revocationTestCred, key, time.Time{}))
sacc, err := conf.Accumulator(revocationTestCred, revocationPkCounter) sacc, err := conf.Accumulator(revocationTestCred, revocationPkCounter)
require.NoError(t, err) require.NoError(t, err)
*acc = *sacc.Accumulator *acc = *sacc.Accumulator
......
...@@ -201,6 +201,7 @@ type RevocationRequest struct { ...@@ -201,6 +201,7 @@ type RevocationRequest struct {
LDContext string `json:"@context,omitempty"` LDContext string `json:"@context,omitempty"`
CredentialType CredentialTypeIdentifier `json:"type"` CredentialType CredentialTypeIdentifier `json:"type"`
Key string `json:"revocationKey,omitempty"` Key string `json:"revocationKey,omitempty"`
Issued int64 `json:"issued,omitempty"`
} }
func (r *RevocationRequest) Validate() error { func (r *RevocationRequest) Validate() error {
......
...@@ -304,9 +304,13 @@ func (rs *RevocationStorage) AddIssuanceRecord(r *IssuanceRecord) error { ...@@ -304,9 +304,13 @@ func (rs *RevocationStorage) AddIssuanceRecord(r *IssuanceRecord) error {
return rs.sqldb.Insert(r) return rs.sqldb.Insert(r)
} }
func (rs *RevocationStorage) IssuanceRecords(typ CredentialTypeIdentifier, key string) ([]*IssuanceRecord, error) { func (rs *RevocationStorage) IssuanceRecords(typ CredentialTypeIdentifier, key string, issued time.Time) ([]*IssuanceRecord, error) {
where := map[string]interface{}{"cred_type": typ, "revocationkey": key}
if !issued.IsZero() {
where["Issued"] = issued.UnixNano()
}
var r []*IssuanceRecord var r []*IssuanceRecord
err := rs.sqldb.Find(&r, map[string]interface{}{"cred_type": typ, "revocationkey": key}) err := rs.sqldb.Find(&r, where)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -321,18 +325,18 @@ func (rs *RevocationStorage) IssuanceRecords(typ CredentialTypeIdentifier, key s ...@@ -321,18 +325,18 @@ func (rs *RevocationStorage) IssuanceRecords(typ CredentialTypeIdentifier, key s
// Revoke revokes the credential specified by key if found within the current database, // Revoke revokes the credential specified by key if found within the current database,
// by updating its revocation time to now, removing its revocation attribute from the current accumulator, // by updating its revocation time to now, removing its revocation attribute from the current accumulator,
// and updating the revocation database on disk. // and updating the revocation database on disk.
func (rs *RevocationStorage) Revoke(typ CredentialTypeIdentifier, key string) error { func (rs *RevocationStorage) Revoke(typ CredentialTypeIdentifier, key string, issued time.Time) error {
if rs.getSettings(typ).Mode != RevocationModeServer { if rs.getSettings(typ).Mode != RevocationModeServer {
return errors.Errorf("cannot revoke %s", typ) return errors.Errorf("cannot revoke %s", typ)
} }
return rs.sqldb.Transaction(func(tx sqlRevStorage) error { return rs.sqldb.Transaction(func(tx sqlRevStorage) error {
return rs.revoke(tx, typ, key) return rs.revoke(tx, typ, key, issued)
}) })
} }
func (rs *RevocationStorage) revoke(tx sqlRevStorage, typ CredentialTypeIdentifier, key string) error { func (rs *RevocationStorage) revoke(tx sqlRevStorage, typ CredentialTypeIdentifier, key string, issued time.Time) error {
var err error var err error
issrecords, err := rs.IssuanceRecords(typ, key) issrecords, err := rs.IssuanceRecords(typ, key, issued)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -7,6 +7,7 @@ package irmaserver ...@@ -7,6 +7,7 @@ package irmaserver
import ( import (
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"time"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/privacybydesign/irmago" "github.com/privacybydesign/irmago"
...@@ -99,11 +100,11 @@ func (s *Server) CancelSession(token string) error { ...@@ -99,11 +100,11 @@ func (s *Server) CancelSession(token string) error {
// Revoke revokes the earlier issued credential specified by key. (Can only be used if this server // Revoke revokes the earlier issued credential specified by key. (Can only be used if this server
// is the revocation server for the specified credential type and if the corresponding // is the revocation server for the specified credential type and if the corresponding
// issuer private key is present in the server configuration.) // issuer private key is present in the server configuration.)
func Revoke(credid irma.CredentialTypeIdentifier, key string) error { func Revoke(credid irma.CredentialTypeIdentifier, key string, issued time.Time) error {
return s.Revoke(credid, key) return s.Revoke(credid, key, issued)
} }
func (s *Server) Revoke(credid irma.CredentialTypeIdentifier, key string) error { func (s *Server) Revoke(credid irma.CredentialTypeIdentifier, key string, issued time.Time) error {
return s.Server.Revoke(credid, key) return s.Server.Revoke(credid, key, issued)
} }
// SubscribeServerSentEvents subscribes the HTTP client to server sent events on status updates // SubscribeServerSentEvents subscribes the HTTP client to server sent events on status updates
......
...@@ -622,7 +622,11 @@ func (s *Server) revoke(w http.ResponseWriter, requestor string, request *irma.R ...@@ -622,7 +622,11 @@ func (s *Server) revoke(w http.ResponseWriter, requestor string, request *irma.R
server.WriteError(w, server.ErrorUnauthorized, reason) server.WriteError(w, server.ErrorUnauthorized, reason)
return return
} }
if err := s.irmaserv.Revoke(request.CredentialType, request.Key); err != nil { var issued time.Time
if request.Issued != 0 {
issued = time.Unix(0, request.Issued)
}
if err := s.irmaserv.Revoke(request.CredentialType, request.Key, issued); err != nil {
server.WriteError(w, server.ErrorUnknown, err.Error()) server.WriteError(w, server.ErrorUnknown, err.Error())
} }
server.WriteString(w, "OK") server.WriteString(w, "OK")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment