Merge "veyron/services/identity: Many changes rolled into one."
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index 22e282e..863f367 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -510,7 +510,7 @@
 		blessing, starterr, finisherr string
 	}{
 		{blessing: "<nil>"},
-		{granter: granter{b: bless(pclient, pserver, "blessed")}, blessing: "client/blessed(0 caveats)"},
+		{granter: granter{b: bless(pclient, pserver, "blessed")}, blessing: "client/blessed"},
 		{granter: granter{err: errors.New("hell no")}, starterr: "hell no"},
 		{granter: granter{b: pclient.BlessingStore().Default()}, finisherr: "blessing granted not bound to this server"},
 	}
diff --git a/services/identity/blesser/macaroon.go b/services/identity/blesser/macaroon.go
index 9fc7798..a8b538e 100644
--- a/services/identity/blesser/macaroon.go
+++ b/services/identity/blesser/macaroon.go
@@ -16,7 +16,7 @@
 )
 
 type macaroonBlesser struct {
-	rt  veyron2.Runtime
+	rt  veyron2.Runtime // TODO(ashankar): Remove when the old security model is ripped out
 	key []byte
 }
 
@@ -27,18 +27,12 @@
 	Name     string
 }
 
-// NewMacaroonBlesserServer provides an identity.MacaroonBlesser Service that uses an
-// bless macaroon.
+// NewMacaroonBlesserServer provides an identity.MacaroonBlesser Service that generates blessings
+// after unpacking a BlessingMacaroon.
 //
-// Blessings generated by this server expire after duration. If domain is non-empty, then blessings
-// are generated only for email addresses from that domain.
-//
-// TODO(ashankar): Remove the veyron2.Runtime parameter once the old security model is ripped out.
+// TODO(ashankar): Remove the "r" argument once the switch to the new security model is complete.
 func NewMacaroonBlesserServer(r veyron2.Runtime, key []byte) interface{} {
-	return identity.NewServerMacaroonBlesser(&macaroonBlesser{
-		rt:  r,
-		key: key,
-	})
+	return identity.NewServerMacaroonBlesser(&macaroonBlesser{r, key})
 }
 
 func (b *macaroonBlesser) Bless(ctx ipc.ServerContext, macaroon string) (vdlutil.Any, error) {
@@ -46,7 +40,7 @@
 	if err != nil {
 		return nil, err
 	}
-	m := BlessingMacaroon{}
+	var m BlessingMacaroon
 	if err := vom.NewDecoder(bytes.NewBuffer(inputs)).Decode(&m); err != nil {
 		return nil, err
 	}
diff --git a/services/identity/blesser/oauth.go b/services/identity/blesser/oauth.go
index 320e370..df19987 100644
--- a/services/identity/blesser/oauth.go
+++ b/services/identity/blesser/oauth.go
@@ -20,7 +20,7 @@
 type googleOAuth struct {
 	rt                 veyron2.Runtime
 	authcodeClient     struct{ ID, Secret string }
-	accessTokenClients []struct{ ID string }
+	accessTokenClients []string
 	duration           time.Duration
 	domain             string
 	dischargerLocation string
@@ -29,20 +29,18 @@
 
 // GoogleParams represents all the parameters provided to NewGoogleOAuthBlesserServer
 type GoogleParams struct {
-	// The Veyron runtime to use
+	// The Veyron runtime to use. // TODO(ashankar): Remove once the old security model is ripped out.
 	R veyron2.Runtime
 	// The OAuth client IDs for the clients of the BlessUsingAccessToken RPCs.
-	AccessTokenClients []struct {
-		ID string
-	}
-	// The duration for which blessings will be valid.
-	BlessingDuration time.Duration
+	AccessTokenClients []string
 	// If non-empty, only email addresses from this domain will be blessed.
 	DomainRestriction string
 	// The object name of the discharger service. If this is empty then revocation caveats will not be granted.
 	DischargerLocation string
 	// The revocation manager that generates caveats and manages revocation.
 	RevocationManager *revocation.RevocationManager
+	// The duration for which blessings will be valid. (Used iff RevocationManager is nil).
+	BlessingDuration time.Duration
 }
 
 // NewGoogleOAuthBlesserServer provides an identity.OAuthBlesserService that uses authorization
@@ -92,7 +90,7 @@
 	}
 	audienceMatch := false
 	for _, c := range b.accessTokenClients {
-		if token.Audience == c.ID {
+		if token.Audience == c {
 			audienceMatch = true
 			break
 		}
@@ -104,35 +102,40 @@
 	if !token.VerifiedEmail {
 		return nil, "", fmt.Errorf("email not verified")
 	}
+
 	if ctx.LocalPrincipal() == nil || ctx.RemoteBlessings() == nil {
 		// TODO(ataly, ashankar): Old security model, remove this block.
 		return b.blessOldModel(ctx, token.Email)
 	}
-	return b.bless(ctx, token.Email)
+	// Append "/webapp" to the blessing. Since blessings issued by this process do not have
+	// many caveats on them and typically have a large expiry duration, use the "/webapp" suffix
+	// so that at least any logs call out the fact that this is a webapp (and ACLs can be used
+	// to kill authorization for them).
+	return b.bless(ctx, token.Email+security.ChainSeparator+"webapp")
 }
 
-func (b *googleOAuth) bless(ctx ipc.ServerContext, email string) (vdlutil.Any, string, error) {
+func (b *googleOAuth) bless(ctx ipc.ServerContext, extension string) (security.WireBlessings, string, error) {
+	var noblessings security.WireBlessings
+	self := ctx.LocalPrincipal()
 	var caveat security.Caveat
 	var err error
 	if b.revocationManager != nil {
-		// TODO(ataly, ashankar): Update the RevocationManager so that it uses the
-		// new security model.
-		revocationCaveat, err := b.revocationManager.NewCaveat(b.rt.Identity().PublicID(), b.dischargerLocation)
+		revocationCaveat, err := b.revocationManager.NewCaveat(self.PublicKey(), b.dischargerLocation)
 		if err != nil {
-			return nil, "", err
+			return noblessings, "", err
 		}
 		caveat, err = security.NewCaveat(revocationCaveat)
 	} else {
 		caveat, err = security.ExpiryCaveat(time.Now().Add(b.duration))
 	}
 	if err != nil {
-		return nil, "", err
+		return noblessings, "", err
 	}
-	blessing, err := ctx.LocalPrincipal().Bless(ctx.RemoteBlessings().PublicKey(), ctx.LocalBlessings(), email, caveat)
+	blessing, err := self.Bless(ctx.RemoteBlessings().PublicKey(), ctx.LocalBlessings(), extension, caveat)
 	if err != nil {
-		return nil, "", err
+		return noblessings, "", err
 	}
-	return security.MarshalBlessings(blessing), email, nil
+	return security.MarshalBlessings(blessing), extension, nil
 }
 
 // DEPRECATED
@@ -147,14 +150,7 @@
 	if self, err = self.Derive(ctx.LocalID()); err != nil {
 		return nil, "", err
 	}
-	var revocationCaveat security.ThirdPartyCaveat
-	if b.revocationManager != nil {
-		revocationCaveat, err = b.revocationManager.NewCaveat(b.rt.Identity().PublicID(), b.dischargerLocation)
-		if err != nil {
-			return nil, "", err
-		}
-	}
-	blessing, err := revocation.Bless(self, ctx.RemoteID(), name, b.duration, nil, revocationCaveat)
+	blessing, err := self.Bless(ctx.RemoteID(), name, b.duration, nil)
 	if err != nil {
 		return nil, "", err
 	}
diff --git a/services/identity/googleoauth/handler.go b/services/identity/googleoauth/handler.go
index 9f7c044..873360e 100644
--- a/services/identity/googleoauth/handler.go
+++ b/services/identity/googleoauth/handler.go
@@ -1,6 +1,6 @@
 // Package googleoauth implements an http.Handler that has two main purposes
 // listed below:
-
+//
 // (1) Uses OAuth 2.0 to authenticate with Google and then renders a page that
 //     displays all the blessings that were provided for that Google user.
 //     The client calls the /listblessings route which redirects to listblessingscallback which
@@ -39,7 +39,6 @@
 
 	"code.google.com/p/goauth2/oauth"
 
-	"veyron.io/veyron/veyron/services/identity/auditor"
 	"veyron.io/veyron/veyron/services/identity/blesser"
 	"veyron.io/veyron/veyron/services/identity/revocation"
 	"veyron.io/veyron/veyron/services/identity/util"
@@ -50,8 +49,7 @@
 )
 
 const (
-	clientIDCookie   = "VeyronHTTPIdentityClientID"
-	revocationCookie = "VeyronHTTPIdentityRevocationID"
+	clientIDCookie = "VeyronHTTPIdentityClientID"
 
 	ListBlessingsRoute         = "listblessings"
 	listBlessingsCallbackRoute = "listblessingscallback"
@@ -79,8 +77,8 @@
 	// (auditor.ReadAuditLog).
 	Auditor string
 	// The RevocationManager is used to revoke blessings granted with a revocation caveat.
-	// If this is empty then revocation caveats will not be added to blessings, and instead
-	// Expiry Caveats of duration BlessingDuration will be added.
+	// If nil, then revocation caveats cannot be added to blessings and an expiration caveat
+	// will be used instead.
 	RevocationManager *revocation.RevocationManager
 	// The object name of the discharger service.
 	DischargerLocation string
@@ -89,9 +87,6 @@
 	MacaroonBlessingService string
 	// If non-empty, only email addressses from this domain will be blessed.
 	DomainRestriction string
-	// BlessingDuration is the duration that blessings granted will be valid for
-	// if RevocationManager is nil.
-	BlessingDuration time.Duration
 }
 
 func (a *HandlerArgs) oauthConfig(redirectSuffix string) *oauth.Config {
@@ -176,72 +171,24 @@
 		util.HTTPBadRequest(w, r, err)
 		return
 	}
-
-	type tmplentry struct {
-		Blessee        security.PublicID
-		Start, End     time.Time
-		Blessed        security.PublicID
-		RevocationTime time.Time
-		Token          string
-	}
-	tmplargs := struct {
-		Log                chan tmplentry
-		Email, RevokeRoute string
-	}{
-		Log:         make(chan tmplentry),
-		Email:       email,
-		RevokeRoute: revokeRoute,
-	}
-	if entrych, err := auditor.ReadAuditLog(h.args.Auditor, email); err != nil {
-		vlog.Errorf("Unable to read audit log: %v", err)
-		util.HTTPServerError(w, fmt.Errorf("unable to read audit log"))
-		return
-	} else {
-		go func(ch chan tmplentry) {
-			defer close(ch)
-			for entry := range entrych {
-				if entry.Method != "Bless" || len(entry.Arguments) < 2 {
-					continue
-				}
-				var tmplentry tmplentry
-				var blessEntry revocation.BlessingAuditEntry
-				blessEntry, err = revocation.ReadBlessAuditEntry(entry)
-				tmplentry.Blessee = blessEntry.Blessee
-				tmplentry.Blessed = blessEntry.Blessed
-				tmplentry.Start = blessEntry.Start
-				tmplentry.End = blessEntry.End
-				if err != nil {
-					vlog.Errorf("Unable to read bless audit entry: %v", err)
-					continue
-				}
-				if blessEntry.RevocationCaveat != nil {
-					if revocationTime := h.args.RevocationManager.GetRevocationTime(blessEntry.RevocationCaveat.ID()); revocationTime != nil {
-						tmplentry.RevocationTime = *revocationTime
-					} else {
-						caveatID := base64.URLEncoding.EncodeToString([]byte(blessEntry.RevocationCaveat.ID()))
-						if tmplentry.Token, err = h.csrfCop.NewToken(w, r, revocationCookie, caveatID); err != nil {
-							vlog.Infof("Failed to create CSRF token[%v] for request %#v", err, r)
-							util.HTTPServerError(w, fmt.Errorf("failed to create new token: %v", err))
-							return
-						}
-					}
-				}
-				ch <- tmplentry
-			}
-		}(tmplargs.Log)
-	}
 	w.Header().Set("Context-Type", "text/html")
 	// This MaybeSetCookie call is needed to ensure that a cookie is created. Since the
 	// header cannot be changed once the body is written to, this needs to be called first.
-	if _, err = h.csrfCop.MaybeSetCookie(w, r, revocationCookie); err != nil {
+	if _, err = h.csrfCop.MaybeSetCookie(w, r, clientIDCookie); err != nil {
 		vlog.Infof("Failed to set CSRF cookie[%v] for request %#v", err, r)
 		util.HTTPServerError(w, err)
 		return
 	}
-	if err := tmplViewBlessings.Execute(w, tmplargs); err != nil {
-		vlog.Errorf("Unable to execute audit page template: %v", err)
-		util.HTTPServerError(w, err)
-	}
+	w.Write([]byte(fmt.Sprintf(`
+<html>
+<head>
+  <title>DISABLED FUNCTIONALITY</title>
+ </head>
+ <body>
+ <h1>Attention %s</h1>
+ <h2>This functionality has been temporarily disabled. ashankar@ and suharshs@ will know more</h2>
+ </body>
+ </html>`, email)))
 }
 
 func (h *handler) revoke(w http.ResponseWriter, r *http.Request) {
@@ -289,7 +236,7 @@
 
 func (h *handler) validateRevocationToken(Token string, r *http.Request) (string, error) {
 	var encCaveatID string
-	if err := h.csrfCop.ValidateToken(Token, r, revocationCookie, &encCaveatID); err != nil {
+	if err := h.csrfCop.ValidateToken(Token, r, clientIDCookie, &encCaveatID); err != nil {
 		return "", fmt.Errorf("invalid CSRF token: %v in request: %#v", err, r)
 	}
 	caveatID, err := base64.URLEncoding.DecodeString(encCaveatID)
@@ -397,6 +344,10 @@
 		util.HTTPBadRequest(w, r, fmt.Errorf("failed to extract caveats: ", err))
 		return
 	}
+	if len(caveats) == 0 {
+		util.HTTPBadRequest(w, r, fmt.Errorf("server disallows attempts to bless with no caveats"))
+		return
+	}
 	buf := &bytes.Buffer{}
 	m := blesser.BlessingMacaroon{
 		Creation: time.Now(),
@@ -426,18 +377,44 @@
 		return nil, err
 	}
 	var caveats []security.Caveat
-	var caveat security.Caveat
-	var err error
+	// Fill in the required caveat.
+	switch required := r.FormValue("requiredCaveat"); required {
+	case "Expiry":
+		str := r.FormValue("expiry")
+		d, err := time.ParseDuration(str)
+		if err != nil {
+			return nil, fmt.Errorf("failed to parse expiration duration(%q): %v", str, err)
+		}
+		expiry, err := security.ExpiryCaveat(time.Now().Add(d))
+		if err != nil {
+			return nil, fmt.Errorf("failed to create ExpiryCaveat: %v", err)
+		}
+		caveats = append(caveats, expiry)
+	case "Revocation":
+		if h.args.RevocationManager == nil {
+			return nil, fmt.Errorf("server not configured to support revocation")
+		}
+		tpc, err := h.args.RevocationManager.NewCaveat(h.args.R.Principal().PublicKey(), h.args.DischargerLocation)
+		if err != nil {
+			return nil, fmt.Errorf("failed to create revocation caveat: %v", err)
+		}
+		revocation, err := security.NewCaveat(tpc)
+		if err != nil {
+			return nil, fmt.Errorf("failed to create revocation caveat: %v", err)
+		}
+		caveats = append(caveats, revocation)
+	default:
+		return nil, fmt.Errorf("%q is not a valid required caveat", required)
+	}
+	if len(caveats) != 1 {
+		return nil, fmt.Errorf("server does not allow for un-restricted blessings")
+	}
 
-	userProvidedExpiryCaveat := false
-
+	// And find any additional ones
 	for i, cavName := range r.Form["caveat"] {
 		if cavName == "none" {
 			continue
 		}
-		if cavName == "ExpiryCaveat" {
-			userProvidedExpiryCaveat = true
-		}
 		args := strings.Split(r.Form[cavName][i], ",")
 		cavInfo, ok := caveatMap[cavName]
 		if !ok {
@@ -449,23 +426,6 @@
 		}
 		caveats = append(caveats, caveat)
 	}
-
-	// TODO(suharshs): have a checkbox in the form that says "include revocation caveat".
-	if h.args.RevocationManager != nil {
-		revocationCaveat, err := h.args.RevocationManager.NewCaveat(h.args.R.Identity().PublicID(), h.args.DischargerLocation)
-		if err != nil {
-			return nil, err
-		}
-		caveat, err = security.NewCaveat(revocationCaveat)
-	} else if !userProvidedExpiryCaveat {
-		caveat, err = security.ExpiryCaveat(time.Now().Add(h.args.BlessingDuration))
-	}
-	if err != nil {
-		return nil, err
-	}
-	// revocationCaveat need to be prepended for extraction in ReadBlessAuditEntry.
-	caveats = append([]security.Caveat{caveat}, caveats...)
-
 	return caveats, nil
 }
 
diff --git a/services/identity/googleoauth/template.go b/services/identity/googleoauth/template.go
index 6f8638c..a01f1e1 100644
--- a/services/identity/googleoauth/template.go
+++ b/services/identity/googleoauth/template.go
@@ -150,17 +150,36 @@
 </script>
 </head>
 <body class="container">
-<form class="form-signin" method="POST" name="input" action="/google/{{.MacaroonRoute}}">
+<form class="form-horizontal" method="POST" name="input" action="/google/{{.MacaroonRoute}}" role="form">
 <h2 class="form-signin-heading">{{.Extension}}</h2>
 <input type="text" class="hidden" name="macaroon" value="{{.Macaroon}}">
-<div class="form-group">
-  <label for="blessing-extension">Extension</label>
-  <input name="blessingExtension" type="text" class="form-control" id="blessing-extension" placeholder="(optional) If set to foo, then blessings will be of the form {{.Extension}}/foo">
+<div class="form-group form-group-lg">
+  <label class="col-sm-2" for="blessing-extension">Extension</label>
+  <div class="col-sm-10">
+  <input name="blessingExtension" type="text" class="form-control" id="blessing-extension" placeholder="(optional) name of the device/application for which the blessing is being sought, e.g. homelaptop">
+  </div>
 </div>
-<br/>
-<h3 class="form-signin-heading">Select Caveats</h3>
+<div class="form-group form-group-lg">
+  <label class="col-sm-2" for="required-caveat">Expiration</label>
+  <div class="col-sm-10" class="input-group" name="required-caveat">
+    <div class="radio">
+      <div class="input-group">
+        <input type="radio" name="requiredCaveat" id="requiredCaveat" value="Expiry" checked>
+        <input type="text" name="expiry" id="expiry" value="1h" placeholder="time after which the blessing will expire">
+      </div>
+    </div>
+    <div class="radio">
+      <label>
+      <!-- TODO(suharshs): Re-enable -->
+      <input type="radio" name="requiredCaveat" id="requiredCaveat" value="Revocation" disabled>
+      When explicitly revoked
+      </label>
+    </div>
+  </div>
+</div>
+<h4 class="form-signin-heading">Additional caveats</h4>
+<span class="help-text">Optional additional restrictions on the use of the blessing</span>
 <div class="caveatRow row">
-<br/>
   <div class="col-md-4">
     <select name="caveat" class="form-control caveats">
       <option value="none" selected="selected">Select a caveat.</option>
diff --git a/services/identity/handlers/handlers_test.go b/services/identity/handlers/handlers_test.go
index e3ed4a6..09d2ec8 100644
--- a/services/identity/handlers/handlers_test.go
+++ b/services/identity/handlers/handlers_test.go
@@ -7,20 +7,18 @@
 	"reflect"
 	"testing"
 
-	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
 
-	_ "veyron.io/veyron/veyron/profiles"
-	"veyron.io/veyron/veyron/services/identity/util"
+	vsecurity "veyron.io/veyron/veyron/security"
 )
 
 func TestPublicKey(t *testing.T) {
-	r, err := rt.New()
+	p, err := vsecurity.NewPrincipal()
 	if err != nil {
 		t.Fatal(err)
 	}
-	defer r.Cleanup()
-	ts := httptest.NewServer(PublicKey{r.Identity().PublicID()})
+	key := p.PublicKey()
+	ts := httptest.NewServer(PublicKey{key})
 	defer ts.Close()
 	response, err := http.Get(ts.URL)
 	if err != nil {
@@ -34,40 +32,7 @@
 	if err != nil {
 		t.Fatal(err)
 	}
-	if want := r.Identity().PublicKey(); !reflect.DeepEqual(got, want) {
+	if want := key; !reflect.DeepEqual(got, want) {
 		t.Errorf("Got %v, want %v", got, want)
 	}
 }
-
-func TestRandom(t *testing.T) {
-	r, err := rt.New()
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer r.Cleanup()
-	ts := httptest.NewServer(Random{r})
-	defer ts.Close()
-
-	got, err := parseResponse(http.Get(ts.URL))
-	if err != nil {
-		t.Fatal(err)
-	}
-	if id, ok := got.(security.PrivateID); !ok {
-		t.Fatalf("Got %T want security.PrivateID", got, id)
-	}
-}
-
-func parseResponse(r *http.Response, err error) (interface{}, error) {
-	if err != nil {
-		return nil, err
-	}
-	b64, err := ioutil.ReadAll(r.Body)
-	if err != nil {
-		return nil, err
-	}
-	var parsed interface{}
-	if err := util.Base64VomDecode(string(b64), &parsed); err != nil {
-		return nil, err
-	}
-	return parsed, nil
-}
diff --git a/services/identity/handlers/publickey.go b/services/identity/handlers/publickey.go
index 640e826..7ab8c96 100644
--- a/services/identity/handlers/publickey.go
+++ b/services/identity/handlers/publickey.go
@@ -1,7 +1,6 @@
 package handlers
 
 import (
-	"fmt"
 	"net/http"
 
 	"veyron.io/veyron/veyron/services/identity/util"
@@ -10,15 +9,15 @@
 
 // PublicKey is an http.Handler implementation that renders a public key in
 // DER format.
-type PublicKey struct{ P security.PublicID }
+type PublicKey struct{ K security.PublicKey }
 
 func (h PublicKey) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	der, err := h.P.PublicKey().MarshalBinary()
+	der, err := h.K.MarshalBinary()
 	if err != nil {
 		util.HTTPServerError(w, err)
 		return
 	}
 	w.Header().Set("Content-Type", "application/octet-stream")
-	w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%v.der", h.P))
+	w.Header().Set("Content-Disposition", "attachment; filename=publickey.der")
 	w.Write(der)
 }
diff --git a/services/identity/handlers/random.go b/services/identity/handlers/random.go
deleted file mode 100644
index 5a19bfd..0000000
--- a/services/identity/handlers/random.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package handlers
-
-import (
-	"fmt"
-	"math/rand"
-	"net/http"
-	"time"
-
-	"veyron.io/veyron/veyron/services/identity/util"
-	"veyron.io/veyron/veyron2"
-)
-
-// Random is an http.Handler implementation that mints a new Veyron PrivateID
-// with a random name.
-type Random struct{ Runtime veyron2.Runtime }
-
-func (h Random) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-	name := fmt.Sprintf("random:%d", rand.Intn(1000))
-	id, err := h.Runtime.NewIdentity(name)
-	if err != nil {
-		util.HTTPServerError(w, err)
-		return
-	}
-	// Bless this with the identity of the runtime, valid for 1 hour.
-	blessing, err := h.Runtime.Identity().Bless(id.PublicID(), name, 1*time.Hour, nil)
-	if err != nil {
-		util.HTTPServerError(w, err)
-		return
-	}
-	id, err = id.Derive(blessing)
-	if err != nil {
-		util.HTTPServerError(w, err)
-		return
-	}
-	util.HTTPSend(w, id)
-}
diff --git a/services/identity/identityd/main.go b/services/identity/identityd/main.go
index 18ab86c..f8ec17c 100644
--- a/services/identity/identityd/main.go
+++ b/services/identity/identityd/main.go
@@ -22,8 +22,6 @@
 	"veyron.io/veyron/veyron2/vlog"
 
 	"veyron.io/veyron/veyron/lib/signals"
-	vsecurity "veyron.io/veyron/veyron/security"
-	"veyron.io/veyron/veyron/security/audit"
 	"veyron.io/veyron/veyron/services/identity/auditor"
 	"veyron.io/veyron/veyron/services/identity/blesser"
 	"veyron.io/veyron/veyron/services/identity/googleoauth"
@@ -33,15 +31,15 @@
 	"veyron.io/veyron/veyron/services/security/discharger"
 
 	"veyron.io/veyron/veyron/profiles/static"
-	_ "veyron.io/veyron/veyron/runtimes/google/security"
 )
 
 var (
-	httpaddr      = flag.String("httpaddr", "localhost:8125", "Address on which the HTTP server listens on.")
-	tlsconfig     = flag.String("tlsconfig", "", "Comma-separated list of TLS certificate and private key files. If empty, will not use HTTPS.")
-	host          = flag.String("host", defaultHost(), "Hostname the HTTP server listens on. This can be the name of the host running the webserver, but if running behind a NAT or load balancer, this should be the host name that clients will connect to. For example, if set to 'x.com', Veyron identities will have the IssuerName set to 'x.com' and clients can expect to find the public key of the signer at 'x.com/pubkey/'.")
-	minExpiryDays = flag.Int("min_expiry_days", 365, "Minimum expiry time (in days) of identities issued by this server")
+	// Flags controlling the HTTP server
+	httpaddr  = flag.String("httpaddr", "localhost:8125", "Address on which the HTTP server listens on.")
+	tlsconfig = flag.String("tlsconfig", "", "Comma-separated list of TLS certificate and private key files. If empty, will not use HTTPS.")
+	host      = flag.String("host", defaultHost(), "Hostname the HTTP server listens on. This can be the name of the host running the webserver, but if running behind a NAT or load balancer, this should be the host name that clients will connect to. For example, if set to 'x.com', Veyron identities will have the IssuerName set to 'x.com' and clients can expect to find the public key of the signer at 'x.com/pubkey/'.")
 
+	// Flags controlling auditing of Blessing operations.
 	auditprefix = flag.String("audit", "", "File prefix to files where auditing information will be written.")
 	auditfilter = flag.String("audit_filter", "", "If non-empty, instead of starting the server the audit log will be dumped to STDOUT (with the filter set to the value of this flag. '/' can be used to dump all events).")
 
@@ -51,7 +49,7 @@
 	googleConfigAndroid = flag.String("google_config_android", "", "Path to the JSON-encoded OAuth client configuration for Android applications that obtain blessings from this server (via the OAuthBlesser.BlessUsingAccessToken RPC) from this server.")
 	googleDomain        = flag.String("google_domain", "", "An optional domain name. When set, only email addresses from this domain are allowed to authenticate via Google OAuth")
 
-	// Revoker/Discharger configuration
+	// Revocation/expiry configuration.
 	// TODO(ashankar,ataly,suharshs): Re-enable by default once the move to the new security API is complete?
 	revocationDir = flag.String("revocation_dir", "" /*filepath.Join(os.TempDir(), "revocation_dir")*/, "Path where the revocation manager will store caveat and revocation information.")
 )
@@ -64,7 +62,7 @@
 
 func main() {
 	flag.Usage = usage
-	r := rt.Init(providerIdentity())
+	r := rt.Init(providerIdentityOld(), providerPrincipal())
 	defer r.Cleanup()
 
 	if len(*auditfilter) > 0 {
@@ -79,10 +77,7 @@
 	}
 
 	// Setup handlers
-	http.Handle("/pubkey/", handlers.PublicKey{r.Identity().PublicID()}) // public key of this server
-	if enableRandomHandler() {
-		http.Handle("/random/", handlers.Random{r}) // mint identities with a random name
-	}
+	http.Handle("/pubkey/", handlers.PublicKey{r.Principal().PublicKey()}) // public key of this server
 	macaroonKey := make([]byte, 32)
 	if _, err := rand.Read(macaroonKey); err != nil {
 		vlog.Fatalf("macaroonKey generation failed: %v", err)
@@ -92,9 +87,7 @@
 	if err != nil {
 		vlog.Fatalf("Failed to setup veyron services for blessing: %v", err)
 	}
-	if ipcServer != nil {
-		defer ipcServer.Stop()
-	}
+	defer ipcServer.Stop()
 	if clientID, clientSecret, ok := getOAuthClientIDAndSecret(*googleConfigWeb); ok {
 		n := "/google/"
 		h, err := googleoauth.NewHandler(googleoauth.HandlerArgs{
@@ -105,22 +98,21 @@
 			ClientSecret:            clientSecret,
 			Auditor:                 *auditprefix,
 			RevocationManager:       revocationManager,
-			BlessingDuration:        time.Duration(*minExpiryDays) * 24 * time.Hour,
 			MacaroonBlessingService: naming.JoinAddressName(published[0], macaroonService),
 		})
 		if err != nil {
-			vlog.Fatalf("Failed to create googleoauth handler: %v", err)
+			vlog.Fatalf("Failed to create HTTP handler for google-based authentication: %v", err)
 		}
 		http.Handle(n, h)
 	}
 	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		args := struct {
-			Self                            security.PublicID
+			Self                            security.Blessings
 			RandomWeb                       bool
 			GoogleServers, DischargeServers []string
 			ListBlessingsRoute              string
 		}{
-			Self:      rt.R().Identity().PublicID(),
+			Self:      rt.R().Principal().BlessingStore().Default(),
 			RandomWeb: enableRandomHandler(),
 		}
 		if revocationManager != nil {
@@ -152,54 +144,44 @@
 // newDispatcher returns a dispatcher for both the blessing and the discharging service.
 // their suffix. ReflectInvoker is used to invoke methods.
 func newDispatcher(googleParams blesser.GoogleParams, macaroonKey []byte) ipc.Dispatcher {
-	d := &dispatcher{
-		invokers: map[string]ipc.Invoker{
-			macaroonService:   ipc.ReflectInvoker(blesser.NewMacaroonBlesserServer(googleParams.R, macaroonKey)),
-			dischargerService: ipc.ReflectInvoker(services.NewServerDischarger(discharger.NewDischarger(googleParams.R.Identity()))),
-		},
-		auth: vsecurity.NewACLAuthorizer(security.ACL{In: map[security.BlessingPattern]security.LabelSet{
-			security.AllPrincipals: security.AllLabels,
-		}}),
-	}
+	d := dispatcher(map[string]ipc.Invoker{
+		macaroonService:   ipc.ReflectInvoker(blesser.NewMacaroonBlesserServer(googleParams.R, macaroonKey)),
+		dischargerService: ipc.ReflectInvoker(services.NewServerDischarger(discharger.NewDischarger())),
+	})
 	if len(*googleConfigChrome) > 0 || len(*googleConfigAndroid) > 0 {
-		d.invokers[googleService] = ipc.ReflectInvoker(blesser.NewGoogleOAuthBlesserServer(googleParams))
+		d[googleService] = ipc.ReflectInvoker(blesser.NewGoogleOAuthBlesserServer(googleParams))
 	}
 	return d
 }
 
-type dispatcher struct {
-	invokers map[string]ipc.Invoker
-	auth     security.Authorizer
-}
+type allowEveryoneAuthorizer struct{}
 
-var _ ipc.Dispatcher = (*dispatcher)(nil)
+func (allowEveryoneAuthorizer) Authorize(security.Context) error { return nil }
+
+type dispatcher map[string]ipc.Invoker
 
 func (d dispatcher) Lookup(suffix, method string) (ipc.Invoker, security.Authorizer, error) {
-	if invoker := d.invokers[suffix]; invoker != nil {
-		return invoker, d.auth, nil
+	if invoker := d[suffix]; invoker != nil {
+		return invoker, allowEveryoneAuthorizer{}, nil
 	}
 	return nil, nil, verror.NoExistf("%q is not a valid suffix at this server", suffix)
 }
 
 // Starts the blessing services and the discharging service on the same port.
 func setupServices(r veyron2.Runtime, revocationManager *revocation.RevocationManager, macaroonKey []byte) (ipc.Server, []string, error) {
-	var enable bool
 	googleParams := blesser.GoogleParams{
-		R:                 r,
-		BlessingDuration:  time.Duration(*minExpiryDays) * 24 * time.Hour,
+		R: r,
+		// TODO(ashankar,nlacasse): Figure out how to have web-appications use the "caveats" form and
+		// always select an expiry instead of forcing a ridiculously large value here.
+		BlessingDuration:  365 * 24 * time.Hour,
 		DomainRestriction: *googleDomain,
 		RevocationManager: revocationManager,
 	}
 	if clientID, ok := getOAuthClientID(*googleConfigChrome); ok {
-		enable = true
-		googleParams.AccessTokenClients = append(googleParams.AccessTokenClients, struct{ ID string }{clientID})
+		googleParams.AccessTokenClients = append(googleParams.AccessTokenClients, clientID)
 	}
 	if clientID, ok := getOAuthClientID(*googleConfigAndroid); ok {
-		enable = true
-		googleParams.AccessTokenClients = append(googleParams.AccessTokenClients, struct{ ID string }{clientID})
-	}
-	if !enable {
-		return nil, nil, nil
+		googleParams.AccessTokenClients = append(googleParams.AccessTokenClients, clientID)
 	}
 	server, err := r.NewServer()
 	if err != nil {
@@ -207,17 +189,16 @@
 	}
 	ep, err := server.ListenX(static.ListenSpec)
 	if err != nil {
-		return nil, nil, fmt.Errorf("server.Listen(%s) failed: %v", static.ListenSpec, err)
+		return nil, nil, fmt.Errorf("server.Listen(%v) failed: %v", static.ListenSpec, err)
 	}
 	googleParams.DischargerLocation = naming.JoinAddressName(ep.String(), dischargerService)
 
 	dispatcher := newDispatcher(googleParams, macaroonKey)
-	objectname := fmt.Sprintf("identity/%s", r.Identity().PublicID().Names()[0])
+	objectname := naming.Join("identity", fmt.Sprintf("%v", r.Principal().BlessingStore().Default()))
 	if err := server.Serve(objectname, dispatcher); err != nil {
 		return nil, nil, fmt.Errorf("failed to start Veyron services: %v", err)
 	}
-	vlog.Infof("Google blessing and discharger services enabled at endpoint %v and name %q", ep, objectname)
-
+	vlog.Infof("Google blessing and discharger services enabled at %v", naming.JoinAddressName(ep.String(), objectname))
 	published, _ := server.Published()
 	if len(published) == 0 {
 		// No addresses published, publish the endpoint instead (which may not be usable everywhere, but oh-well).
@@ -280,19 +261,15 @@
 }
 
 func usage() {
-	fmt.Fprintf(os.Stderr, `%s starts an HTTP server that mints veyron identities in response to GET requests.
+	fmt.Fprintf(os.Stderr, `%s starts an HTTP server that brokers blessings after authenticating through OAuth.
 
 To generate TLS certificates so the HTTP server can use SSL:
 go run $GOROOT/src/pkg/crypto/tls/generate_cert.go --host <IP address>
 
-To generate an identity for this service itself, use:
-go install veyron/tools/identity && ./bin/identity generate <name> ><filename>
-and set the VEYRON_IDENTITY environment variable when running this application.
+To use Google as an OAuth provider the --google_config_* flags must be set to point to
+the a JSON file obtained after registering the application with the Google Developer Console
+at https://cloud.google.com/console
 
-To enable use of Google APIs to use Google OAuth for authorization, set --google_config,
-which must point to the contents of a JSON file obtained after registering your application
-with the Google Developer Console at:
-https://code.google.com/apis/console
 More details on Google OAuth at:
 https://developers.google.com/accounts/docs/OAuth2Login
 
@@ -309,10 +286,27 @@
 	return host
 }
 
-// providerIdentity returns the identity of the identity provider (i.e., this program) itself.
-func providerIdentity() veyron2.ROpt {
-	// TODO(ashankar): This scheme of initializing a runtime just to share the "load identity" code is ridiculous.
-	// Figure out a way to update the runtime's identity with a wrapper and avoid this spurios "New" call.
+// providerPrincipal returns the Principal to use for the identity provider (i.e., this program).
+func providerPrincipal() veyron2.ROpt {
+	// TODO(ashankar): Somewhat silly to have to create a runtime, but oh-well.
+	r, err := rt.New()
+	if err != nil {
+		vlog.Fatal(err)
+	}
+	defer r.Cleanup()
+	p := r.Principal()
+	// TODO(ashankar): Hook this up with Suharsh's new auditor implementation.
+	// DO NOT SUBMIT
+	if len(*auditprefix) == 0 {
+		return options.RuntimePrincipal{p}
+	}
+	vlog.Fatalf("--auditprefix is not supported just yet!")
+	return nil
+}
+
+// TOOD(ashankar): Remove
+// providerIdentityOld returns the PrivateID of the identity provider (i.e., this program) itself.
+func providerIdentityOld() veyron2.ROpt {
 	r, err := rt.New()
 	if err != nil {
 		vlog.Fatal(err)
@@ -320,11 +314,8 @@
 	defer r.Cleanup()
 	id := r.Identity()
 	if len(*auditprefix) > 0 {
-		auditor, err := auditor.NewFileAuditor(*auditprefix)
-		if err != nil {
-			vlog.Fatal(err)
-		}
-		id = audit.NewPrivateID(id, auditor)
+		vlog.Errorf("Auditing is temporarily disabled. Ask suharshs@ for details")
+		*auditprefix = ""
 	}
 	return options.RuntimeID{id}
 }
@@ -366,7 +357,7 @@
 </head>
 <body>
 <div class="container">
-<div class="page-header"><h2>{{.Self.Names}}</h2><h4>A Veyron Blessing Provider</h4></div>
+<div class="page-header"><h2>{{.Self}}</h2><h4>A Veyron Blessing Provider</h4></div>
 <div class="well">
 This is a Veyron identity provider that provides blessings with the name prefix <mark>{{.Self}}</mark>.
 <br/>
@@ -384,10 +375,7 @@
 {{end}}
 {{if .ListBlessingsRoute}}
 <li>You can <a class="btn btn-xs btn-primary" href="/google/{{.ListBlessingsRoute}}">enumerate</a> blessings provided with your
-email address as the name.</li>
-{{end}}
-{{if .RandomWeb}}
-<li>You can obtain a randomly assigned PrivateID <a class="btn btn-sm btn-primary" href="/random/">here</a></li>
+email address.</li>
 {{end}}
 </ul>
 </div>
diff --git a/services/identity/revocation/bless.go b/services/identity/revocation/bless.go
deleted file mode 100644
index 03f8df3..0000000
--- a/services/identity/revocation/bless.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package revocation
-
-import (
-	"fmt"
-	"time"
-
-	vsecurity "veyron.io/veyron/veyron/security"
-	"veyron.io/veyron/veyron/security/audit"
-
-	"veyron.io/veyron/veyron2/security"
-)
-
-// Bless creates a blessing on behalf of the identity server.
-func Bless(server security.PrivateID, blessee security.PublicID, email string, duration time.Duration, caveats []security.Caveat, revocationCaveat security.ThirdPartyCaveat) (security.PublicID, error) {
-	if revocationCaveat != nil {
-		caveat, err := security.NewCaveat(revocationCaveat)
-		if err != nil {
-			return nil, err
-		}
-		// revocationCaveat must be prepended because it is assumed to be first by ReadBlessAuditEntry.
-		caveats = append([]security.Caveat{caveat}, caveats...)
-	}
-	// TODO(suharshs): Extend the duration for blessings with provided revocaionCaveats.
-	return server.Bless(blessee, email, duration, caveats)
-}
-
-type BlessingAuditEntry struct {
-	Blessee, Blessed security.PublicID
-	Start, End       time.Time
-	RevocationCaveat security.ThirdPartyCaveat
-}
-
-// ReadBlessAuditEntry is for use in the googleauth.handler to parse the arguments to the Bless call in util.Bless.
-func ReadBlessAuditEntry(entry audit.Entry) (BlessingAuditEntry, error) {
-	var blessEntry BlessingAuditEntry
-
-	if len(entry.Arguments) < 4 || len(entry.Results) < 1 {
-		return blessEntry, fmt.Errorf("entry is invalid format")
-	}
-
-	blessEntry.Blessee, _ = entry.Arguments[0].(security.PublicID)
-	blessEntry.Start = entry.Timestamp
-	if duration, ok := entry.Arguments[2].(int64); ok {
-		blessEntry.End = blessEntry.Start.Add(time.Duration(duration))
-	}
-	blessEntry.Blessed, _ = entry.Results[0].(security.PublicID)
-	caveats, _ := entry.Arguments[3].([]security.Caveat)
-	if len(caveats) > 0 {
-		revocationCaveat, err := vsecurity.CaveatValidators(caveats[0])
-		if err != nil {
-			return blessEntry, err
-		}
-		blessEntry.RevocationCaveat, _ = revocationCaveat[0].(security.ThirdPartyCaveat)
-	}
-	return blessEntry, nil
-}
diff --git a/services/identity/revocation/bless_test.go b/services/identity/revocation/bless_test.go
deleted file mode 100644
index 4643c2e..0000000
--- a/services/identity/revocation/bless_test.go
+++ /dev/null
@@ -1,105 +0,0 @@
-package revocation
-
-import (
-	"os"
-	"path/filepath"
-	"reflect"
-	"testing"
-	"time"
-
-	"veyron.io/veyron/veyron/security/audit"
-
-	"veyron.io/veyron/veyron2/rt"
-	"veyron.io/veyron/veyron2/security"
-)
-
-//TODO(suharshs,ashankar,ataly): switch this to the new security model.
-
-type auditor struct {
-	LastEntry audit.Entry
-}
-
-func (a *auditor) Audit(entry audit.Entry) error {
-	a.LastEntry = entry
-	return nil
-}
-
-func newAuditedPrivateID(a *auditor) (security.PrivateID, error) {
-	r, err := rt.New()
-	if err != nil {
-		return nil, err
-	}
-	defer r.Cleanup()
-	id := r.Identity()
-	if err != nil {
-		return nil, err
-	}
-	return audit.NewPrivateID(id, a), err
-}
-
-func TestReadBlessAudit(t *testing.T) {
-	var a auditor
-	var revocationDir = filepath.Join(os.TempDir(), "util_bless_test_dir")
-	os.MkdirAll(revocationDir, 0700)
-	defer os.RemoveAll(revocationDir)
-
-	self, err := newAuditedPrivateID(&a)
-	if err != nil {
-		t.Fatalf("failed to create new audited private id: %v", err)
-	}
-
-	// Test caveat
-	correct_blessee := self.PublicID()
-
-	cav, err := security.NewPublicKeyCaveat(self.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.MethodCaveat("method")))
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	correct_blessed, err := Bless(self, self.PublicID(), "test", time.Second, nil, cav)
-	if err != nil {
-		t.Fatalf("Bless: failed with caveats: %v", err)
-	}
-
-	var blessEntry BlessingAuditEntry
-	blessEntry, err = ReadBlessAuditEntry(a.LastEntry)
-	if err != nil {
-		t.Fatal("ReadBlessAuditEntryFailed %v:", err)
-	}
-	if !reflect.DeepEqual(blessEntry.Blessee, correct_blessee) {
-		t.Errorf("blessee incorrect: expected %v got %v", correct_blessee, blessEntry.Blessee)
-	}
-	if !reflect.DeepEqual(blessEntry.Blessed, correct_blessed) {
-		t.Errorf("blessed incorrect: expected %v got %v", correct_blessed, blessEntry.Blessed)
-	}
-	if blessEntry.RevocationCaveat.ID() != cav.ID() {
-		t.Errorf("caveat ID incorrect: expected %s got %s", cav.ID(), blessEntry.RevocationCaveat.ID())
-	}
-
-	// Test no caveat
-	correct_blessed, err = Bless(self, self.PublicID(), "test", time.Second, nil, nil)
-	if err != nil {
-		t.Fatalf("Bless: failed with no caveats: %v", err)
-	}
-
-	blessEntry, err = ReadBlessAuditEntry(a.LastEntry)
-	if err != nil {
-		t.Fatal("ReadBlessAuditEntryFailed %v:", err)
-	}
-	if !reflect.DeepEqual(blessEntry.Blessee, correct_blessee) {
-		t.Errorf("blessee incorrect: expected %v got %v", correct_blessee, blessEntry.Blessee)
-	}
-	if !reflect.DeepEqual(blessEntry.Blessed, correct_blessed) {
-		t.Errorf("blessed incorrect: expected %v got %v", correct_blessed, blessEntry.Blessed)
-	}
-	if blessEntry.RevocationCaveat != nil {
-		t.Errorf("caveat ID incorrect: expected %s got %s", cav.ID(), blessEntry.RevocationCaveat.ID())
-	}
-}
-
-func newCaveat(c security.Caveat, err error) security.Caveat {
-	if err != nil {
-		panic(err)
-	}
-	return c
-}
diff --git a/services/identity/revocation/revocation_manager.go b/services/identity/revocation/revocation_manager.go
index f79e740..698e759 100644
--- a/services/identity/revocation/revocation_manager.go
+++ b/services/identity/revocation/revocation_manager.go
@@ -25,7 +25,7 @@
 
 // NewCaveat returns a security.ThirdPartyCaveat for which discharges will be
 // issued iff Revoke has not been called for the returned caveat.
-func (r *RevocationManager) NewCaveat(dischargerID security.PublicID, dischargerLocation string) (security.ThirdPartyCaveat, error) {
+func (r *RevocationManager) NewCaveat(discharger security.PublicKey, dischargerLocation string) (security.ThirdPartyCaveat, error) {
 	var revocation [16]byte
 	if _, err := rand.Read(revocation[:]); err != nil {
 		return nil, err
@@ -34,7 +34,7 @@
 	if err != nil {
 		return nil, err
 	}
-	cav, err := security.NewPublicKeyCaveat(dischargerID.PublicKey(), dischargerLocation, security.ThirdPartyRequirements{}, restriction)
+	cav, err := security.NewPublicKeyCaveat(discharger, dischargerLocation, security.ThirdPartyRequirements{}, restriction)
 	if err != nil {
 		return nil, err
 	}
diff --git a/services/identity/revocation/revoker_test.go b/services/identity/revocation/revoker_test.go
index 5a5c18d..7684c15 100644
--- a/services/identity/revocation/revoker_test.go
+++ b/services/identity/revocation/revoker_test.go
@@ -8,6 +8,7 @@
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
+	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
 
@@ -16,9 +17,9 @@
 	"veyron.io/veyron/veyron/services/security/discharger"
 )
 
-func revokerSetup(t *testing.T) (dischargerID security.PublicID, dischargerEndpoint string, revoker *RevocationManager, closeFunc func(), runtime veyron2.Runtime) {
+func revokerSetup(t *testing.T) (dischargerKey security.PublicKey, dischargerEndpoint string, revoker *RevocationManager, closeFunc func(), runtime veyron2.Runtime) {
 	var dir = filepath.Join(os.TempDir(), "revoker_test_dir")
-	r := rt.Init()
+	r := rt.Init(options.ForceNewSecurityModel{})
 	revokerService, err := NewRevocationManager(dir)
 	if err != nil {
 		t.Fatalf("NewRevocationManager failed: %v", err)
@@ -32,11 +33,11 @@
 	if err != nil {
 		t.Fatalf("dischargerServer.Listen failed: %v", err)
 	}
-	dischargerServiceStub := services.NewServerDischarger(discharger.NewDischarger(r.Identity()))
+	dischargerServiceStub := services.NewServerDischarger(discharger.NewDischarger())
 	if err := dischargerServer.Serve("", ipc.LeafDispatcher(dischargerServiceStub, nil)); err != nil {
 		t.Fatalf("dischargerServer.Serve revoker: %s", err)
 	}
-	return r.Identity().PublicID(),
+	return r.Principal().PublicKey(),
 		naming.JoinAddressName(dischargerEP.String(), ""),
 		revokerService,
 		func() {
@@ -47,7 +48,7 @@
 }
 
 func TestDischargeRevokeDischargeRevokeDischarge(t *testing.T) {
-	dcID, dc, revoker, closeFunc, r := revokerSetup(t)
+	dcKey, dc, revoker, closeFunc, r := revokerSetup(t)
 	defer closeFunc()
 
 	discharger, err := services.BindDischarger(dc)
@@ -55,7 +56,7 @@
 		t.Fatalf("error binding to server: ", err)
 	}
 
-	cav, err := revoker.NewCaveat(dcID, dc)
+	cav, err := revoker.NewCaveat(dcKey, dc)
 	if err != nil {
 		t.Fatalf("failed to create public key caveat: %s", err)
 	}
diff --git a/services/identity/util/b64vom.go b/services/identity/util/b64vom.go
index 1485cca..add1cb4 100644
--- a/services/identity/util/b64vom.go
+++ b/services/identity/util/b64vom.go
@@ -7,6 +7,10 @@
 	"veyron.io/veyron/veyron2/vom"
 )
 
+// TODO(ashankar): Once the old security model is ripped out, the only use of
+// these functions will be in the "principal" command-line tool. So, move these
+// helper functions there instead of having them here.
+
 // Bas64VomEncode returns the base64 encoding of the serialization of i with
 // vom.
 func Base64VomEncode(i interface{}) (string, error) {
diff --git a/services/identity/util/csrf.go b/services/identity/util/csrf.go
index 1efcae2..9fbe392 100644
--- a/services/identity/util/csrf.go
+++ b/services/identity/util/csrf.go
@@ -19,6 +19,8 @@
 	keyLength = 16
 )
 
+// CSRFCop implements utilities for generating and validating tokens for
+// cross-site-request-forgery prevention (also called XSRF).
 type CSRFCop struct {
 	key []byte
 }
diff --git a/services/identity/util/write.go b/services/identity/util/write.go
index 3983842..b948148 100644
--- a/services/identity/util/write.go
+++ b/services/identity/util/write.go
@@ -8,20 +8,6 @@
 	"veyron.io/veyron/veyron2/vlog"
 )
 
-// HTTPSend encodes obj using VOM and writes it out to the response in base64
-// encoding.
-func HTTPSend(w http.ResponseWriter, obj interface{}) {
-	b64, err := Base64VomEncode(obj)
-	if err != nil {
-		HTTPServerError(w, err)
-		return
-	}
-	w.Header().Set("Content-Type", "text/plain")
-	w.Header().Set("Access-Control-Allow-Origin", "*")
-	w.Write([]byte(b64))
-	vlog.Infof("Sending %T=%v", obj, obj)
-}
-
 // HTTPBadRequest sends an HTTP 400 error on 'w' and renders a pretty page.
 // If err is not nil, it also renders the string representation of err in the response page.
 func HTTPBadRequest(w http.ResponseWriter, req *http.Request, err error) {
diff --git a/services/identity/util/write_test.go b/services/identity/util/write_test.go
index 42e08e1..22d75e0 100644
--- a/services/identity/util/write_test.go
+++ b/services/identity/util/write_test.go
@@ -6,34 +6,6 @@
 	"testing"
 )
 
-func TestSend(t *testing.T) {
-	impl := impl{Content: "batman"}
-	var iface iface
-	iface = &impl
-
-	tests := []interface{}{
-		1,
-		"foo",
-		iface,
-		impl,
-	}
-	for _, test := range tests {
-		w := httptest.NewRecorder()
-		HTTPSend(w, test)
-		if got, want := w.Code, http.StatusOK; got != want {
-			t.Errorf("Got %d want %d (%T=%#v)", got, want, test, test)
-			continue
-		}
-		if got, want := w.HeaderMap.Get("Content-Type"), "text/plain"; got != want {
-			t.Errorf("Got %v want %v (%T=%v)", got, want, test, test)
-		}
-		var decoded interface{}
-		if err := Base64VomDecode(w.Body.String(), &decoded); err != nil {
-			t.Errorf("%v (%T=%v)", err, test, test)
-		}
-	}
-}
-
 func TestBadRequest(t *testing.T) {
 	w := httptest.NewRecorder()
 	HTTPBadRequest(w, newRequest(), nil)
diff --git a/services/security/discharger/discharger.go b/services/security/discharger/discharger.go
index b110866..f66bbdd 100644
--- a/services/security/discharger/discharger.go
+++ b/services/security/discharger/discharger.go
@@ -12,13 +12,11 @@
 
 // dischargerd issues discharges for all caveats present in the current
 // namespace with no additional caveats iff the caveat is valid.
-type dischargerd struct {
-	id security.PrivateID
-}
+type dischargerd struct{}
 
 // TODO(andreser,ataly): make it easier for third party public key caveats to specify the caveats on their discharges
 
-func (d dischargerd) Discharge(ctx ipc.ServerContext, caveatAny vdlutil.Any, _ security.DischargeImpetus) (vdlutil.Any, error) {
+func (dischargerd) Discharge(ctx ipc.ServerContext, caveatAny vdlutil.Any, _ security.DischargeImpetus) (vdlutil.Any, error) {
 	caveat, ok := caveatAny.(security.ThirdPartyCaveat)
 	if !ok {
 		return nil, fmt.Errorf("type %T does not implement security.ThirdPartyCaveat", caveatAny)
@@ -26,10 +24,15 @@
 	if err := caveat.Dischargeable(ctx); err != nil {
 		return nil, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", caveat, err)
 	}
-	return d.id.MintDischarge(caveat, ctx, time.Minute, nil)
+	expiry, err := security.ExpiryCaveat(time.Now().Add(time.Minute))
+	if err != nil {
+		return nil, fmt.Errorf("unable to create expiration caveat on the discharge: %v", err)
+	}
+	return ctx.LocalPrincipal().MintDischarge(caveat, expiry)
 }
 
-// NewDischarger returns a discharger service implementation that grants discharges using id.MintDischarge.
-func NewDischarger(id security.PrivateID) services.DischargerService {
-	return dischargerd{id}
+// NewDischarger returns a discharger service implementation that grants discharges using the MintDischarge
+// on the principal receiving the RPC.
+func NewDischarger() services.DischargerService {
+	return dischargerd{}
 }
diff --git a/tools/principal/test.sh b/tools/principal/test.sh
index 72eb84a..9d26963 100755
--- a/tools/principal/test.sh
+++ b/tools/principal/test.sh
@@ -57,9 +57,9 @@
   cat >want <<EOF
 Public key : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
 ---------------- BlessingStore ----------------
-Default blessings: alice(0 caveats)
+Default blessings: alice
 Peer pattern                   : Blessings
-...                            : alice(0 caveats)
+...                            : alice
 ---------------- BlessingRoots ----------------
 Public key                                      : Pattern
 XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX : [alice/...]
@@ -70,7 +70,7 @@
 
   dumpblessings alice.blessself >got || shell_test::fail "line ${LINENO}: dumpblessings failed"
   cat >want <<EOF
-Blessings          : alicereborn(0 caveats)
+Blessings          : alicereborn
 PublicKey          : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
 Certificate chains : 1
 Chain #0 (1 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
@@ -82,7 +82,7 @@
 
   dumpblessings bob.store.default >got || shell_test::fail "line ${LINENO}: dumpblessings failed"
   cat >want <<EOF
-Blessings          : alice/friend(1 caveats)
+Blessings          : alice/friend
 PublicKey          : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
 Certificate chains : 1
 Chain #0 (2 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
@@ -96,7 +96,7 @@
 
   dumpblessings bob.store.forpeer >got || shell_test::fail "line ${LINENO}: dumpblessings failed"
   cat >want <<EOF
-Blessings          : bob(0 caveats)#alice/friend(1 caveats)
+Blessings          : bob#alice/friend
 PublicKey          : XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
 Certificate chains : 2
 Chain #0 (1 certificates). Root certificate public key: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX