Browspr Authentication support.

When a veyron web app asks for authentication, it sends an 'auth'
message to the extension, which creates and associates an account on
WSPR.

Previously, the extension was communicating with WSPR over HTTP.

Now, the extension must communicate with Browspr over postMessage.

This CL:
* Sets up a channel for browspr RPCs.
* Uses channel RPCs for "start", "cleanup", "createAccount" and
  "associateAccount" messages.
* Moves the account test into browspr, and uses channel RPCs rather than
  HTTP.
* Adds a "RootAccount" to the account manager, and methods for the
  extension to ask if the root account has been set.
* Adds principal.TrustIdentdBlessingRoot, which tells browspr to trust
  the public key and blessing names from the identdurl and add them to
  its trusted roots.  This must be done before making a veyron rpc to
  the identity server.
* Moves fileSerializer into its own file.

MultiPart: 2/2

Change-Id: I1e166ce1fc5b75f0b7b011c0ee3388ac42456c3a
diff --git a/services/wsprd/browspr/browspr.go b/services/wsprd/browspr/browspr.go
index 3636c9b..4dfbf6a 100644
--- a/services/wsprd/browspr/browspr.go
+++ b/services/wsprd/browspr/browspr.go
@@ -2,12 +2,13 @@
 package browspr
 
 import (
-	"net"
+	"fmt"
 	"sync"
-	"time"
 
 	"veyron.io/veyron/veyron2"
 	"veyron.io/veyron/veyron2/ipc"
+	"veyron.io/veyron/veyron2/vdl"
+	"veyron.io/veyron/veyron2/vdl/valconv"
 	"veyron.io/veyron/veyron2/vlog"
 	"veyron.io/wspr/veyron/services/wsprd/account"
 	"veyron.io/wspr/veyron/services/wsprd/lib"
@@ -19,16 +20,17 @@
 	namespace.EpFormatter = lib.EndpointsToWs
 }
 
-// Browspr is an intermediary between our javascript code and the veyron network that allows our javascript library to use veyron.
+// Browspr is an intermediary between our javascript code and the veyron
+// network that allows our javascript library to use veyron.
 type Browspr struct {
-	rt             veyron2.Runtime
-	profileFactory func() veyron2.Profile
-	listenSpec     ipc.ListenSpec
-	identdEP       string
-	namespaceRoots []string
-	logger         vlog.Logger
-	accountManager *account.AccountManager
-	postMessage    func(instanceId int32, ty, msg string)
+	rt               veyron2.Runtime
+	profileFactory   func() veyron2.Profile
+	listenSpec       *ipc.ListenSpec
+	namespaceRoots   []string
+	logger           vlog.Logger
+	accountManager   *account.AccountManager
+	postMessage      func(instanceId int32, ty, msg string)
+	principalManager *principal.PrincipalManager
 
 	// Locks activeInstances
 	mu              sync.Mutex
@@ -36,18 +38,22 @@
 }
 
 // Create a new Browspr instance.
-func NewBrowspr(runtime veyron2.Runtime, postMessage func(instanceId int32, ty, msg string), profileFactory func() veyron2.Profile, listenSpec ipc.ListenSpec, identdEP string, wsNamespaceRoots []string) *Browspr {
+func NewBrowspr(runtime veyron2.Runtime,
+	postMessage func(instanceId int32, ty, msg string),
+	profileFactory func() veyron2.Profile,
+	listenSpec *ipc.ListenSpec,
+	identd string,
+	wsNamespaceRoots []string) *Browspr {
 	if listenSpec.Proxy == "" {
 		vlog.Fatalf("a veyron proxy must be set")
 	}
-	if identdEP == "" {
+	if identd == "" {
 		vlog.Fatalf("an identd server must be set")
 	}
 
 	browspr := &Browspr{
 		profileFactory:  profileFactory,
 		listenSpec:      listenSpec,
-		identdEP:        identdEP,
 		namespaceRoots:  wsNamespaceRoots,
 		postMessage:     postMessage,
 		rt:              runtime,
@@ -56,12 +62,12 @@
 	}
 
 	// TODO(nlacasse, bjornick) use a serializer that can actually persist.
-	principalManager, err := principal.NewPrincipalManager(runtime.Principal(), &principal.InMemorySerializer{})
-	if err != nil {
+	var err error
+	if browspr.principalManager, err = principal.NewPrincipalManager(runtime.Principal(), &principal.InMemorySerializer{}); err != nil {
 		vlog.Fatalf("principal.NewPrincipalManager failed: %s", err)
 	}
 
-	browspr.accountManager = account.NewAccountManager(runtime, identdEP, principalManager)
+	browspr.accountManager = account.NewAccountManager(runtime, identd, browspr.principalManager)
 
 	return browspr
 }
@@ -70,69 +76,86 @@
 	// TODO(ataly, bprosnitz): Get rid of this method if possible.
 }
 
-// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted connections.
-// It's used by ListenAndServe and ListenAndServeTLS so dead TCP connections
-// (e.g. closing laptop mid-download) eventually go away.
-// Copied from http/server.go, since it's not exported.
-type tcpKeepAliveListener struct {
-	*net.TCPListener
-}
-
-func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
-	tc, err := ln.AcceptTCP()
-	if err != nil {
-		return
-	}
-	tc.SetKeepAlive(true)
-	tc.SetKeepAlivePeriod(3 * time.Minute)
-	return tc, nil
-}
-
 // HandleMessage handles most messages from javascript and forwards them to a
 // Controller.
-func (b *Browspr) HandleMessage(instanceId int32, msg string) error {
+func (b *Browspr) HandleMessage(instanceId int32, origin, msg string) error {
 	b.mu.Lock()
 	defer b.mu.Unlock()
 	instance, ok := b.activeInstances[instanceId]
 	if !ok {
-		instance = newPipe(b, instanceId)
+		instance = newPipe(b, instanceId, origin)
+		if instance == nil {
+			return fmt.Errorf("Could not create pipe for origin %v: origin")
+		}
 		b.activeInstances[instanceId] = instance
 	}
 
 	return instance.handleMessage(msg)
 }
 
-// HandleCleanupMessage cleans up the specified instance state. (For instance,
+type cleanupMessage struct {
+	InstanceId int32
+}
+
+// HandleCleanupRpc cleans up the specified instance state. (For instance,
 // when a browser tab is closed)
-func (b *Browspr) HandleCleanupMessage(instanceId int32) {
+func (b *Browspr) HandleCleanupRpc(val *vdl.Value) (interface{}, error) {
+	var msg cleanupMessage
+	if err := valconv.Convert(&msg, val); err != nil {
+		return nil, err
+	}
+
 	b.mu.Lock()
 	defer b.mu.Unlock()
-	if instance, ok := b.activeInstances[instanceId]; ok {
-		delete(b.activeInstances, instanceId)
+	if instance, ok := b.activeInstances[msg.InstanceId]; ok {
+		delete(b.activeInstances, msg.InstanceId)
 		// NOTE(nlacasse): Calling cleanup() on the main thread locks
 		// browspr, so we must do it in a goroutine.
 		// TODO(nlacasse): Consider running all the message handlers in
 		// goroutines.
 		go instance.cleanup()
 	}
+	return nil, nil
 }
 
-// HandleCreateAccountMessage creates an account for the specified instance.
-func (b *Browspr) HandleCreateAccountMessage(instanceId int32, accessToken string) error {
-	account, err := b.accountManager.CreateAccount(accessToken)
-	if err != nil {
-		b.postMessage(instanceId, "createAccountFailedResponse", err.Error())
-		return err
+type createAccountMessage struct {
+	Token string
+}
+
+// Handler for creating an account in the principal manager.
+// A valid OAuth2 access token must be supplied in the request body,
+// which is exchanged for blessings from the veyron blessing server.
+// An account based on the blessings is then added to WSPR's principal
+// manager, and the set of blessing strings are returned to the client.
+func (b *Browspr) HandleAuthCreateAccountRpc(val *vdl.Value) (interface{}, error) {
+	var msg createAccountMessage
+	if err := valconv.Convert(&msg, val); err != nil {
+		return nil, err
 	}
 
-	b.postMessage(instanceId, "createAccountResponse", account)
-	return nil
+	account, err := b.accountManager.CreateAccount(msg.Token)
+	if err != nil {
+		return nil, err
+	}
+
+	return account, nil
+}
+
+type associateAccountMessage struct {
+	Account string
+	Origin  string
+	Caveats []account.Caveat
 }
 
 // HandleAssociateAccountMessage associates an account with the specified origin.
-func (b *Browspr) HandleAssociateAccountMessage(origin, account string, cavs []account.Caveat) error {
-	if err := b.accountManager.AssociateAccount(origin, account, cavs); err != nil {
-		return err
+func (b *Browspr) HandleAuthAssociateAccountRpc(val *vdl.Value) (interface{}, error) {
+	var msg associateAccountMessage
+	if err := valconv.Convert(&msg, val); err != nil {
+		return nil, err
 	}
-	return nil
+
+	if err := b.accountManager.AssociateAccount(msg.Origin, msg.Account, msg.Caveats); err != nil {
+		return nil, err
+	}
+	return nil, nil
 }
diff --git a/services/wsprd/browspr/browspr_account_test.go b/services/wsprd/browspr/browspr_account_test.go
index 3c61191..7eefaf1 100644
--- a/services/wsprd/browspr/browspr_account_test.go
+++ b/services/wsprd/browspr/browspr_account_test.go
@@ -8,15 +8,14 @@
 	"veyron.io/veyron/veyron2/ipc"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
-	"veyron.io/veyron/veyron2/vlog"
+	"veyron.io/veyron/veyron2/vdl"
+	"veyron.io/veyron/veyron2/vdl/valconv"
 
 	"veyron.io/veyron/veyron/profiles"
-	"veyron.io/wspr/veyron/services/wsprd/lib"
 )
 
 const topLevelName = "mock-blesser"
 
-// BEGIN MOCK BLESSER SERVICE
 type mockBlesserService struct {
 	p     security.Principal
 	count int
@@ -30,97 +29,77 @@
 }
 
 func (m *mockBlesserService) BlessUsingAccessToken(c context.T, accessToken string, co ...ipc.CallOpt) (security.WireBlessings, string, error) {
+	var empty security.WireBlessings
 	m.count++
 	name := fmt.Sprintf("%s%s%d", topLevelName, security.ChainSeparator, m.count)
 	blessing, err := m.p.BlessSelf(name)
 	if err != nil {
-		return security.WireBlessings{}, "", err
+		return empty, "", err
 	}
 	return security.MarshalBlessings(blessing), name, nil
 }
 
-// END MOCK BLESSER SERVICE
-
-func setup(t *testing.T, postMessageHandler func(instanceId int32, ty string, msg string)) (*Browspr, func()) {
+func setup(t *testing.T) (*Browspr, func()) {
 	spec := profiles.LocalListenSpec
 	spec.Proxy = "/mock/proxy"
-	runtime, err := rt.New()
+	r, err := rt.New()
 	if err != nil {
-		vlog.Fatalf("rt.New failed: %s", err)
+		t.Fatal(err)
 	}
-	defer runtime.Cleanup()
-	wsNamespaceRoots, err := lib.EndpointsToWs(runtime, nil)
-	if err != nil {
-		vlog.Fatal(err)
-	}
-	runtime.Namespace().SetRoots(wsNamespaceRoots...)
-	browspr := NewBrowspr(runtime, postMessageHandler, nil, spec, "/mock/identd", wsNamespaceRoots)
+	mockPostMessage := func(_ int32, _, _ string) {}
+	browspr := NewBrowspr(r, mockPostMessage, nil, &spec, "/mock:1234/identd", nil)
 	browspr.accountManager.SetMockBlesser(newMockBlesserService(browspr.rt.Principal()))
+
 	return browspr, func() {
 		browspr.Shutdown()
+		r.Cleanup()
 	}
 }
 
 func TestHandleCreateAccount(t *testing.T) {
-	lastInstanceId := int32(0)
-	lastType := ""
-	lastResponse := ""
-	postMessageHandler := func(instanceId int32, ty string, response string) {
-		lastInstanceId = instanceId
-		lastType = ty
-		lastResponse = response
-	}
-
-	browspr, teardown := setup(t, postMessageHandler)
+	browspr, teardown := setup(t)
 	defer teardown()
 
-	instanceId := int32(11) // The id of the tab / background script.
-	if err := browspr.HandleCreateAccountMessage(instanceId, "mock-access-token-1"); err != nil {
-		t.Fatalf("Failed to create account: %v", err)
+	// Add one account
+	message1, err := valueOf(createAccountMessage{
+		Token: "mock-access-token-1",
+	})
+	if err != nil {
+		t.Fatal(err)
 	}
-	if lastInstanceId != instanceId {
-		t.Errorf("Received incorrect instance id on first account creation: %d", lastInstanceId)
-	}
-	if lastType != "createAccountResponse" {
-		t.Errorf("Unexpected response type: %s", lastType)
-	}
-	if lastResponse != "mock-blesser/1" {
-		t.Errorf("Unexpected response: %s", lastResponse)
+	account1, err := browspr.HandleAuthCreateAccountRpc(message1)
+	if err != nil {
+		t.Fatalf("browspr.HandleAuthCreateAccountRpc(%v) failed: %v", message1, err)
 	}
 
 	// Verify that principalManager has the new account
-	expectedAccount := fmt.Sprintf("%s%s%d", topLevelName, security.ChainSeparator, 1)
-	if b, err := browspr.accountManager.PrincipalManager().BlessingsForAccount(expectedAccount); err != nil || b == nil {
-		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", expectedAccount, b, err)
+	if b, err := browspr.principalManager.BlessingsForAccount(account1.(string)); err != nil || b == nil {
+		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", account1, b, err)
 	}
 
-	if err := browspr.HandleCreateAccountMessage(instanceId, "mock-access-token-2"); err != nil {
-		t.Fatalf("Failed to create account: %v", err)
+	// Add another account
+	message2, err := valueOf(createAccountMessage{
+		Token: "mock-access-token-2",
+	})
+	if err != nil {
+		t.Fatal(err)
 	}
-	if lastInstanceId != instanceId {
-		t.Errorf("Received incorrect instance id on second account creation: %d", lastInstanceId)
-	}
-	if lastType != "createAccountResponse" {
-		t.Errorf("Unexpected response type: %s", lastType)
-	}
-	if lastResponse != "mock-blesser/2" {
-		t.Errorf("Unexpected response: %s", lastResponse)
+	account2, err := browspr.HandleAuthCreateAccountRpc(message2)
+	if err != nil {
+		t.Fatalf("browspr.HandleAuthCreateAccountRpc(%v) failed: %v", message2, err)
 	}
 
-	// Verify that principalManager has the new account
-	expectedAccount2 := fmt.Sprintf("%s%s%d", topLevelName, security.ChainSeparator, 1)
-	if b, err := browspr.accountManager.PrincipalManager().BlessingsForAccount(expectedAccount2); err != nil || b == nil {
-		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", expectedAccount, b, err)
+	// Verify that principalManager has both accounts
+	if b, err := browspr.principalManager.BlessingsForAccount(account1.(string)); err != nil || b == nil {
+		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", account1, b, err)
 	}
-
-	// Verify that principalManager has the first account
-	if b, err := browspr.accountManager.PrincipalManager().BlessingsForAccount(expectedAccount); err != nil || b == nil {
-		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", expectedAccount, b, err)
+	if b, err := browspr.principalManager.BlessingsForAccount(account2.(string)); err != nil || b == nil {
+		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", account2, b, err)
 	}
 }
 
 func TestHandleAssocAccount(t *testing.T) {
-	browspr, teardown := setup(t, nil)
+	browspr, teardown := setup(t)
 	defer teardown()
 
 	// First create an account.
@@ -129,19 +108,25 @@
 	if err != nil {
 		t.Fatalf("browspr.rt.Principal.BlessSelf(%v) failed: %v", account, err)
 	}
-	if err := browspr.accountManager.PrincipalManager().AddAccount(account, blessing); err != nil {
+	if err := browspr.principalManager.AddAccount(account, blessing); err != nil {
 		t.Fatalf("browspr.principalManager.AddAccount(%v, %v) failed; %v", account, blessing, err)
 	}
 
 	origin := "https://my.webapp.com:443"
+	message, err := valueOf(associateAccountMessage{
+		Account: account,
+		Origin:  origin,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
 
-	// TODO(suharshs,nlacasse,bprosnitz): Get caveats here like wspr is doing. See account.go AssociateAccount.
-	if err := browspr.HandleAssociateAccountMessage(origin, account, nil); err != nil {
-		t.Fatalf("Failed to associate account: %v", err)
+	if _, err := browspr.HandleAuthAssociateAccountRpc(message); err != nil {
+		t.Fatalf("browspr.HandleAuthAssociateAccountRpc(%v) failed: %v", message, err)
 	}
 
 	// Verify that principalManager has the correct principal for the origin
-	got, err := browspr.accountManager.PrincipalManager().Principal(origin)
+	got, err := browspr.principalManager.Principal(origin)
 	if err != nil {
 		t.Fatalf("browspr.principalManager.Principal(%v) failed: %v", origin, err)
 	}
@@ -152,24 +137,39 @@
 }
 
 func TestHandleAssocAccountWithMissingAccount(t *testing.T) {
-	browspr, teardown := setup(t, nil)
+	browspr, teardown := setup(t)
 	defer teardown()
 
 	account := "mock-account"
 	origin := "https://my.webapp.com:443"
+	message, err := valueOf(associateAccountMessage{
+		Account: account,
+		Origin:  origin,
+	})
+	if err != nil {
+		t.Fatal(err)
+	}
 
-	// TODO(suharshs,nlacasse,bprosnitz): Get caveats here like wspr is doing. See account.go AssociateAccount.
-	if err := browspr.HandleAssociateAccountMessage(origin, account, nil); err == nil {
-		t.Fatalf("Expected to receive error associating non-existant account.")
+	if _, err := browspr.HandleAuthAssociateAccountRpc(message); err == nil {
+		t.Fatalf("browspr.HandleAuthAssociateAccountRpc(%v) should have failed but did not.")
 	}
 
 	// Verify that principalManager creates no principal for the origin
-	got, err := browspr.accountManager.PrincipalManager().Principal(origin)
+	got, err := browspr.principalManager.Principal(origin)
 	if err == nil {
-		t.Fatalf("Expected wspr.principalManager.Principal(%v) to fail, but got: %v", origin, got)
+		t.Fatalf("Expected browspr.principalManager.Principal(%v) to fail, but got: %v", origin, got)
 	}
 
 	if got != nil {
-		t.Fatalf("Expected wspr.principalManager.Principal(%v) not to return a principal, but got %v", origin, got)
+		t.Fatalf("Expected browspr.principalManager.Principal(%v) not to return a principal, but got %v", origin, got)
 	}
 }
+
+// Helper to create a *vdl.Value from interface.
+// TODO(nlacasse): Todd says there will eventually be a "ValueOf" somewhere
+// inside vom/vdl. Remove this once that is available.
+func valueOf(in interface{}) (*vdl.Value, error) {
+	var out *vdl.Value
+	err := valconv.Convert(&out, in)
+	return out, err
+}
diff --git a/services/wsprd/browspr/browspr_test.go b/services/wsprd/browspr/browspr_test.go
index f8a7cc0..da16e1a 100644
--- a/services/wsprd/browspr/browspr_test.go
+++ b/services/wsprd/browspr/browspr_test.go
@@ -158,7 +158,7 @@
 		vlog.Fatal(err)
 	}
 	runtime.Namespace().SetRoots(wsNamespaceRoots...)
-	browspr := NewBrowspr(runtime, postMessageHandler, nil, spec, "/mock/identd", wsNamespaceRoots)
+	browspr := NewBrowspr(runtime, postMessageHandler, nil, &spec, "/mock:1234/identd", wsNamespaceRoots)
 
 	// browspr sets its namespace root to use the "ws" protocol, but we want to force "tcp" here.
 	browspr.namespaceRoots = []string{tcpNamespaceRoot}
@@ -167,6 +167,17 @@
 	browspr.accountManager.SetMockBlesser(newMockBlesserService(principal))
 
 	msgInstanceId := int32(11)
+	msgOrigin := "http://test-origin.com"
+
+	// Associate the origin with the root accounts' blessings, otherwise a
+	// dummy account will be used and will be rejected by the authorizer.
+	accountName := "test-account"
+	if err := browspr.principalManager.AddAccount(accountName, browspr.rt.Principal().BlessingStore().Default()); err != nil {
+		t.Fatalf("Failed to add account: %v")
+	}
+	if err := browspr.accountManager.AssociateAccount(msgOrigin, accountName, nil); err != nil {
+		t.Fatalf("Failed to associate account: %v")
+	}
 
 	rpc := app.VeyronRPC{
 		Name:        mockServerName,
@@ -191,7 +202,7 @@
 		t.Fatalf("Failed to marshall app message to json: %v", err)
 	}
 
-	err = browspr.HandleMessage(msgInstanceId, string(msg))
+	err = browspr.HandleMessage(msgInstanceId, msgOrigin, string(msg))
 	if err != nil {
 		t.Fatalf("Error while handling message: %v", err)
 	}
diff --git a/services/wsprd/browspr/file_serializer_nacl.go b/services/wsprd/browspr/file_serializer_nacl.go
new file mode 100644
index 0000000..96fc8e1
--- /dev/null
+++ b/services/wsprd/browspr/file_serializer_nacl.go
@@ -0,0 +1,61 @@
+package browspr
+
+import (
+	"io"
+	"os"
+	"runtime/ppapi"
+)
+
+// fileSerializer implements vsecurity.SerializerReaderWriter that persists state to
+// files with the pepper API.
+type fileSerializer struct {
+	system    ppapi.FileSystem
+	data      *ppapi.FileIO
+	signature *ppapi.FileIO
+
+	dataFile      string
+	signatureFile string
+}
+
+func (fs *fileSerializer) Readers() (data io.ReadCloser, sig io.ReadCloser, err error) {
+	if fs.data == nil || fs.signature == nil {
+		return nil, nil, nil
+	}
+	return fs.data, fs.signature, nil
+}
+
+func (fs *fileSerializer) Writers() (data io.WriteCloser, sig io.WriteCloser, err error) {
+	// Remove previous version of the files
+	fs.system.Remove(fs.dataFile)
+	fs.system.Remove(fs.signatureFile)
+	if fs.data, err = fs.system.Create(fs.dataFile); err != nil {
+		return nil, nil, err
+	}
+	if fs.signature, err = fs.system.Create(fs.signatureFile); err != nil {
+		return nil, nil, err
+	}
+	return fs.data, fs.signature, nil
+}
+
+func fileNotExist(err error) bool {
+	pe, ok := err.(*os.PathError)
+	return ok && pe.Err.Error() == "file not found"
+}
+
+func NewFileSerializer(dataFile, signatureFile string, system ppapi.FileSystem) (*fileSerializer, error) {
+	data, err := system.Open(dataFile)
+	if err != nil && !fileNotExist(err) {
+		return nil, err
+	}
+	signature, err := system.Open(signatureFile)
+	if err != nil && !fileNotExist(err) {
+		return nil, err
+	}
+	return &fileSerializer{
+		system:        system,
+		data:          data,
+		signature:     signature,
+		dataFile:      dataFile,
+		signatureFile: signatureFile,
+	}, nil
+}
diff --git a/services/wsprd/browspr/main/main_nacl.go b/services/wsprd/browspr/main/main_nacl.go
index 3982c88..4f8e955 100644
--- a/services/wsprd/browspr/main/main_nacl.go
+++ b/services/wsprd/browspr/main/main_nacl.go
@@ -3,9 +3,8 @@
 import (
 	"bytes"
 	"crypto/ecdsa"
+	"encoding/base64"
 	"fmt"
-	"io"
-	"os"
 	"runtime/ppapi"
 
 	"veyron.io/veyron/veyron/lib/websocket"
@@ -15,8 +14,11 @@
 	"veyron.io/veyron/veyron2/options"
 	"veyron.io/veyron/veyron2/rt"
 	"veyron.io/veyron/veyron2/security"
+	"veyron.io/veyron/veyron2/vdl"
+	"veyron.io/veyron/veyron2/vdl/valconv"
 	"veyron.io/veyron/veyron2/vlog"
 	"veyron.io/wspr/veyron/services/wsprd/browspr"
+	"veyron.io/wspr/veyron/services/wsprd/channel/channel_nacl"
 	"veyron.io/wspr/veyron/services/wsprd/lib"
 )
 
@@ -24,79 +26,30 @@
 	ppapi.Init(newBrowsprInstance)
 }
 
-// fileSerializer implements vsecurity.SerializerReaderWriter that persists state to
-// files with the pepper API.
-type fileSerializer struct {
-	system    ppapi.FileSystem
-	data      *ppapi.FileIO
-	signature *ppapi.FileIO
-
-	dataFile      string
-	signatureFile string
-}
-
-func (fs *fileSerializer) Readers() (io.ReadCloser, io.ReadCloser, error) {
-	if fs.data == nil || fs.signature == nil {
-		return nil, nil, nil
-	}
-	return fs.data, fs.signature, nil
-}
-
-func (fs *fileSerializer) Writers() (io.WriteCloser, io.WriteCloser, error) {
-	// Remove previous version of the files
-	fs.system.Remove(fs.dataFile)
-	fs.system.Remove(fs.signatureFile)
-	var err error
-	if fs.data, err = fs.system.Create(fs.dataFile); err != nil {
-		return nil, nil, err
-	}
-	if fs.signature, err = fs.system.Create(fs.signatureFile); err != nil {
-		return nil, nil, err
-	}
-	return fs.data, fs.signature, nil
-}
-
-func fileNotExist(err error) bool {
-	pe, ok := err.(*os.PathError)
-	return ok && pe.Err.Error() == "file not found"
-}
-
-func newFileSerializer(dataFile, signatureFile string, system ppapi.FileSystem) (*fileSerializer, error) {
-	data, err := system.Open(dataFile)
-	if err != nil && !fileNotExist(err) {
-		return nil, err
-	}
-	signature, err := system.Open(signatureFile)
-	if err != nil && !fileNotExist(err) {
-		return nil, err
-	}
-	fmt.Print("NewFileSerializer:%v", err)
-	return &fileSerializer{
-		system:        system,
-		data:          data,
-		signature:     signature,
-		dataFile:      dataFile,
-		signatureFile: signatureFile,
-	}, nil
-}
-
-// WSPR instance represents an instance of a PPAPI client and receives callbacks from PPAPI to handle events.
+// browsprInstance represents an instance of a PPAPI client and receives
+// callbacks from PPAPI to handle events.
 type browsprInstance struct {
 	ppapi.Instance
 	fs      ppapi.FileSystem
 	browspr *browspr.Browspr
+	channel *channel_nacl.Channel
 }
 
 var _ ppapi.InstanceHandlers = (*browsprInstance)(nil)
 
 func newBrowsprInstance(inst ppapi.Instance) ppapi.InstanceHandlers {
-	browspr := &browsprInstance{Instance: inst}
-	browspr.initFileSystem()
-	websocket.PpapiInstance = inst
-	return browspr
-}
+	browsprInst := &browsprInstance{Instance: inst}
+	browsprInst.initFileSystem()
 
-const browsprDir = "/browspr/data"
+	// Give the websocket interface the ppapi instance.
+	websocket.PpapiInstance = inst
+
+	// Set up the channel and register start rpc handler.
+	browsprInst.channel = channel_nacl.NewChannel(inst)
+	browsprInst.channel.RegisterRequestHandler("start", browsprInst.HandleStartMessage)
+
+	return browsprInst
+}
 
 func (inst *browsprInstance) initFileSystem() {
 	var err error
@@ -117,125 +70,177 @@
 	}
 }
 
-// StartBrowspr handles starting browspr.
-func (inst *browsprInstance) StartBrowspr(instanceId int32, message ppapi.Var) error {
-	fmt.Println("Starting Browspr")
+const browsprDir = "/browspr/data"
+
+// Loads a saved key if one exists, otherwise creates a new one and persists it.
+func (inst *browsprInstance) initKey() (*ecdsa.PrivateKey, error) {
 	var ecdsaKey *ecdsa.PrivateKey
 	browsprKeyFile := browsprDir + "/privateKey.pem."
-
 	// See whether we have any cached keys for WSPR
 	if rFile, err := inst.fs.Open(browsprKeyFile); err == nil {
 		fmt.Print("Opening cached browspr ecdsaPrivateKey")
 		defer rFile.Release()
 		key, err := vsecurity.LoadPEMKey(rFile, nil)
 		if err != nil {
-			return fmt.Errorf("failed to load browspr key:%s", err)
+			return nil, fmt.Errorf("failed to load browspr key:%s", err)
 		}
 		var ok bool
 		if ecdsaKey, ok = key.(*ecdsa.PrivateKey); !ok {
-			return fmt.Errorf("got key of type %T, want *ecdsa.PrivateKey", key)
+			return nil, fmt.Errorf("got key of type %T, want *ecdsa.PrivateKey", key)
 		}
 	} else {
-		if pemKey, err := message.LookupStringValuedKey("pemPrivateKey"); err == nil {
-			fmt.Print("Using ecdsaPrivateKey from incoming request")
-			key, err := vsecurity.LoadPEMKey(bytes.NewBufferString(pemKey), nil)
-			if err != nil {
-				return err
-			}
-			var ok bool
-			ecdsaKey, ok = key.(*ecdsa.PrivateKey)
-			if !ok {
-				return fmt.Errorf("got key of type %T, want *ecdsa.PrivateKey", key)
-			}
-		} else {
-			fmt.Print("Generating new browspr ecdsaPrivateKey")
-			// Generate new keys and store them.
-			var err error
-			if _, ecdsaKey, err = vsecurity.NewPrincipalKey(); err != nil {
-				return fmt.Errorf("failed to generate security key:%s", err)
-			}
+		fmt.Print("Generating new browspr ecdsaPrivateKey")
+		// Generate new keys and store them.
+		var err error
+		if _, ecdsaKey, err = vsecurity.NewPrincipalKey(); err != nil {
+			return nil, fmt.Errorf("failed to generate security key:%s", err)
 		}
 		// Persist the keys in a local file.
 		wFile, err := inst.fs.Create(browsprKeyFile)
 		if err != nil {
-			return fmt.Errorf("failed to create file to persist browspr keys:%s", err)
+			return nil, fmt.Errorf("failed to create file to persist browspr keys:%s", err)
 		}
 		defer wFile.Release()
 		var b bytes.Buffer
 		if err = vsecurity.SavePEMKey(&b, ecdsaKey, nil); err != nil {
-			return fmt.Errorf("failed to save browspr key:%s", err)
+			return nil, fmt.Errorf("failed to save browspr key:%s", err)
 		}
 		if n, err := wFile.Write(b.Bytes()); n != b.Len() || err != nil {
-			return fmt.Errorf("failed to write browspr key:%s", err)
+			return nil, fmt.Errorf("failed to write browspr key:%s", err)
 		}
 	}
+	return ecdsaKey, nil
+}
 
-	roots, err := newFileSerializer(browsprDir+"/blessingroots.data", browsprDir+"/blessingroots.sig", inst.fs)
+func (inst *browsprInstance) newPersistantPrincipal(peerNames []string) (security.Principal, error) {
+	ecdsaKey, err := inst.initKey()
 	if err != nil {
-		return fmt.Errorf("failed to create blessing roots serializer:%s", err)
+		return nil, fmt.Errorf("failed to initialize ecdsa key:%s", err)
 	}
-	store, err := newFileSerializer(browsprDir+"/blessingstore.data", browsprDir+"/blessingstore.sig", inst.fs)
+
+	roots, err := browspr.NewFileSerializer(browsprDir+"/blessingroots.data", browsprDir+"/blessingroots.sig", inst.fs)
 	if err != nil {
-		return fmt.Errorf("failed to create blessing store serializer:%s", err)
+		return nil, fmt.Errorf("failed to create blessing roots serializer:%s", err)
+	}
+	store, err := browspr.NewFileSerializer(browsprDir+"/blessingstore.data", browsprDir+"/blessingstore.sig", inst.fs)
+	if err != nil {
+		return nil, fmt.Errorf("failed to create blessing store serializer:%s", err)
 	}
 	state := &vsecurity.PrincipalStateSerializer{
 		BlessingRoots: roots,
 		BlessingStore: store,
 	}
-	principal, err := vsecurity.NewPrincipalFromSigner(security.NewInMemoryECDSASigner(ecdsaKey), state)
-	if err != nil {
-		return err
-	}
 
-	defaultBlessingName, err := message.LookupStringValuedKey("defaultBlessingName")
-	if err != nil {
-		return err
-	}
+	return vsecurity.NewPrincipalFromSigner(security.NewInMemoryECDSASigner(ecdsaKey), state)
+}
 
-	if err := vsecurity.InitDefaultBlessings(principal, defaultBlessingName); err != nil {
-		return err
-	}
+type startMessage struct {
+	Identityd             string
+	IdentitydBlessingRoot blessingRoot
+	Proxy                 string
+	NamespaceRoot         string
+}
 
-	veyronProxy, err := message.LookupStringValuedKey("proxy")
-	if err != nil {
-		return err
-	}
-	if veyronProxy == "" {
-		return fmt.Errorf("proxy field was empty")
-	}
+// Copied from
+// veyron.io/veyron/veyron/services/identity/handlers/blessing_root.go, since
+// depcop prohibits importing that package.
+type blessingRoot struct {
+	Names     []string `json:"names"`
+	PublicKey string   `json:"publicKey"`
+}
 
-	mounttable, err := message.LookupStringValuedKey("namespaceRoot")
+// Base64-decode and unmarshal a public key.
+func decodeAndUnmarshalPublicKey(k string) (security.PublicKey, error) {
+	decodedK, err := base64.URLEncoding.DecodeString(k)
 	if err != nil {
-		return err
+		return nil, err
 	}
+	return security.UnmarshalPublicKey(decodedK)
+}
 
-	identityd, err := message.LookupStringValuedKey("identityd")
-	if err != nil {
-		return err
+func (inst *browsprInstance) HandleStartMessage(val *vdl.Value) (interface{}, error) {
+	fmt.Println("Starting Browspr")
+
+	var msg startMessage
+	if err := valconv.Convert(&msg, val); err != nil {
+		return nil, err
 	}
 
 	listenSpec := ipc.ListenSpec{
-		Proxy: veyronProxy,
+		Proxy: msg.Proxy,
 		Addrs: ipc.ListenAddrs{{Protocol: "ws", Address: ""}},
 	}
 
+	principal, err := inst.newPersistantPrincipal(msg.IdentitydBlessingRoot.Names)
+	if err != nil {
+		return nil, err
+	}
+
+	blessingName := "browspr-default-blessing"
+	blessing, err := principal.BlessSelf(blessingName)
+	if err != nil {
+		return nil, fmt.Errorf("principal.BlessSelf(%v) failed: %v", blessingName, err)
+	}
+
+	// If msg.IdentitydBlessingRoot has a public key and names, then add
+	// the public key to our set of trusted roots, and limit our blessing
+	// to only talk to those names.
+	if msg.IdentitydBlessingRoot.PublicKey != "" {
+		if len(msg.IdentitydBlessingRoot.Names) == 0 {
+			return nil, fmt.Errorf("invalid IdentitydBlessingRoot: Names is empty")
+		}
+
+		fmt.Printf("Using blessing roots for identity with key %v and names %v", msg.IdentitydBlessingRoot.PublicKey, msg.IdentitydBlessingRoot.Names)
+		key, err := decodeAndUnmarshalPublicKey(msg.IdentitydBlessingRoot.PublicKey)
+		if err != nil {
+			vlog.Fatalf("decodeAndUnmarshalPublicKey(%v) failed: %v", msg.IdentitydBlessingRoot.PublicKey, err)
+		}
+
+		for _, name := range msg.IdentitydBlessingRoot.Names {
+			globPattern := security.BlessingPattern(name).MakeGlob()
+
+			// Trust the identity servers blessing root.
+			principal.Roots().Add(key, globPattern)
+
+			// Use our blessing to only talk to the identity server.
+			if _, err := principal.BlessingStore().Set(blessing, globPattern); err != nil {
+				return nil, fmt.Errorf("principal.BlessingStore().Set(%v, %v) failed: %v", blessing, globPattern, err)
+			}
+		}
+	} else {
+		fmt.Printf("IdentitydBlessingRoot.PublicKey is empty.  Will allow browspr blessing to be shareable with all principals.")
+		// Set our blessing as shareable with all peers.
+		if _, err := principal.BlessingStore().Set(blessing, security.AllPrincipals); err != nil {
+			return nil, fmt.Errorf("principal.BlessingStore().Set(%v, %v) failed: %v", blessing, security.AllPrincipals, err)
+		}
+	}
+
 	runtime, err := rt.New(options.RuntimePrincipal{principal})
 	if err != nil {
-		vlog.Fatalf("rt.New failed: %s", err)
+		return nil, err
 	}
 	// TODO(ataly, bprosnitz, caprita): The runtime MUST be cleaned up
 	// after use. Figure out the appropriate place to add the Cleanup call.
-	wsNamespaceRoots, err := lib.EndpointsToWs(runtime, []string{mounttable})
+	wsNamespaceRoots, err := lib.EndpointsToWs(runtime, []string{msg.NamespaceRoot})
 	if err != nil {
-		vlog.Fatal(err)
+		return nil, err
 	}
 	runtime.Namespace().SetRoots(wsNamespaceRoots...)
 
-	fmt.Printf("Starting browspr with config: proxy=%q mounttable=%q identityd=%q ", veyronProxy, mounttable, identityd)
-	inst.browspr = browspr.NewBrowspr(runtime, inst.BrowsprOutgoingPostMessage, chrome.New, listenSpec, identityd, wsNamespaceRoots)
+	fmt.Printf("Starting browspr with config: proxy=%q mounttable=%q identityd=%q identitydBlessingRoot=%q ", msg.Proxy, msg.NamespaceRoot, msg.Identityd, msg.IdentitydBlessingRoot)
+	inst.browspr = browspr.NewBrowspr(runtime,
+		inst.BrowsprOutgoingPostMessage,
+		chrome.New,
+		&listenSpec,
+		msg.Identityd,
+		wsNamespaceRoots)
 
-	inst.BrowsprOutgoingPostMessage(instanceId, "browsprStarted", "")
-	return nil
+	// Add the rpc handlers that depend on inst.browspr.
+	inst.channel.RegisterRequestHandler("auth:create-account", inst.browspr.HandleAuthCreateAccountRpc)
+	inst.channel.RegisterRequestHandler("auth:associate-account", inst.browspr.HandleAuthAssociateAccountRpc)
+	inst.channel.RegisterRequestHandler("cleanup", inst.browspr.HandleCleanupRpc)
+
+	return nil, nil
 }
 
 func (inst *browsprInstance) BrowsprOutgoingPostMessage(instanceId int32, ty string, message string) {
@@ -258,56 +263,26 @@
 	dict.Release()
 }
 
-func (inst *browsprInstance) HandleBrowsprMessage(instanceId int32, message ppapi.Var) error {
+// HandleBrowsprMessage handles one-way messages of the type "browsprMsg" by
+// sending them to browspr's handler.
+func (inst *browsprInstance) HandleBrowsprMessage(instanceId int32, origin string, message ppapi.Var) error {
 	str, err := message.AsString()
 	if err != nil {
 		// TODO(bprosnitz) Remove. We shouldn't panic on user input.
 		return fmt.Errorf("Error while converting message to string: %v", err)
 	}
 
-	if err := inst.browspr.HandleMessage(instanceId, str); err != nil {
+	if err := inst.browspr.HandleMessage(instanceId, origin, str); err != nil {
 		// TODO(bprosnitz) Remove. We shouldn't panic on user input.
 		return fmt.Errorf("Error while handling message in browspr: %v", err)
 	}
 	return nil
 }
 
-func (inst *browsprInstance) HandleBrowsprCleanup(instanceId int32, message ppapi.Var) error {
-	inst.browspr.HandleCleanupMessage(instanceId)
-	return nil
-}
-
-func (inst *browsprInstance) HandleBrowsprCreateAccount(instanceId int32, message ppapi.Var) error {
-	accessToken, err := message.LookupStringValuedKey("accessToken")
-	if err != nil {
-		return err
-	}
-
-	err = inst.browspr.HandleCreateAccountMessage(instanceId, accessToken)
-	if err != nil {
-		// TODO(bprosnitz) Remove. We shouldn't panic on user input.
-		panic(fmt.Sprintf("Error creating account: %v", err))
-	}
-	return nil
-}
-
-func (inst *browsprInstance) HandleBrowsprAssociateAccount(_ int32, message ppapi.Var) error {
-	origin, err := message.LookupStringValuedKey("origin")
-	if err != nil {
-		return err
-	}
-
-	account, err := message.LookupStringValuedKey("account")
-	if err != nil {
-		return err
-	}
-
-	// TODO(suharshs,nlacasse,bprosnitz): Get caveats here like wspr is doing. See account.go AssociateAccount.
-	err = inst.browspr.HandleAssociateAccountMessage(origin, account, nil)
-	if err != nil {
-		// TODO(bprosnitz) Remove. We shouldn't panic on user input.
-		return fmt.Errorf("Error associating account: %v", err)
-	}
+// HandleBrowsprRpc handles two-way rpc messages of the type "browsprRpc"
+// sending them to the channel's handler.
+func (inst *browsprInstance) HandleBrowsprRpc(instanceId int32, origin string, message ppapi.Var) error {
+	inst.channel.HandleMessage(message)
 	return nil
 }
 
@@ -327,17 +302,19 @@
 		inst.handleGoError(err)
 		return
 	}
+	origin, err := message.LookupStringValuedKey("origin")
+	if err != nil {
+		inst.handleGoError(err)
+		return
+	}
 	ty, err := message.LookupStringValuedKey("type")
 	if err != nil {
 		inst.handleGoError(err)
 		return
 	}
-	var messageHandlers = map[string]func(int32, ppapi.Var) error{
-		"browsprStart":            inst.StartBrowspr,
-		"browsprMsg":              inst.HandleBrowsprMessage,
-		"browsprCleanup":          inst.HandleBrowsprCleanup,
-		"browsprCreateAccount":    inst.HandleBrowsprCreateAccount,
-		"browsprAssociateAccount": inst.HandleBrowsprAssociateAccount,
+	var messageHandlers = map[string]func(int32, string, ppapi.Var) error{
+		"browsprMsg": inst.HandleBrowsprMessage,
+		"browsprRpc": inst.HandleBrowsprRpc,
 	}
 	h, ok := messageHandlers[ty]
 	if !ok {
@@ -348,7 +325,7 @@
 	if err != nil {
 		body = ppapi.VarUndefined
 	}
-	err = h(int32(instanceId), body)
+	err = h(int32(instanceId), origin, body)
 	body.Release()
 	if err != nil {
 		inst.handleGoError(err)
diff --git a/services/wsprd/browspr/pipe.go b/services/wsprd/browspr/pipe.go
index f31e1fb..ab42047 100644
--- a/services/wsprd/browspr/pipe.go
+++ b/services/wsprd/browspr/pipe.go
@@ -14,28 +14,46 @@
 type pipe struct {
 	browspr    *Browspr
 	controller *app.Controller
+	origin     string
 	instanceId int32
 }
 
-func newPipe(b *Browspr, instanceId int32) *pipe {
+func newPipe(b *Browspr, instanceId int32, origin string) *pipe {
 	pipe := &pipe{
 		browspr:    b,
+		origin:     origin,
 		instanceId: instanceId,
 	}
 
-	// TODO(bprosnitz) Principal() maybe should not take a string in the future.
-	p, err := b.accountManager.LookupPrincipal(fmt.Sprintf("%d", instanceId))
+	// TODO(bprosnitz) LookupPrincipal() maybe should not take a string in the future.
+	p, err := b.accountManager.LookupPrincipal(origin)
 	if err != nil {
-		p = b.rt.Principal()
-		b.rt.Logger().Errorf("No principal associated with instanceId %d: %v", instanceId, err)
-		// TODO(bjornick): Send an error to the client when all of the principal stuff is set up.
+		// TODO(nlacasse, bjornick): This code should go away once we
+		// start requiring authentication.  At that point, we should
+		// just return an error to the client.
+		b.rt.Logger().Errorf("No principal associated with origin %v, creating a new principal with self-signed blessing from browspr: %v", origin, err)
+
+		dummyAccount, err := b.principalManager.DummyAccount()
+		if err != nil {
+			b.rt.Logger().Errorf("principalManager.DummyAccount() failed: %v", err)
+			return nil
+		}
+
+		if err := b.accountManager.AssociateAccount(origin, dummyAccount, nil); err != nil {
+			b.rt.Logger().Errorf("accountManager.AssociateAccount(%v, %v, %v) failed: %v", origin, dummyAccount, nil, err)
+			return nil
+		}
+		p, err = b.accountManager.LookupPrincipal(origin)
+		if err != nil {
+			return nil
+		}
 	}
 
 	var profile veyron2.Profile
 	if b.profileFactory != nil {
 		profile = b.profileFactory()
 	}
-	pipe.controller, err = app.NewController(pipe.createWriter, profile, &b.listenSpec, b.namespaceRoots, options.RuntimePrincipal{p})
+	pipe.controller, err = app.NewController(pipe.createWriter, profile, b.listenSpec, b.namespaceRoots, options.RuntimePrincipal{p})
 	if err != nil {
 		b.rt.Logger().Errorf("Could not create controller: %v", err)
 		return nil
diff --git a/services/wsprd/channel/channel.go b/services/wsprd/channel/channel.go
index c2b7836..1e16121 100644
--- a/services/wsprd/channel/channel.go
+++ b/services/wsprd/channel/channel.go
@@ -94,10 +94,13 @@
 
 func (c *Channel) HandleMessage(m Message) {
 	switch r := m.(type) {
+	// Run the handlers in goroutines so we don't block the main thread.
+	// This is particularly important for the request handler, since it can
+	// potentially do a lot of work.
 	case MessageRequest:
-		c.handleRequest(r.Value)
+		go c.handleRequest(r.Value)
 	case MessageResponse:
-		c.handleResponse(r.Value)
+		go c.handleResponse(r.Value)
 	default:
 		panic(fmt.Sprintf("Unknown message type: %T", m))
 	}
diff --git a/services/wsprd/channel/channel_nacl/channel_nacl.go b/services/wsprd/channel/channel_nacl/channel_nacl.go
index ec4ee5c..4c7c830 100644
--- a/services/wsprd/channel/channel_nacl/channel_nacl.go
+++ b/services/wsprd/channel/channel_nacl/channel_nacl.go
@@ -6,6 +6,7 @@
 	"runtime/ppapi"
 
 	"veyron.io/veyron/veyron2/vdl"
+	"veyron.io/veyron/veyron2/vdl/valconv"
 	"veyron.io/veyron/veyron2/vom2"
 	"veyron.io/wspr/veyron/services/wsprd/channel" // contains most of the logic, factored out for testing
 )
@@ -42,7 +43,11 @@
 
 func (c *Channel) RegisterRequestHandler(typ string, handler RequestHandler) {
 	wrappedHandler := func(val interface{}) (interface{}, error) {
-		return handler(val.(*vdl.Value))
+		var v *vdl.Value
+		if err := valconv.Convert(&v, val); err != nil {
+			return nil, err
+		}
+		return handler(v)
 	}
 	c.impl.RegisterRequestHandler(typ, wrappedHandler)
 }
diff --git a/services/wsprd/principal/principal.go b/services/wsprd/principal/principal.go
index 19001c4..ed33767 100644
--- a/services/wsprd/principal/principal.go
+++ b/services/wsprd/principal/principal.go
@@ -28,6 +28,7 @@
 
 import (
 	"bytes"
+	"fmt"
 	"io"
 	"net/url"
 	"sync"
@@ -116,6 +117,11 @@
 	root security.Principal
 
 	serializer vsecurity.SerializerReaderWriter
+
+	// Dummy account name
+	// TODO(bjornick, nlacasse): Remove this once the tests no longer need
+	// it.
+	dummyAccount string
 }
 
 // NewPrincipalManager returns a new PrincipalManager that creates new principals
@@ -273,3 +279,28 @@
 	}
 	return ret, nil
 }
+
+// Add dummy account with default blessings, for use by unauthenticated
+// clients.
+// TODO(nlacasse, bjornick): This should go away once unauthenticate clients
+// are no longer allowed.
+func (i *PrincipalManager) DummyAccount() (string, error) {
+	if i.dummyAccount == "" {
+		// Note: We only set i.dummyAccount once the account has been
+		// successfully created.  Otherwise, if an error occurs, the
+		// next time this function is called it the account won't exist
+		// but this function will return the name of the account
+		// without trying to create it.
+		dummyAccount := "unauthenticated-dummy-account"
+		blessings, err := i.root.BlessSelf(dummyAccount)
+		if err != nil {
+			return "", fmt.Errorf("i.root.BlessSelf(%v) failed: %v", dummyAccount, err)
+		}
+
+		if err := i.AddAccount(dummyAccount, blessings); err != nil {
+			return "", fmt.Errorf("browspr.principalManager.AddAccount(%v, %v) failed: %v", dummyAccount, blessings, err)
+		}
+		i.dummyAccount = dummyAccount
+	}
+	return i.dummyAccount, nil
+}
diff --git a/services/wsprd/wspr.go b/services/wsprd/wspr.go
index 8e87825..df661e8 100644
--- a/services/wsprd/wspr.go
+++ b/services/wsprd/wspr.go
@@ -13,7 +13,7 @@
 
 func main() {
 	port := flag.Int("port", 8124, "Port to listen on.")
-	identd := flag.String("identd", "", "identd server name. Must be set.")
+	identd := flag.String("identd", "", "name of identd server.")
 
 	flag.Parse()
 
diff --git a/services/wsprd/wspr/wspr.go b/services/wsprd/wspr/wspr.go
index cb4c9e6..8a29f46 100644
--- a/services/wsprd/wspr/wspr.go
+++ b/services/wsprd/wspr/wspr.go
@@ -17,7 +17,6 @@
 import (
 	"bytes"
 	"crypto/tls"
-	"encoding/json"
 	"fmt"
 	"io"
 	"net"
@@ -49,7 +48,6 @@
 	logger           vlog.Logger
 	profileFactory   func() veyron2.Profile
 	listenSpec       *ipc.ListenSpec
-	identdEP         string
 	namespaceRoots   []string
 	principalManager *principal.PrincipalManager
 	accountManager   *account.AccountManager
@@ -102,8 +100,6 @@
 func (ctx *WSPR) Serve() {
 	// Configure HTTP routes.
 	http.HandleFunc("/debug", ctx.handleDebug)
-	http.HandleFunc("/create-account", ctx.handleCreateAccount)
-	http.HandleFunc("/assoc-account", ctx.handleAssocAccount)
 	http.HandleFunc("/ws", ctx.handleWS)
 	// Everything else is a 404.
 	// Note: the pattern "/" matches all paths not matched by other registered
@@ -131,15 +127,11 @@
 	if listenSpec.Proxy == "" {
 		vlog.Fatalf("a veyron proxy must be set")
 	}
-	if identdEP == "" {
-		vlog.Fatalf("an identd server must be set")
-	}
 
 	wspr := &WSPR{
 		httpPort:       httpPort,
 		profileFactory: profileFactory,
 		listenSpec:     listenSpec,
-		identdEP:       identdEP,
 		namespaceRoots: namespaceRoots,
 		rt:             runtime,
 		logger:         runtime.Logger(),
@@ -198,79 +190,3 @@
 	defer ctx.mu.Unlock()
 	ctx.pipes[r] = p
 }
-
-// Structs for marshalling input/output to create-account route.
-type createAccountInput struct {
-	AccessToken string `json:"access_token"`
-}
-
-type createAccountOutput struct {
-	Account string `json:"account"`
-}
-
-// Handler for creating an account in the principal manager.
-// A valid OAuth2 access token must be supplied in the request body,
-// which is exchanged for blessings from the veyron blessing server.
-// An account based on the blessings is then added to WSPR's principal
-// manager, and the set of blessing strings are returned to the client.
-func (ctx *WSPR) handleCreateAccount(w http.ResponseWriter, r *http.Request) {
-	if r.Method != "POST" {
-		http.Error(w, "Method not allowed.", http.StatusMethodNotAllowed)
-		return
-	}
-
-	// Parse request body.
-	var data createAccountInput
-	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
-		ctx.logAndSendBadReqErr(w, fmt.Sprintf("Error parsing body: %v", err))
-	}
-
-	account, err := ctx.accountManager.CreateAccount(data.AccessToken)
-	if err != nil {
-		ctx.logAndSendBadReqErr(w, err.Error())
-		return
-	}
-
-	// Return blessings to the client.
-	out := createAccountOutput{
-		Account: account,
-	}
-	outJson, err := json.Marshal(out)
-	if err != nil {
-		ctx.logAndSendBadReqErr(w, fmt.Sprintf("Error mashalling names: %v", err))
-		return
-	}
-
-	// Success.
-	w.Header().Set("Content-Type", "application/json")
-	fmt.Fprintf(w, string(outJson))
-}
-
-// Struct for marshalling input to assoc-account route.
-type assocAccountInput struct {
-	Account string           `json:"account"`
-	Origin  string           `json:"origin"`
-	Caveats []account.Caveat `json:"caveats"`
-}
-
-// Handler for associating an existing principal with an origin.
-func (ctx *WSPR) handleAssocAccount(w http.ResponseWriter, r *http.Request) {
-	if r.Method != "POST" {
-		http.Error(w, "Method not allowed.", http.StatusMethodNotAllowed)
-		return
-	}
-
-	// Parse request body.
-	var data assocAccountInput
-	if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
-		http.Error(w, fmt.Sprintf("Error parsing body: %v", err), http.StatusBadRequest)
-	}
-
-	if err := ctx.accountManager.AssociateAccount(data.Origin, data.Account, data.Caveats); err != nil {
-		http.Error(w, err.Error(), http.StatusBadRequest)
-		return
-	}
-
-	// Success.
-	fmt.Fprintf(w, "")
-}
diff --git a/services/wsprd/wspr/wspr_account_test.go b/services/wsprd/wspr/wspr_account_test.go
deleted file mode 100644
index 42f6ff6..0000000
--- a/services/wsprd/wspr/wspr_account_test.go
+++ /dev/null
@@ -1,219 +0,0 @@
-package wspr
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"net/http"
-	"net/http/httptest"
-	"testing"
-
-	"veyron.io/veyron/veyron2/context"
-	"veyron.io/veyron/veyron2/ipc"
-	"veyron.io/veyron/veyron2/rt"
-	"veyron.io/veyron/veyron2/security"
-
-	"veyron.io/veyron/veyron/profiles"
-)
-
-const topLevelName = "mock-blesser"
-
-// BEGIN MOCK BLESSER SERVICE
-type mockBlesserService struct {
-	p     security.Principal
-	count int
-}
-
-func newMockBlesserService(p security.Principal) *mockBlesserService {
-	return &mockBlesserService{
-		p:     p,
-		count: 0,
-	}
-}
-
-func (m *mockBlesserService) BlessUsingAccessToken(c context.T, accessToken string, co ...ipc.CallOpt) (security.WireBlessings, string, error) {
-	var empty security.WireBlessings
-	m.count++
-	name := fmt.Sprintf("%s%s%d", topLevelName, security.ChainSeparator, m.count)
-	blessing, err := m.p.BlessSelf(name)
-	if err != nil {
-		return empty, "", err
-	}
-	return security.MarshalBlessings(blessing), name, nil
-}
-
-// END MOCK BLESSER SERVICE
-
-func setup(t *testing.T) (*WSPR, func()) {
-	spec := profiles.LocalListenSpec
-	spec.Proxy = "/mock/proxy"
-	r, err := rt.New()
-	if err != nil {
-		panic(err)
-	}
-	wspr := NewWSPR(r, 0, nil, &spec, "/mock/identd", nil)
-	wspr.accountManager.SetMockBlesser(newMockBlesserService(wspr.rt.Principal()))
-	return wspr, func() {
-		wspr.Shutdown()
-		r.Cleanup()
-	}
-}
-
-func TestHandleCreateAccount(t *testing.T) {
-	wspr, teardown := setup(t)
-	defer teardown()
-
-	method := "POST"
-	path := "/create-account"
-
-	// Add one account
-	data1 := createAccountInput{
-		AccessToken: "mock-access-token-1",
-	}
-	data1Json, err := json.Marshal(data1)
-	if err != nil {
-		t.Fatalf("json.Marshal(%v) failed: %v", data1, err)
-	}
-
-	data1JsonReader := bytes.NewReader(data1Json)
-	req, err := http.NewRequest(method, path, (data1JsonReader))
-	if err != nil {
-		t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, data1JsonReader, err)
-	}
-
-	resp1 := httptest.NewRecorder()
-	wspr.handleCreateAccount(resp1, req)
-	if resp1.Code != 200 {
-		t.Fatalf("Expected handleCreateAccount to return 200 OK, instead got %v", resp1)
-	}
-
-	// Verify that principalManager has the new account
-	account1 := fmt.Sprintf("%s%s%d", topLevelName, security.ChainSeparator, 1)
-	if b, err := wspr.principalManager.BlessingsForAccount(account1); err != nil || b == nil {
-		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", account1, b, err)
-	}
-
-	// Add another account
-	data2 := createAccountInput{
-		AccessToken: "mock-access-token-2",
-	}
-	data2Json, err := json.Marshal(data2)
-	if err != nil {
-		t.Fatalf("json.Marshal(%v) failed: %v", data2, err)
-	}
-	data2JsonReader := bytes.NewReader(data2Json)
-	req, err = http.NewRequest(method, path, data2JsonReader)
-	if err != nil {
-		t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, data2JsonReader, err)
-	}
-
-	resp2 := httptest.NewRecorder()
-	wspr.handleCreateAccount(resp2, req)
-	if resp2.Code != 200 {
-		t.Fatalf("Expected handleCreateAccount to return 200 OK, instead got %v", resp2)
-	}
-
-	// Verify that principalManager has both accounts
-	if b, err := wspr.principalManager.BlessingsForAccount(account1); err != nil || b == nil {
-		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", account1, b, err)
-	}
-	account2 := fmt.Sprintf("%s%s%d", topLevelName, security.ChainSeparator, 2)
-	if b, err := wspr.principalManager.BlessingsForAccount(account2); err != nil || b == nil {
-		t.Fatalf("Failed to get Blessings for account %v: got %v, %v", account2, b, err)
-	}
-}
-
-func TestHandleAssocAccount(t *testing.T) {
-	wspr, teardown := setup(t)
-	defer teardown()
-
-	// First create an account.
-	account := "mock-account"
-	blessing, err := wspr.rt.Principal().BlessSelf(account)
-	if err != nil {
-		t.Fatalf("wspr.rt.Principal.BlessSelf(%v) failed: %v", account, err)
-	}
-	if err := wspr.principalManager.AddAccount(account, blessing); err != nil {
-		t.Fatalf("wspr.principalManager.AddAccount(%v, %v) failed; %v", account, blessing, err)
-	}
-
-	// Associate with that account
-	method := "POST"
-	path := "/assoc-account"
-
-	origin := "https://my.webapp.com:443"
-	data := assocAccountInput{
-		Account: account,
-		Origin:  origin,
-	}
-
-	dataJson, err := json.Marshal(data)
-	if err != nil {
-		t.Fatalf("json.Marshal(%v) failed: %v", data, err)
-	}
-
-	dataJsonReader := bytes.NewReader(dataJson)
-	req, err := http.NewRequest(method, path, (dataJsonReader))
-	if err != nil {
-		t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, dataJsonReader, err)
-	}
-
-	resp := httptest.NewRecorder()
-	wspr.handleAssocAccount(resp, req)
-	if resp.Code != 200 {
-		t.Fatalf("Expected handleAssocAccount to return 200 OK, instead got %v", resp)
-	}
-
-	// Verify that principalManager has the correct principal for the origin
-	got, err := wspr.principalManager.Principal(origin)
-	if err != nil {
-		t.Fatalf("wspr.principalManager.Principal(%v) failed: %v", origin, err)
-	}
-
-	if got == nil {
-		t.Fatalf("Expected wspr.principalManager.Principal(%v) to return a valid principal, but got %v", origin, got)
-	}
-}
-
-func TestHandleAssocAccountWithMissingAccount(t *testing.T) {
-	wspr, teardown := setup(t)
-	defer teardown()
-
-	method := "POST"
-	path := "/assoc-account"
-
-	account := "mock-account"
-	origin := "https://my.webapp.com:443"
-	data := assocAccountInput{
-		Account: account,
-		Origin:  origin,
-	}
-
-	dataJson, err := json.Marshal(data)
-	if err != nil {
-		t.Fatalf("json.Marshal(%v) failed: %v", data, err)
-	}
-
-	dataJsonReader := bytes.NewReader(dataJson)
-	req, err := http.NewRequest(method, path, (dataJsonReader))
-	if err != nil {
-		t.Fatalf("http.NewRequest(%v, %v, %v,) failed: %v", method, path, dataJsonReader, err)
-	}
-
-	// Verify that the request fails with 400 Bad Request error
-	resp := httptest.NewRecorder()
-	wspr.handleAssocAccount(resp, req)
-	if resp.Code != 400 {
-		t.Fatalf("Expected handleAssocAccount to return 400 error, but got %v", resp)
-	}
-
-	// Verify that principalManager creates no principal for the origin
-	got, err := wspr.principalManager.Principal(origin)
-	if err == nil {
-		t.Fatalf("Expected wspr.principalManager.Principal(%v) to fail, but got: %v", origin, got)
-	}
-
-	if got != nil {
-		t.Fatalf("Expected wspr.principalManager.Principal(%v) not to return a principal, but got %v", origin, got)
-	}
-}