"veyron/security/wsprd": Update WSPR Controller

Updated the WSPR Controller (and other related objects) to
support the new security model. With this change WSPR
should be capable of handling both the old and new security
models. The next step is to change the JS code.

Change-Id: I4970930b6ebc4797e36f9a1fe2a85826be95f6f3
diff --git a/services/wsprd/app/app.go b/services/wsprd/app/app.go
index 54f49fd..f58254e 100644
--- a/services/wsprd/app/app.go
+++ b/services/wsprd/app/app.go
@@ -11,6 +11,7 @@
 	"sync"
 	"time"
 
+	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/context"
 	"veyron.io/veyron/veyron2/ipc"
@@ -26,6 +27,7 @@
 	"veyron.io/wspr/veyron/services/wsprd/ipc/server"
 	"veyron.io/wspr/veyron/services/wsprd/lib"
 	"veyron.io/wspr/veyron/services/wsprd/namespace"
+	"veyron.io/wspr/veyron/services/wsprd/principal"
 	"veyron.io/wspr/veyron/services/wsprd/signature"
 )
 
@@ -33,12 +35,18 @@
 const pkgPath = "veyron.io/veyron/veyron/services/wsprd/app"
 
 // Errors
-var marshallingError = verror2.Register(pkgPath+".marshallingError", verror2.NoRetry, "{1} {2} marshalling error {_}")
-var noResults = verror2.Register(pkgPath+".noResults", verror2.NoRetry, "{1} {2} no results from call {_}")
-var signatureError = verror2.Register(pkgPath+".signatureError", verror2.NoRetry, "{1} {2} signature error {_}")
-var badCaveatType = verror2.Register(pkgPath+".badCaveatType", verror2.NoRetry, "{1} {2} bad caveat type {_}")
-var unknownPublicID = verror2.Register(pkgPath+".unknownPublicID", verror2.NoRetry, "{1} {2} unknown public id {_}")
-var invalidPublicHandle = verror2.Register(pkgPath+".invalidPublicHandle", verror2.NoRetry, "{1} {2} invalid public handle {_}")
+var (
+	marshallingError       = verror2.Register(pkgPath+".marshallingError", verror2.NoRetry, "{1} {2} marshalling error {_}")
+	noResults              = verror2.Register(pkgPath+".noResults", verror2.NoRetry, "{1} {2} no results from call {_}")
+	signatureError         = verror2.Register(pkgPath+".signatureError", verror2.NoRetry, "{1} {2} signature error {_}")
+	badCaveatType          = verror2.Register(pkgPath+".badCaveatType", verror2.NoRetry, "{1} {2} bad caveat type {_}")
+	unknownBlessings       = verror2.Register(pkgPath+".unknownPublicID", verror2.NoRetry, "{1} {2} unknown public id {_}")
+	invalidBlessingsHandle = verror2.Register(pkgPath+".invalidBlessingsHandle", verror2.NoRetry, "{1} {2} invalid blessings handle {_}")
+
+	// TODO(ataly, ashankar, bjornick): Remove this field once the old security model is killed.
+	unknownPublicID     = verror2.Register(pkgPath+".unknownPublicID", verror2.NoRetry, "{1} {2} unknown public id {_}")
+	invalidPublicHandle = verror2.Register(pkgPath+".invalidPublicHandle", verror2.NoRetry, "{1} {2} invalid public handle {_}")
+)
 
 // TODO(bjornick,nlacasse): Remove the retryTimeout flag once we able
 // to pass it in from javascript. For now all RPCs have the same
@@ -84,7 +92,10 @@
 	Handle     int64
 	Caveats    []jsonCaveatValidator
 	DurationMs int64
-	Name       string
+
+	// TODO(ataly, ashankar, bjornick): Rename this field to Extension
+	// once the old security model is killed.
+	Name string
 }
 
 // Controller represents all the state of a Veyron Web App.  This is the struct
@@ -129,8 +140,12 @@
 
 	veyronProxyEP string
 
-	// Store for all the PublicIDs that javascript has a handle to.
-	idStore *identity.JSPublicIDHandles
+	// Store for all the Blessings that javascript has a handle to.
+	blessingsStore *principal.JSBlessingsHandles
+
+	// TODO(ataly, ashankar, bjornick): Remove the fields below once the old security model is killed.
+	idStore     *identity.JSPublicIDHandles
+	useOldModel bool
 }
 
 // NewController creates a new Controller.  writerCreator will be used to create a new flow for rpcs to
@@ -148,13 +163,23 @@
 	}
 
 	controller := &Controller{
-		rt:            r,
-		logger:        r.Logger(),
-		client:        client,
-		writerCreator: writerCreator,
-		listenSpec:    listenSpec,
-		idStore:       identity.NewJSPublicIDHandles(),
+		rt:             r,
+		logger:         r.Logger(),
+		client:         client,
+		writerCreator:  writerCreator,
+		listenSpec:     listenSpec,
+		idStore:        identity.NewJSPublicIDHandles(),
+		blessingsStore: principal.NewJSBlessingsHandles(),
+		useOldModel:    true,
 	}
+
+	for _, o := range opts {
+		if _, ok := o.(options.ForceNewSecurityModel); ok {
+			controller.useOldModel = false
+			break
+		}
+	}
+
 	controller.setup()
 	return controller, nil
 }
@@ -262,12 +287,12 @@
 	return c.rt
 }
 
-// AddIdentity adds the PublicID to the local id store and returns
+// AddBlessings adds the Blessings to the local blessings store and returns
 // the handle to it.  This function exists because JS only has
-// a handle to the PublicID to avoid shipping the blessing forest
+// a handle to the blessings to avoid shipping the certificate forest
 // to JS and back.
-func (c *Controller) AddIdentity(id security.PublicID) int64 {
-	return c.idStore.Add(id)
+func (c *Controller) AddBlessings(blessings security.Blessings) int64 {
+	return c.blessingsStore.Add(blessings)
 }
 
 // Cleanup cleans up any outstanding rpcs.
@@ -318,7 +343,6 @@
 		w.Error(verror2.Make(signatureError, ctx, tempMsg.Name, err))
 		return
 	}
-
 	methName := lib.UppercaseFirstCharacter(tempMsg.Method)
 	methSig, ok := sig.Methods[methName]
 	if !ok {
@@ -586,15 +610,15 @@
 	}
 }
 
-// HandleUnlinkJSIdentity removes an identity from the JS identity store.
-// data should be JSON encoded number
-func (c *Controller) HandleUnlinkJSIdentity(data string, w lib.ClientWriter) {
+// HandleUnlinkJSBlessings removes the specified blessings from the JS blessings
+// store.  'data' should be a JSON encoded number (representing the blessings handle).
+func (c *Controller) HandleUnlinkJSBlessings(data string, w lib.ClientWriter) {
 	var handle int64
 	if err := json.Unmarshal([]byte(data), &handle); err != nil {
 		w.Error(verror2.Convert(verror2.Internal, nil, err))
 		return
 	}
-	c.idStore.Remove(handle)
+	c.blessingsStore.Remove(handle)
 }
 
 // Convert the json wire format of a caveat into the right go object
@@ -615,6 +639,115 @@
 	}
 }
 
+func (c *Controller) getBlessingsHandle(handle int64) (*principal.BlessingsHandle, error) {
+	id := c.blessingsStore.Get(handle)
+	if id == nil {
+		return nil, verror2.Make(unknownBlessings, nil)
+	}
+	return principal.ConvertBlessingsToHandle(id, handle), nil
+}
+
+func (c *Controller) blessPublicKey(request blessingRequest) (*principal.BlessingsHandle, error) {
+	var blessee security.Blessings
+	if blessee := c.blessingsStore.Get(request.Handle); blessee == nil {
+		return nil, verror2.Make(invalidPublicHandle, nil)
+	}
+
+	expiryCav, err := security.ExpiryCaveat(time.Now().Add(time.Duration(request.DurationMs) * time.Millisecond))
+	if err != nil {
+		return nil, err
+	}
+	caveats := []security.Caveat{expiryCav}
+	for _, c := range request.Caveats {
+		cav, err := decodeCaveat(c)
+		if err != nil {
+			return nil, verror2.Convert(verror2.BadArg, nil, err)
+		}
+		caveats = append(caveats, cav)
+	}
+
+	// TODO(ataly, ashankar, bjornick): Currently the Bless operation is carried
+	// out using the Default blessing in this principal's blessings store. We
+	// should change this so that the JS blessing request can also specify the
+	// blessing to be used for the Bless operation.
+	blessings, err := c.rt.Principal().Bless(blessee.PublicKey(), c.rt.Principal().BlessingStore().Default(), request.Name, caveats[0], caveats[1:]...)
+	if err != nil {
+		return nil, err
+	}
+
+	return principal.ConvertBlessingsToHandle(blessings, c.blessingsStore.Add(blessings)), nil
+}
+
+// HandleBlessPublicKey handles a blessing request from JS.
+func (c *Controller) HandleBlessPublicKey(data string, w lib.ClientWriter) {
+	var request blessingRequest
+	if err := json.Unmarshal([]byte(data), &request); err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+
+	handle, err := c.blessPublicKey(request)
+	if err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+
+	// Send the id back.
+	if err := w.Send(lib.ResponseFinal, handle); err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+}
+
+func (c *Controller) HandleCreateBlessings(data string, w lib.ClientWriter) {
+	var extension string
+	if err := json.Unmarshal([]byte(data), &extension); err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+	p, err := vsecurity.NewPrincipal()
+	if err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+
+	blessings, err := p.BlessSelf(extension)
+	if err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+	handle := principal.ConvertBlessingsToHandle(blessings, c.blessingsStore.Add(blessings))
+	if err := w.Send(lib.ResponseFinal, handle); err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+}
+
+// TODO(ataly, ashankar, bjornick): Remove this method
+// once the old security model is killed.
+func (c *Controller) UseOldModel() bool {
+	return c.useOldModel
+}
+
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method
+// once the old security model is killed.
+func (c *Controller) AddIdentity(id security.PublicID) int64 {
+	return c.idStore.Add(id)
+}
+
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method
+// once the old security model is killed.
+func (c *Controller) HandleUnlinkJSIdentity(data string, w lib.ClientWriter) {
+	var handle int64
+	if err := json.Unmarshal([]byte(data), &handle); err != nil {
+		w.Error(verror2.Convert(verror2.Internal, nil, err))
+		return
+	}
+	c.idStore.Remove(handle)
+}
+
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method
+// once the old security model is killed.
 func (c *Controller) getPublicIDHandle(handle int64) (*identity.PublicIDHandle, error) {
 	id := c.idStore.Get(handle)
 	if id == nil {
@@ -623,6 +756,8 @@
 	return identity.ConvertPublicIDToHandle(id, handle), nil
 }
 
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method once
+// the old security model is killed.
 func (c *Controller) bless(request blessingRequest) (*identity.PublicIDHandle, error) {
 	var caveats []security.Caveat
 	for _, c := range request.Caveats {
@@ -649,7 +784,8 @@
 	return identity.ConvertPublicIDToHandle(blessed, c.idStore.Add(blessed)), nil
 }
 
-// HandleBlessing handles a blessing request from JS.
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method once
+// the old security model is killed.
 func (c *Controller) HandleBlessing(data string, w lib.ClientWriter) {
 	var request blessingRequest
 	if err := json.Unmarshal([]byte(data), &request); err != nil {
@@ -671,6 +807,8 @@
 	}
 }
 
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method once
+// the old security model is killed.
 func (c *Controller) HandleCreateIdentity(data string, w lib.ClientWriter) {
 	var name string
 	if err := json.Unmarshal([]byte(data), &name); err != nil {
diff --git a/services/wsprd/app/app_test.go b/services/wsprd/app/app_test.go
index 8964f76..3297124 100644
--- a/services/wsprd/app/app_test.go
+++ b/services/wsprd/app/app_test.go
@@ -7,6 +7,7 @@
 	"reflect"
 	"testing"
 
+	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/naming"
 	"veyron.io/veyron/veyron2/options"
@@ -21,12 +22,58 @@
 	"veyron.io/wspr/veyron/services/wsprd/lib/testwriter"
 	"veyron.io/wspr/veyron/services/wsprd/signature"
 
+	tsecurity "veyron.io/veyron/veyron/lib/testutil/security"
 	"veyron.io/veyron/veyron/profiles"
 	"veyron.io/veyron/veyron/runtimes/google/ipc/stream/proxy"
+	vsecurity "veyron.io/veyron/veyron/security"
 	mounttable "veyron.io/veyron/veyron/services/mounttable/lib"
 )
 
-var r = rt.Init()
+var (
+	testPrincipalBlessing = "test"
+	testPrincipal         = newPrincipal(testPrincipalBlessing)
+	r                     = rt.Init(options.ForceNewSecurityModel{})
+
+	// TODO(ataly, ashankar, bjornick): Remove the variable below once the old
+	// security model is killed.
+	emptyPublicIDHandleMsg = map[string]interface{}{
+		"Handle":    0.0,
+		"PublicKey": "",
+		"Names":     nil,
+	}
+)
+
+// newBlessedPrincipal returns a new principal that has a blessing from the
+// provided runtime's principal which is set on its BlessingStore such
+// that it is revealed to all clients and servers.
+func newBlessedPrincipal(r veyron2.Runtime) security.Principal {
+	p, err := vsecurity.NewPrincipal()
+	if err != nil {
+		panic(err)
+	}
+	b, err := r.Principal().Bless(p.PublicKey(), r.Principal().BlessingStore().Default(), "delegate", security.UnconstrainedUse())
+	if err != nil {
+		panic(err)
+	}
+	tsecurity.SetDefaultBlessings(p, b)
+	return p
+}
+
+// newPrincipal returns a new principal that has a self-blessing with
+// the provided extension 'selfBlessing' which is set on its BlessingStore
+// such that it is revealed to all clients and servers.
+func newPrincipal(selfBlessing string) security.Principal {
+	p, err := vsecurity.NewPrincipal()
+	if err != nil {
+		panic(err)
+	}
+	b, err := p.BlessSelf(selfBlessing)
+	if err != nil {
+		panic(err)
+	}
+	tsecurity.SetDefaultBlessings(p, b)
+	return p
+}
 
 type simpleAdder struct{}
 
@@ -156,18 +203,18 @@
 	defer s.Stop()
 	spec := *profiles.LocalListenSpec
 	spec.Proxy = "mockVeyronProxyEP"
-	controller, err := NewController(nil, &spec)
+	controller, err := NewController(nil, &spec, options.ForceNewSecurityModel{}, options.RuntimePrincipal{newBlessedPrincipal(r)})
 
 	if err != nil {
-		t.Errorf("Failed to create controller: %v", err)
+		t.Fatalf("Failed to create controller: %v", err)
 	}
 	jsSig, err := controller.getSignature(r.NewContext(), "/"+endpoint.String())
 	if err != nil {
-		t.Errorf("Failed to get signature: %v", err)
+		t.Fatalf("Failed to get signature: %v", err)
 	}
 
 	if !reflect.DeepEqual(jsSig, adderServiceSignature) {
-		t.Errorf("Unexpected signature, got :%v, expected: %v", jsSig, adderServiceSignature)
+		t.Fatalf("Unexpected signature, got :%v, expected: %v", jsSig, adderServiceSignature)
 	}
 }
 
@@ -189,17 +236,15 @@
 		return
 	}
 	defer s.Stop()
-
 	spec := *profiles.LocalListenSpec
 	spec.Proxy = "mockVeyronProxyEP"
-	controller, err := NewController(nil, &spec)
+	controller, err := NewController(nil, &spec, options.ForceNewSecurityModel{}, options.RuntimePrincipal{newBlessedPrincipal(r)})
 
 	if err != nil {
 		t.Errorf("unable to create controller: %v", err)
 		t.Fail()
 		return
 	}
-
 	writer := testwriter.Writer{}
 	var stream *outstandingStream
 	if len(test.streamingInputs) > 0 {
@@ -313,7 +358,7 @@
 	}
 	spec := *profiles.LocalListenSpec
 	spec.Proxy = "/" + proxyEndpoint
-	controller, err := NewController(writerCreator, &spec, options.NamespaceRoots{"/" + endpoint.String()})
+	controller, err := NewController(writerCreator, &spec, options.NamespaceRoots{"/" + endpoint.String()}, options.ForceNewSecurityModel{}, options.RuntimePrincipal{testPrincipal})
 
 	if err != nil {
 		return nil, err
@@ -553,13 +598,8 @@
 	}
 	rt.controller.HandleLookupResponse(2, string(bytes))
 
-	id := rt.controller.rt.Identity().PublicID()
-	typedNames := rt.controller.rt.Identity().PublicID().Names()
-	names := []interface{}{}
-	for _, n := range typedNames {
-		names = append(names, n)
-	}
-	k := id.PublicKey()
+	blessings := rt.controller.rt.Principal().BlessingStore().Default()
+	k := blessings.PublicKey()
 	keyBytes, err := k.MarshalBinary()
 
 	if err != nil {
@@ -569,9 +609,9 @@
 
 	publicKey := base64.StdEncoding.EncodeToString(keyBytes)
 
-	// The expectedHandle for the javascript ID.  Since we don't always call the authorizer
+	// The expectedBlessingsHandle for the javascript Blessings.  Since we don't always call the authorizer
 	// this handle could be different by the time we make the start rpc call.
-	expectedIDHandle := 1.0
+	expectedBlessingsHandle := 1.0
 	expectedFlowCount := int64(4)
 	if test.hasAuthorizer {
 		// If an authorizer exists, it gets called twice.  The first time to see if the
@@ -587,18 +627,20 @@
 					"name":   "adder",
 					"suffix": "adder",
 					"label":  8.0, // This is a read label.
-					"localId": map[string]interface{}{
+					"localBlessings": map[string]interface{}{
 						"Handle":    1.0,
-						"Names":     names,
 						"PublicKey": publicKey,
 					},
-					"remoteId": map[string]interface{}{
+					"localBlessingStrings": []interface{}{testPrincipalBlessing},
+					"remoteBlessings": map[string]interface{}{
 						"Handle":    2.0,
-						"Names":     names,
 						"PublicKey": publicKey,
 					},
-					"localEndpoint":  endpoint.String(),
-					"remoteEndpoint": "remoteEndpoint",
+					"remoteBlessingStrings": []interface{}{testPrincipalBlessing},
+					"localEndpoint":         endpoint.String(),
+					"remoteEndpoint":        "remoteEndpoint",
+					"localId":               emptyPublicIDHandleMsg,
+					"remoteId":              emptyPublicIDHandleMsg,
 				},
 			},
 		})
@@ -645,18 +687,20 @@
 					"name":   "adder",
 					"suffix": "adder",
 					"label":  16.0,
-					"localId": map[string]interface{}{
+					"localBlessings": map[string]interface{}{
 						"Handle":    3.0,
-						"Names":     names,
 						"PublicKey": publicKey,
 					},
-					"remoteId": map[string]interface{}{
+					"localBlessingStrings": []interface{}{testPrincipalBlessing},
+					"remoteBlessings": map[string]interface{}{
 						"Handle":    4.0,
-						"Names":     names,
 						"PublicKey": publicKey,
 					},
-					"localEndpoint":  endpoint.String(),
-					"remoteEndpoint": "remoteEndpoint",
+					"remoteBlessingStrings": []interface{}{testPrincipalBlessing},
+					"localEndpoint":         endpoint.String(),
+					"remoteEndpoint":        "remoteEndpoint",
+					"localId":               emptyPublicIDHandleMsg,
+					"remoteId":              emptyPublicIDHandleMsg,
 				},
 			},
 		})
@@ -675,7 +719,7 @@
 		}
 		rt.controller.HandleAuthResponse(6, string(bytes))
 
-		expectedIDHandle += 4
+		expectedBlessingsHandle += 4
 		expectedFlowCount += 4
 	}
 
@@ -690,11 +734,11 @@
 			"Context": map[string]interface{}{
 				"Name":   "adder",
 				"Suffix": "adder",
-				"RemoteID": map[string]interface{}{
-					"Handle":    expectedIDHandle,
-					"Names":     names,
+				"RemoteBlessings": map[string]interface{}{
+					"Handle":    expectedBlessingsHandle,
 					"PublicKey": publicKey,
 				},
+				"RemoteID": emptyPublicIDHandleMsg,
 			},
 		},
 	})
diff --git a/services/wsprd/ipc/server/server.go b/services/wsprd/ipc/server/server.go
index eb31feb..aca1eee 100644
--- a/services/wsprd/ipc/server/server.go
+++ b/services/wsprd/ipc/server/server.go
@@ -9,6 +9,7 @@
 	vsecurity "veyron.io/veyron/veyron/security"
 	"veyron.io/wspr/veyron/services/wsprd/identity"
 	"veyron.io/wspr/veyron/services/wsprd/lib"
+	"veyron.io/wspr/veyron/services/wsprd/principal"
 	"veyron.io/wspr/veyron/services/wsprd/signature"
 
 	"veyron.io/veyron/veyron2"
@@ -34,8 +35,11 @@
 
 // call context for a serverRPCRequest
 type serverRPCRequestContext struct {
-	Suffix   string
-	Name     string
+	Suffix          string
+	Name            string
+	RemoteBlessings principal.BlessingsHandle
+
+	// TODO(ataly, ashankar, bjornick): Remove this field once the old security model is killed.
 	RemoteID identity.PublicIDHandle
 }
 
@@ -52,6 +56,10 @@
 }
 
 type HandleStore interface {
+	// Adds blessings to the store and returns handle to the blessings
+	AddBlessings(blessings security.Blessings) int64
+
+	// TODO(ataly, ashankar, bjornick): Remove this method once the old security model is killed.
 	// Adds an identity to the store and returns handle to the identity
 	AddIdentity(identity security.PublicID) int64
 }
@@ -63,6 +71,9 @@
 	GetLogger() vlog.Logger
 
 	RT() veyron2.Runtime
+
+	// TODO(ataly, ashankar, bjornick): Remove this once the old security model is killed.
+	UseOldModel() bool
 }
 
 type authReply struct {
@@ -70,14 +81,21 @@
 }
 
 type context struct {
-	Method         string                  `json:"method"`
-	Name           string                  `json:"name"`
-	Suffix         string                  `json:"suffix"`
-	Label          security.Label          `json:"label"`
-	LocalID        identity.PublicIDHandle `json:"localId"`
-	RemoteID       identity.PublicIDHandle `json:"remoteId"`
-	LocalEndpoint  string                  `json:"localEndpoint"`
-	RemoteEndpoint string                  `json:"remoteEndpoint"`
+	Method                string                    `json:"method"`
+	Name                  string                    `json:"name"`
+	Suffix                string                    `json:"suffix"`
+	Label                 security.Label            `json:"label"`
+	LocalBlessings        principal.BlessingsHandle `json:"localBlessings"`
+	LocalBlessingStrings  []string                  `json:"localBlessingStrings"`
+	RemoteBlessings       principal.BlessingsHandle `json:"remoteBlessings"`
+	RemoteBlessingStrings []string                  `json:"remoteBlessingStrings"`
+	LocalEndpoint         string                    `json:"localEndpoint"`
+	RemoteEndpoint        string                    `json:"remoteEndpoint"`
+
+	// TODO(ataly, ashankar, bjornick): Remove the fields below once the old security
+	// model is killed.
+	LocalID  identity.PublicIDHandle `json:"localId"`
+	RemoteID identity.PublicIDHandle `json:"remoteId"`
 }
 
 type authRequest struct {
@@ -139,11 +157,14 @@
 		s.mu.Lock()
 		s.outstandingServerRequests[flow.ID] = replyChan
 		s.mu.Unlock()
-		remoteID := call.RemoteID()
 		context := serverRPCRequestContext{
-			Suffix:   call.Suffix(),
-			Name:     call.Name(),
-			RemoteID: s.convertPublicIDToHandle(remoteID),
+			Suffix: call.Suffix(),
+			Name:   call.Name(),
+		}
+		if s.helper.UseOldModel() {
+			context.RemoteID = s.convertPublicIDToHandle(call.RemoteID())
+		} else {
+			context.RemoteBlessings = s.convertBlessingsToHandle(call.RemoteBlessings())
 		}
 		// Send a invocation request to JavaScript
 		message := serverRPCRequest{
@@ -187,8 +208,8 @@
 	}
 }
 
-func (s *Server) convertPublicIDToHandle(id security.PublicID) identity.PublicIDHandle {
-	return *identity.ConvertPublicIDToHandle(id, s.helper.AddIdentity(id))
+func (s *Server) convertBlessingsToHandle(blessings security.Blessings) principal.BlessingsHandle {
+	return *principal.ConvertBlessingsToHandle(blessings, s.helper.AddBlessings(blessings))
 }
 
 type remoteAuthFunc func(security.Context) error
@@ -208,12 +229,19 @@
 				Name:           ctx.Name(),
 				Suffix:         ctx.Suffix(),
 				Label:          ctx.Label(),
-				LocalID:        s.convertPublicIDToHandle(ctx.LocalID()),
-				RemoteID:       s.convertPublicIDToHandle(ctx.RemoteID()),
 				LocalEndpoint:  ctx.LocalEndpoint().String(),
 				RemoteEndpoint: ctx.RemoteEndpoint().String(),
 			},
 		}
+		if s.helper.UseOldModel() {
+			message.Context.LocalID = s.convertPublicIDToHandle(ctx.LocalID())
+			message.Context.RemoteID = s.convertPublicIDToHandle(ctx.RemoteID())
+		} else {
+			message.Context.LocalBlessings = s.convertBlessingsToHandle(ctx.LocalBlessings())
+			message.Context.LocalBlessingStrings = ctx.LocalBlessings().ForContext(ctx)
+			message.Context.RemoteBlessings = s.convertBlessingsToHandle(ctx.RemoteBlessings())
+			message.Context.RemoteBlessingStrings = ctx.RemoteBlessings().ForContext(ctx)
+		}
 		s.helper.GetLogger().VI(0).Infof("Sending out auth request for %v, %v", flow.ID, message)
 
 		if err := flow.Writer.Send(lib.ResponseAuthRequest, message); err != nil {
@@ -354,3 +382,9 @@
 	s.outstandingServerRequests = make(map[int64]chan *serverRPCReply)
 	s.server.Stop()
 }
+
+// DEPRECATED: TODO(ataly, ashankar, bjornick): Remove this method once
+// the old security model is killed.
+func (s *Server) convertPublicIDToHandle(id security.PublicID) identity.PublicIDHandle {
+	return *identity.ConvertPublicIDToHandle(id, s.helper.AddIdentity(id))
+}
diff --git a/services/wsprd/lib/testwriter/writer.go b/services/wsprd/lib/testwriter/writer.go
index 21572cf..01f22ff 100644
--- a/services/wsprd/lib/testwriter/writer.go
+++ b/services/wsprd/lib/testwriter/writer.go
@@ -86,12 +86,11 @@
 	return nil
 }
 
-func CheckResponses(w *Writer, expectedStream []Response, err error, t TestHarness) {
-	if !reflect.DeepEqual(expectedStream, w.Stream) {
-		t.Errorf("streams don't match: expected %v, got %v", expectedStream, w.Stream)
+func CheckResponses(w *Writer, wantStream []Response, wantErr error, t TestHarness) {
+	if got, want := w.Stream, wantStream; !reflect.DeepEqual(got, want) {
+		t.Errorf("streams don't match: got %v, want %v", got, want)
 	}
-
-	if !verror2.Equal(err, w.err) {
-		t.Errorf("unexpected error, got: %#v, expected: %#v", w.err, err)
+	if got, want := w.err, wantErr; !verror2.Equal(got, want) {
+		t.Errorf("unexpected error, got: %#v, expected: %#v", got, want)
 	}
 }
diff --git a/services/wsprd/principal/blessings.go b/services/wsprd/principal/blessings.go
new file mode 100644
index 0000000..444cf67
--- /dev/null
+++ b/services/wsprd/principal/blessings.go
@@ -0,0 +1,22 @@
+package principal
+
+import (
+	"encoding/base64"
+	"veyron.io/veyron/veyron2/security"
+)
+
+type BlessingsHandle struct {
+	Handle    int64
+	PublicKey string
+}
+
+func ConvertBlessingsToHandle(blessings security.Blessings, handle int64) *BlessingsHandle {
+	bytes, err := blessings.PublicKey().MarshalBinary()
+	if err != nil {
+		panic(err)
+	}
+	return &BlessingsHandle{
+		Handle:    handle,
+		PublicKey: base64.StdEncoding.EncodeToString(bytes),
+	}
+}
diff --git a/services/wsprd/wspr/pipe.go b/services/wsprd/wspr/pipe.go
index 9841482..feffa05 100644
--- a/services/wsprd/wspr/pipe.go
+++ b/services/wsprd/wspr/pipe.go
@@ -50,6 +50,8 @@
 	// A request to associate an identity with an origin
 	websocketAssocIdentity = 7
 
+	// TODO(ataly, ashankar, bjornick): Get rid of the constants below
+	// once the old security model is killed.
 	// A request to bless an identity
 	websocketBlessIdentity = 8
 
@@ -68,6 +70,16 @@
 
 	// A request to run a namespace client method
 	websocketNamespaceRequest = 13
+
+	// A request to bless a public key.
+	websocketBlessPublicKey = 14
+
+	// A request to unlink blessings.  This request means that
+	// we can remove the given handle from the handle store.
+	websocketUnlinkBlessings = 15
+
+	// A request to create a new random blessings
+	websocketCreateBlessings = 16
 )
 
 type websocketMessage struct {
@@ -124,8 +136,33 @@
 		return nil
 	}
 
-	id, err := wspr.idManager.Identity(origin)
+	// Shortcut for old security model.
+	if wspr.useOldModel {
+		return newPipeOldModel(pipe, origin, w, req, wspr, creator)
+	}
 
+	p, err := wspr.principalManager.Principal(origin)
+	if err != nil {
+		p = wspr.rt.Principal()
+		wspr.rt.Logger().Errorf("no principal associated with origin %s: %v", origin, err)
+		// TODO(bjornick): Send an error to the client when all of the principal stuff is set up.
+	}
+
+	pipe.controller, err = app.NewController(creator, &wspr.listenSpec, options.RuntimePrincipal{p})
+	if err != nil {
+		wspr.rt.Logger().Errorf("Could not create controller: %v", err)
+		http.Error(w, fmt.Sprintf("Failed to create controller: %v", err), http.StatusInternalServerError)
+		return nil
+	}
+
+	pipe.start(w, req)
+	return pipe
+}
+
+// TODO(ataly, ashankar, bjornick): Get rid of this method once the old security model
+// is killed.
+func newPipeOldModel(pipe *pipe, origin string, w http.ResponseWriter, req *http.Request, wspr *WSPR, creator func(id int64) lib.ClientWriter) *pipe {
+	id, err := wspr.idManager.Identity(origin)
 	if err != nil {
 		id = wspr.rt.Identity()
 		wspr.rt.Logger().Errorf("no identity associated with origin %s: %v", origin, err)
@@ -133,7 +170,6 @@
 	}
 
 	pipe.controller, err = app.NewController(creator, &wspr.listenSpec, options.RuntimeID{id})
-
 	if err != nil {
 		wspr.rt.Logger().Errorf("Could not create controller: %v", err)
 		http.Error(w, fmt.Sprintf("Failed to create controller: %v", err), http.StatusInternalServerError)
@@ -287,6 +323,12 @@
 			go p.controller.HandleCreateIdentity(msg.Data, ww)
 		case websocketUnlinkIdentity:
 			go p.controller.HandleUnlinkJSIdentity(msg.Data, ww)
+		case websocketBlessPublicKey:
+			go p.controller.HandleBlessPublicKey(msg.Data, ww)
+		case websocketCreateBlessings:
+			go p.controller.HandleCreateBlessings(msg.Data, ww)
+		case websocketUnlinkBlessings:
+			go p.controller.HandleUnlinkJSBlessings(msg.Data, ww)
 		case websocketAuthResponse:
 			go p.controller.HandleAuthResponse(msg.Id, msg.Data)
 		case websocketNamespaceRequest:
diff --git a/services/wsprd/wspr/wspr.go b/services/wsprd/wspr/wspr.go
index 0236fa6..3385927 100644
--- a/services/wsprd/wspr/wspr.go
+++ b/services/wsprd/wspr/wspr.go
@@ -170,7 +170,6 @@
 		if wspr.idManager, err = identity.NewIDManager(newrt, &identity.InMemorySerializer{}); err != nil {
 			log.Fatalf("identity.NewIDManager failed: %s", err)
 		}
-		return wspr
 	}
 
 	// TODO(nlacasse, bjornick) use a serializer that can actually persist.