ipc,naming,security: Use blessing names in endpoint for server
authorization.

Servers now export "v4" formatted endpoints which contain the
blessing names that will be presented by the server. These endpoints
make their way into the mounttable.

This commit makes client use these blessing names to authorize servers
and prevent man-in-the-middle attacks.

This replaces the older scheme where the mounttable would explicitly
track blessings for each mounted server, separate from the endpoint.
Code for that (naming.MountedServer.BlessingPattern and related code)
will be removed in a follow-up change.

MultiPart: 1/2

Change-Id: Ib9f8fb3d5e6fe4ae1b87a8eb9755666f4f3e18ff
diff --git a/cmd/mgmt/device/impl/impl.go b/cmd/mgmt/device/impl/impl.go
index be5b3fb..602b7f7 100644
--- a/cmd/mgmt/device/impl/impl.go
+++ b/cmd/mgmt/device/impl/impl.go
@@ -220,9 +220,9 @@
 			serverKeyOpts = options.ServerPublicKey{deviceKey}
 		}
 	}
-	// Skip server resolve authorization since an unclaimed device might have
+	// Skip server endpoint authorization since an unclaimed device might have
 	// roots that will not be recognized by the claimer.
-	if err := device.ClaimableClient(deviceName).Claim(gctx, pairingToken, &granter{p: v23.GetPrincipal(gctx), extension: grant}, serverKeyOpts, options.SkipResolveAuthorization{}); err != nil {
+	if err := device.ClaimableClient(deviceName).Claim(gctx, pairingToken, &granter{p: v23.GetPrincipal(gctx), extension: grant}, serverKeyOpts, options.SkipServerEndpointAuthorization{}); err != nil {
 		return err
 	}
 	fmt.Fprintln(cmd.Stdout(), "Successfully claimed.")
diff --git a/cmd/namespace/impl.go b/cmd/namespace/impl.go
index 3d9fb58..5a8d085 100644
--- a/cmd/namespace/impl.go
+++ b/cmd/namespace/impl.go
@@ -166,7 +166,7 @@
 
 	var opts []naming.ResolveOpt
 	if flagInsecureResolve {
-		opts = append(opts, options.SkipResolveAuthorization{})
+		opts = append(opts, options.SkipServerEndpointAuthorization{})
 	}
 	me, err := ns.Resolve(ctx, name, opts...)
 	if err != nil {
@@ -200,7 +200,7 @@
 	ns := v23.GetNamespace(ctx)
 	var opts []naming.ResolveOpt
 	if flagInsecureResolveToMT {
-		opts = append(opts, options.SkipResolveAuthorization{})
+		opts = append(opts, options.SkipServerEndpointAuthorization{})
 	}
 	e, err := ns.ResolveToMountTable(ctx, name, opts...)
 	if err != nil {
diff --git a/cmd/principal/bless.go b/cmd/principal/bless.go
index 3656853..23c237a 100644
--- a/cmd/principal/bless.go
+++ b/cmd/principal/bless.go
@@ -21,7 +21,7 @@
 )
 
 func exchangeMacaroonForBlessing(ctx *context.T, macaroonChan <-chan string) (security.Blessings, error) {
-	service, macaroon, rootKey, err := prepareBlessArgs(ctx, macaroonChan)
+	service, macaroon, serviceKey, err := prepareBlessArgs(ctx, macaroonChan)
 	if err != nil {
 		return security.Blessings{}, err
 	}
@@ -32,7 +32,7 @@
 	// Authorize the server by its public key (obtained from macaroonChan).
 	// Must skip authorization during name resolution because the identity
 	// service is not a trusted root yet.
-	blessings, err := identity.MacaroonBlesserClient(service).Bless(ctx, macaroon, options.SkipResolveAuthorization{}, options.ServerPublicKey{rootKey})
+	blessings, err := identity.MacaroonBlesserClient(service).Bless(ctx, macaroon, options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{serviceKey})
 	if err != nil {
 		return security.Blessings{}, fmt.Errorf("failed to get blessing from %q: %v", service, err)
 	}
diff --git a/cmd/principal/main.go b/cmd/principal/main.go
index d8076a0..3f18568 100644
--- a/cmd/principal/main.go
+++ b/cmd/principal/main.go
@@ -16,6 +16,7 @@
 
 	"v.io/v23"
 	"v.io/v23/context"
+	"v.io/v23/options"
 	"v.io/v23/rpc"
 	"v.io/v23/security"
 	"v.io/v23/vom"
@@ -914,7 +915,16 @@
 
 func sendBlessings(ctx *context.T, object string, granter *granter, remoteToken string) error {
 	client := v23.GetClient(ctx)
-	call, err := client.StartCall(ctx, object, "Grant", []interface{}{remoteToken}, granter)
+	// The receiver is being authorized based on the hash of its public key
+	// (see Grant), so it should be fine to ignore the blessing names in the endpoint
+	// (which are likely to not be recognized by the sender anyway).
+	//
+	// At worst, there is a privacy leak of the senders intent to send some
+	// blessings.  That could be addressed by making the full public key of
+	// the recipeint available to the sender and using
+	// options.ServerPublicKey instead of providing a "hash" of the
+	// recipients public key and verifying in the Granter implementation.
+	call, err := client.StartCall(ctx, object, "Grant", []interface{}{remoteToken}, granter, options.SkipServerEndpointAuthorization{})
 	if err != nil {
 		return fmt.Errorf("failed to start RPC to %q: %v", object, err)
 	}
diff --git a/cmd/vrpc/vrpc.go b/cmd/vrpc/vrpc.go
index c80d7a8..fddd97f 100644
--- a/cmd/vrpc/vrpc.go
+++ b/cmd/vrpc/vrpc.go
@@ -130,7 +130,10 @@
 	defer cancel()
 	var types vdlgen.NamedTypes
 	if method != "" {
-		methodSig, err := reserved.MethodSignature(ctx, server, method, options.SkipResolveAuthorization{})
+		// TODO(ashankar): Should not skip authorization, but instead
+		// authorize by default and provide a --insecure flag to skip
+		// it?
+		methodSig, err := reserved.MethodSignature(ctx, server, method, options.SkipServerEndpointAuthorization{})
 		if err != nil {
 			return fmt.Errorf("MethodSignature failed: %v", err)
 		}
@@ -139,7 +142,9 @@
 		types.Print(cmd.Stdout())
 		return nil
 	}
-	ifacesSig, err := reserved.Signature(ctx, server, options.SkipResolveAuthorization{})
+	// TODO(ashankar): Should not skip authorization, but instead authorize
+	// by default and provide a --insecure flag to skip it?
+	ifacesSig, err := reserved.Signature(ctx, server, options.SkipServerEndpointAuthorization{})
 	if err != nil {
 		return fmt.Errorf("Signature failed: %v", err)
 	}
diff --git a/examples/rps/rpsbot/impl_test.go b/examples/rps/rpsbot/impl_test.go
index 7ae1b0d..caa28fc 100644
--- a/examples/rps/rpsbot/impl_test.go
+++ b/examples/rps/rpsbot/impl_test.go
@@ -89,7 +89,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("Could not create shell: %v", err)
 	}
diff --git a/profiles/internal/naming/namespace/all_test.go b/profiles/internal/naming/namespace/all_test.go
index d10ece6..6ebfa7b 100644
--- a/profiles/internal/naming/namespace/all_test.go
+++ b/profiles/internal/naming/namespace/all_test.go
@@ -1,7 +1,7 @@
 package namespace_test
 
 import (
-	"reflect"
+	"fmt"
 	"runtime"
 	"runtime/debug"
 	"sync"
@@ -20,7 +20,6 @@
 
 	_ "v.io/x/ref/profiles"
 	"v.io/x/ref/profiles/internal/naming/namespace"
-	vsecurity "v.io/x/ref/security"
 	service "v.io/x/ref/services/mounttable/lib"
 	test "v.io/x/ref/test"
 	tsecurity "v.io/x/ref/test/security"
@@ -610,61 +609,17 @@
 	delegate.BlessingStore().SetDefault(b)
 }
 
-func TestRootBlessing(t *testing.T) {
-	c, cc, cleanup := createContexts(t)
-	defer cleanup()
-
-	proot, err := vsecurity.NewPrincipal()
-	if err != nil {
-		panic(err)
-	}
-	b, err := proot.BlessSelf("root")
-	if err != nil {
-		panic(err)
-	}
-	proot.BlessingStore().SetDefault(b)
-
-	sprincipal := v23.GetPrincipal(c)
-	cprincipal := v23.GetPrincipal(cc)
-	bless(proot, sprincipal, "server")
-	bless(proot, cprincipal, "client")
-	cprincipal.AddToRoots(proot.BlessingStore().Default())
-	sprincipal.AddToRoots(proot.BlessingStore().Default())
-
-	root, mts, _, stopper := createNamespace(t, c)
-	defer stopper()
-	ns := v23.GetNamespace(c)
-
-	name := naming.Join(root.name, mt2MP)
-	// First check with a non-matching blessing pattern.
-	_, err = ns.Resolve(c, name, naming.RootBlessingPatternOpt("root/foobar"))
-	if !verror.Is(err, verror.ErrNotTrusted.ID) {
-		t.Errorf("Resolve expected NotTrusted error, got %v", err)
-	}
-	_, err = ns.ResolveToMountTable(c, name, naming.RootBlessingPatternOpt("root/foobar"))
-	if !verror.Is(err, verror.ErrNotTrusted.ID) {
-		t.Errorf("ResolveToMountTable expected NotTrusted error, got %v", err)
-	}
-
-	// Now check a matching pattern.
-	testResolveWithPattern(t, c, ns, name, naming.RootBlessingPatternOpt("root/server"), mts[mt2MP].name)
-	testResolveToMountTableWithPattern(t, c, ns, name, naming.RootBlessingPatternOpt("root/server"), name)
-
-	// After successful lookup it should be cached, so the pattern doesn't matter.
-	testResolveWithPattern(t, c, ns, name, naming.RootBlessingPatternOpt("root/foobar"), mts[mt2MP].name)
-}
-
-func TestAuthenticationDuringResolve(t *testing.T) {
+func TestAuthorizationDuringResolve(t *testing.T) {
 	ctx, shutdown := v23.Init()
 	defer shutdown()
 
 	var (
-		rootMtCtx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // root mounttable
-		mtCtx, _     = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // intermediate mounttable
-		serverCtx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // end server
-		clientCtx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // client process (doing Resolves).
-		idp          = tsecurity.NewIDProvider("idp")                  // identity provider
-		ep1          = naming.FormatEndpoint("tcp", "127.0.0.1:14141")
+		rootMtCtx, _   = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // root mounttable
+		mtCtx, _       = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // intermediate mounttable
+		serverCtx, _   = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // end server
+		clientCtx, _   = v23.SetPrincipal(ctx, tsecurity.NewPrincipal()) // client process (doing Resolves).
+		idp            = tsecurity.NewIDProvider("idp")                  // identity provider
+		serverEndpoint = naming.FormatEndpoint("tcp", "127.0.0.1:14141")
 
 		resolve = func(name string, opts ...naming.ResolveOpt) (*naming.MountEntry, error) {
 			return v23.GetNamespace(clientCtx).Resolve(clientCtx, name, opts...)
@@ -689,47 +644,51 @@
 	// are noticed immediately.
 	v23.GetNamespace(clientCtx).CacheCtl(naming.DisableCache(true))
 
-	// Server mounting without an explicitly specified MountedServerBlessingsOpt,
-	// will automatically fill the Default blessings in.
-	if err := mount("server", ep1, time.Minute); err != nil {
-		t.Error(err)
-	} else if e, err := resolve("server"); err != nil {
-		t.Error(err)
-	} else if len(e.Servers) != 1 {
-		t.Errorf("Got %v, wanted a single server", e.Servers)
-	} else if s := e.Servers[0]; s.Server != ep1 || len(s.BlessingPatterns) != 1 || s.BlessingPatterns[0] != "idp/server" {
-		t.Errorf("Got (%q, %v) want (%q, [%q])", s.Server, s.BlessingPatterns, ep1, "idp/server")
-	} else if e, err = resolve("__(otherpattern)/server"); err != nil {
-		// Resolving with the "__(<pattern>)/<OA>" syntax, then <pattern> wins.
-		t.Error(err)
-	} else if s = e.Servers[0]; s.Server != ep1 || len(s.BlessingPatterns) != 1 || s.BlessingPatterns[0] != "otherpattern" {
-		t.Errorf("Got (%q, %v) want (%q, [%q])", s.Server, s.BlessingPatterns, ep1, "otherpattern")
-	}
-	// If an option is explicitly specified, it should be respected.
-	if err := mount("server", ep1, time.Minute, naming.ReplaceMountOpt(true), naming.MountedServerBlessingsOpt{"b1", "b2"}); err != nil {
-		t.Error(err)
-	} else if e, err := resolve("server"); err != nil {
-		t.Error(err)
-	} else if len(e.Servers) != 1 {
-		t.Errorf("Got %v, wanted a single server", e.Servers)
-	} else if s, pats := e.Servers[0], []string{"b1", "b2"}; s.Server != ep1 || !reflect.DeepEqual(s.BlessingPatterns, pats) {
-		t.Errorf("Got (%q, %v) want (%q, %v)", s.Server, s.BlessingPatterns, ep1, pats)
-	}
-
 	// Intermediate mounttables should be authenticated.
 	mt := runMT(t, mtCtx, "mt")
 	// Mount a server on "mt".
-	if err := mount("mt/server", ep1, time.Minute, naming.ReplaceMountOpt(true)); err != nil {
+	if err := mount("mt/server", serverEndpoint, time.Minute, naming.ReplaceMountOpt(true)); err != nil {
 		t.Error(err)
 	}
-	// Imagine that the network address of "mt" has been taken over by an attacker. However, this attacker cannot
-	// mess with the mount entry for "mt". This would result in "mt" and its mount entry (in the global mounttable)
-	// having inconsistent blessings. Simulate this by explicitly changing the mount entry for "mt".
-	if err := v23.GetNamespace(mtCtx).Mount(mtCtx, "mt", mt.name, time.Minute, naming.ServesMountTableOpt(true), naming.MountedServerBlessingsOpt{"realmounttable"}, naming.ReplaceMountOpt(true)); err != nil {
+	// The namespace root should be authenticated too
+	if e, err := resolve("mt/server"); err != nil {
+		t.Errorf("Got (%v, %v)", e, err)
+	} else {
+		// Host:Port and Endpoint versions of the other namespace root
+		// (which has different blessings)
+		hproot := fmt.Sprintf("(otherroot)@%v", rootmt.endpoint.Addr())
+		eproot := naming.FormatEndpoint(rootmt.endpoint.Addr().Network(), rootmt.endpoint.Addr().String(), rootmt.endpoint.RoutingID(), naming.BlessingOpt("otherroot"), naming.ServesMountTableOpt(rootmt.endpoint.ServesMountTable()))
+		for _, root := range []string{hproot, eproot} {
+			name := naming.JoinAddressName(root, "mt")
+			// Rooted name resolutions should fail authorization because of the "otherrot"
+			if e, err := resolve(name); !verror.Is(err, verror.ErrNotTrusted.ID) {
+				t.Errorf("resolve(%q) returned (%v, errorid=%v %v), wanted errorid=%v", name, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID)
+			}
+			// But not fail if the skip-authorization option is provided
+			if e, err := resolve(name, options.SkipServerEndpointAuthorization{}); err != nil {
+				t.Errorf("resolve(%q): Got (%v, %v), expected resolution to succeed", name, e, err)
+			}
+			// The namespace root from the context should be authorized as well.
+			ctx, ns, _ := v23.SetNewNamespace(clientCtx, naming.JoinAddressName(root, ""))
+			if e, err := ns.Resolve(ctx, "mt/server"); !verror.Is(err, verror.ErrNotTrusted.ID) {
+				t.Errorf("resolve with root=%q returned (%v, errorid=%v %v), wanted errorid=%v", root, e, verror.ErrorID(err), err, verror.ErrNotTrusted.ID)
+			}
+			if _, err := ns.Resolve(ctx, "mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
+				t.Errorf("resolve with root=%q should have succeeded when authorization checks are skipped. Got %v", err)
+			}
+		}
+	}
+	// Imagine that the network address of "mt" has been taken over by an
+	// attacker. However, this attacker cannot mess with the mount entry
+	// for "mt". This would result in "mt" and its mount entry (in the
+	// global mounttable) having inconsistent blessings. Simulate this by
+	// explicitly changing the mount entry for "mt".
+	goodChildMTEndpoint := naming.FormatEndpoint(mt.endpoint.Addr().Network(), mt.endpoint.Addr().String(), naming.BlessingOpt("idp/goodchildmt"), mt.endpoint.RoutingID())
+	if err := v23.GetNamespace(mtCtx).Mount(mtCtx, "mt", goodChildMTEndpoint, time.Minute, naming.ServesMountTableOpt(true), naming.ReplaceMountOpt(true)); err != nil {
 		t.Error(err)
 	}
 
-	if e, err := resolve("mt/server", options.SkipResolveAuthorization{}); err != nil {
+	if e, err := resolve("mt/server", options.SkipServerEndpointAuthorization{}); err != nil {
 		t.Errorf("Resolve should succeed when skipping server authorization. Got (%v, %v)", e, err)
 	} else if e, err := resolve("mt/server"); !verror.Is(err, verror.ErrNotTrusted.ID) {
 		t.Errorf("Resolve should have failed with %q because an attacker has taken over the intermediate mounttable. Got (%+v, errorid=%q:%v)", verror.ErrNotTrusted.ID, e, verror.ErrorID(err), err)
diff --git a/profiles/internal/naming/namespace/namespace.go b/profiles/internal/naming/namespace/namespace.go
index 5862908..24fd1c6 100644
--- a/profiles/internal/naming/namespace/namespace.go
+++ b/profiles/internal/naming/namespace/namespace.go
@@ -137,7 +137,6 @@
 		ns.RLock()
 		defer ns.RUnlock()
 		for _, r := range ns.roots {
-			// TODO(ashankar): Configured namespace roots should also include the pattern?
 			server := naming.MountedServer{Server: r, Deadline: deadline}
 			if len(mtPattern) > 0 {
 				server.BlessingPatterns = []string{mtPattern}
diff --git a/profiles/internal/naming/namespace/resolve.go b/profiles/internal/naming/namespace/resolve.go
index adb8060..0a09964 100644
--- a/profiles/internal/naming/namespace/resolve.go
+++ b/profiles/internal/naming/namespace/resolve.go
@@ -17,7 +17,6 @@
 func (ns *namespace) resolveAgainstMountTable(ctx *context.T, client rpc.Client, e *naming.MountEntry, opts ...rpc.CallOpt) (*naming.MountEntry, error) {
 	// Try each server till one answers.
 	finalErr := errors.New("no servers to resolve query")
-	skipServerAuth := skipServerAuthorization(opts)
 	opts = append(opts, options.NoResolve{})
 	for _, s := range e.Servers {
 		name := naming.JoinAddressName(s.Server, e.Name)
@@ -27,9 +26,6 @@
 			return &ne, nil
 		}
 		// Not in cache, call the real server.
-		if !skipServerAuth {
-			opts = setAllowedServers(opts, s.BlessingPatterns)
-		}
 		callCtx, _ := context.WithTimeout(ctx, callTimeout)
 		call, err := client.StartCall(callCtx, name, "ResolveStep", nil, opts...)
 		if err != nil {
@@ -213,23 +209,3 @@
 		e.Servers[idx].BlessingPatterns = slice
 	}
 }
-
-func setAllowedServers(opts []rpc.CallOpt, patterns []string) []rpc.CallOpt {
-	if len(patterns) == 0 {
-		return opts
-	}
-	p := make(options.AllowedServersPolicy, len(patterns))
-	for i, v := range patterns {
-		p[i] = security.BlessingPattern(v)
-	}
-	return append(opts, p)
-}
-
-func skipServerAuthorization(opts []rpc.CallOpt) bool {
-	for _, o := range opts {
-		if _, ok := o.(options.SkipResolveAuthorization); ok {
-			return true
-		}
-	}
-	return false
-}
diff --git a/profiles/internal/rpc/cancel_test.go b/profiles/internal/rpc/cancel_test.go
index 3f4a5b7..38c3ea6 100644
--- a/profiles/internal/rpc/cancel_test.go
+++ b/profiles/internal/rpc/cancel_test.go
@@ -86,29 +86,32 @@
 func TestCancellationPropagation(t *testing.T) {
 	ctx, shutdown := initForTest()
 	defer shutdown()
-
-	sm := manager.InternalNew(naming.FixedRoutingID(0x555555555))
-	ns := tnaming.NewSimpleNamespace()
-
+	var (
+		sm               = manager.InternalNew(naming.FixedRoutingID(0x555555555))
+		ns               = tnaming.NewSimpleNamespace()
+		pclient, pserver = newClientServerPrincipals()
+		serverCtx, _     = v23.SetPrincipal(ctx, pserver)
+		clientCtx, _     = v23.SetPrincipal(ctx, pclient)
+	)
 	client, err := InternalNewClient(sm, ns)
 	if err != nil {
 		t.Error(err)
 	}
 
-	c1, err := makeCanceld(ctx, ns, "c1", "c2")
+	c1, err := makeCanceld(serverCtx, ns, "c1", "c2")
 	if err != nil {
 		t.Fatal("Can't start server:", err)
 	}
 	defer c1.stop()
 
-	c2, err := makeCanceld(ctx, ns, "c2", "")
+	c2, err := makeCanceld(serverCtx, ns, "c2", "")
 	if err != nil {
 		t.Fatal("Can't start server:", err)
 	}
 	defer c2.stop()
 
-	ctx, cancel := context.WithCancel(ctx)
-	_, err = client.StartCall(ctx, "c1", "Run", []interface{}{})
+	clientCtx, cancel := context.WithCancel(clientCtx)
+	_, err = client.StartCall(clientCtx, "c1", "Run", []interface{}{})
 	if err != nil {
 		t.Fatal("can't call: ", err)
 	}
diff --git a/profiles/internal/rpc/client.go b/profiles/internal/rpc/client.go
index 84e8166..961c076 100644
--- a/profiles/internal/rpc/client.go
+++ b/profiles/internal/rpc/client.go
@@ -78,8 +78,6 @@
 
 	errNoBlessingsForPeer = verror.Register(pkgPath+".noBlessingsForPeer", verror.NoRetry, "no blessings tagged for peer {3}{:4}")
 
-	errDefaultAuthDenied = verror.Register(pkgPath+".defaultAuthDenied", verror.NoRetry, "default authorization precludes talking to server with blessings{:3}")
-
 	errBlessingGrant = verror.Register(pkgPath+".blessingGrantFailed", verror.NoRetry, "failed to grant blessing to server with blessings {3}{:4}")
 
 	errBlessingAdd = verror.Register(pkgPath+".blessingAddFailed", verror.NoRetry, "failed to add blessing granted to server {3}{:4}")
@@ -387,6 +385,8 @@
 func (c *client) tryCall(ctx *context.T, name, method string, args []interface{}, opts []rpc.CallOpt) (rpc.ClientCall, verror.ActionCode, error) {
 	var resolved *naming.MountEntry
 	var err error
+	var blessingPattern security.BlessingPattern
+	blessingPattern, name = security.SplitPatternName(name)
 	if resolved, err = c.ns.Resolve(ctx, name, getResolveOpts(opts)...); err != nil {
 		vlog.Errorf("Resolve: %v", err)
 		// We always return NoServers as the error so that the caller knows
@@ -420,10 +420,14 @@
 	responses := make([]*serverStatus, attempts)
 	ch := make(chan *serverStatus, attempts)
 	vcOpts := append(getVCOpts(opts), c.vcOpts...)
+	authorizer := newServerAuthorizer(blessingPattern, opts...)
 	for i, server := range resolved.Names() {
+		// Create a copy of vcOpts for each call to tryCreateFlow
+		// to avoid concurrent tryCreateFlows from stepping on each
+		// other while manipulating their copy of the options.
 		vcOptsCopy := make([]stream.VCOpt, len(vcOpts))
 		copy(vcOptsCopy, vcOpts)
-		go c.tryCreateFlow(ctx, i, name, server, method, newServerAuthorizer(ctx, bpatterns(resolved.Servers[i].BlessingPatterns), opts...), ch, vcOptsCopy)
+		go c.tryCreateFlow(ctx, i, name, server, method, authorizer, ch, vcOptsCopy)
 	}
 
 	var timeoutChan <-chan time.Time
diff --git a/profiles/internal/rpc/full_test.go b/profiles/internal/rpc/full_test.go
index bd5f0fe..46e3aad 100644
--- a/profiles/internal/rpc/full_test.go
+++ b/profiles/internal/rpc/full_test.go
@@ -233,6 +233,7 @@
 
 func startServerWS(t *testing.T, ctx *context.T, principal security.Principal, sm stream.Manager, ns ns.Namespace, name string, disp rpc.Dispatcher, shouldUseWebsocket websocketMode, opts ...rpc.ServerOpt) (naming.Endpoint, rpc.Server) {
 	vlog.VI(1).Info("InternalNewServer")
+	ctx, _ = v23.SetPrincipal(ctx, principal)
 	server, err := testInternalNewServer(ctx, sm, ns, principal, opts...)
 	if err != nil {
 		t.Errorf("InternalNewServer failed: %v", err)
@@ -457,14 +458,18 @@
 }
 
 func TestRPCServerAuthorization(t *testing.T) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
+
 	const (
-		publicKeyErr = "not matched by server key"
-		forPeerErr   = "no blessings tagged for peer"
-		nameErr      = "do not match pattern"
-		allowedErr   = "do not match any allowed server patterns"
+		publicKeyErr        = "not matched by server key"
+		missingDischargeErr = "missing discharge"
+		expiryErr           = "is after expiry"
+		allowedErr          = "do not match any allowed server patterns"
 	)
+	type O []rpc.CallOpt // shorthand
 	var (
-		pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal("server")
+		pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal()
 		pdischarger                 = pprovider
 		now                         = time.Now()
 		noErrID                     verror.IDAction
@@ -475,65 +480,47 @@
 
 		// Server blessings.
 		bServer          = bless(pprovider, pserver, "server")
-		bServerExpired   = bless(pprovider, pserver, "server", mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Second))))
+		bServerExpired   = bless(pprovider, pserver, "expiredserver", mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Second))))
 		bServerTPValid   = bless(pprovider, pserver, "serverWithTPCaveats", cavTPValid)
-		bServerTPExpired = bless(pprovider, pserver, "serverWithTPCaveats", cavTPExpired)
-		bTwoBlessings, _ = security.UnionOfBlessings(bServer, bServerTPValid)
+		bServerTPExpired = bless(pprovider, pserver, "serverWithExpiredTPCaveats", cavTPExpired)
+		bOther           = bless(pprovider, pserver, "other")
+		bTwoBlessings, _ = security.UnionOfBlessings(bServer, bOther)
 
 		mgr   = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
 		ns    = tnaming.NewSimpleNamespace()
 		tests = []struct {
 			server security.Blessings // blessings presented by the server to the client.
 			name   string             // name provided by the client to StartCall
-			opt    rpc.CallOpt        // option provided to StartCall.
+			opts   O                  // options provided to StartCall.
 			errID  verror.IDAction
 			err    string
 		}{
 			// Client accepts talking to the server only if the
-			// server's blessings match the provided pattern
-			{bServer, "__(...)/mountpoint/server", nil, noErrID, ""},
-			{bServer, "__(root/server)/mountpoint/server", nil, noErrID, ""},
-			{bServer, "__(root/otherserver)/mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
-			{bServer, "__(otherroot/server)/mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
+			// server presents valid blessings (and discharges)
+			// consistent with the ones published in the endpoint.
+			{bServer, "mountpoint/server", nil, noErrID, ""},
+			{bServerTPValid, "mountpoint/server", nil, noErrID, ""},
 
-			// and, if the server's blessing has third-party
-			// caveats then the server provides appropriate
-			// discharges.
-			{bServerTPValid, "__(...)/mountpoint/server", nil, noErrID, ""},
-			{bServerTPValid, "__(root/serverWithTPCaveats)/mountpoint/server", nil, noErrID, ""},
-			{bServerTPValid, "__(root/otherserver)/mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
-			{bServerTPValid, "__(otherroot/server)/mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
-
-			// Client does not talk to a server that presents
-			// expired blessings (because the blessing store is
-			// configured to only talk to root).
-			{bServerExpired, "__(...)/mountpoint/server", nil, verror.ErrNotTrusted, forPeerErr},
-
-			// Client does not talk to a server that fails to
-			// provide discharges for third-party caveats on the
-			// blessings presented by it.
-			{bServerTPExpired, "__(...)/mountpoint/server", nil, verror.ErrNotTrusted, forPeerErr},
+			// Client will not talk to a server that presents
+			// expired blessings or is missing discharges.
+			{bServerExpired, "mountpoint/server", nil, verror.ErrNotTrusted, expiryErr},
+			{bServerTPExpired, "mountpoint/server", nil, verror.ErrNotTrusted, missingDischargeErr},
 
 			// Testing the AllowedServersPolicy option.
-			{bServer, "__(...)/mountpoint/server", options.AllowedServersPolicy{"otherroot"}, verror.ErrNotTrusted, allowedErr},
-			{bServer, "__(root/server)/mountpoint/server", options.AllowedServersPolicy{"otherroot"}, verror.ErrNotTrusted, allowedErr},
-			{bServer, "__(otherroot/server)/mountpoint/server", options.AllowedServersPolicy{"root/server"}, verror.ErrNotTrusted, nameErr},
-			{bServer, "__(root/server)/mountpoint/server", options.AllowedServersPolicy{"root"}, noErrID, ""},
+			{bServer, "mountpoint/server", O{options.AllowedServersPolicy{"otherroot"}}, verror.ErrNotTrusted, allowedErr},
+			{bServer, "mountpoint/server", O{options.AllowedServersPolicy{"root"}}, noErrID, ""},
+			{bTwoBlessings, "mountpoint/server", O{options.AllowedServersPolicy{"root/other"}}, noErrID, ""},
 
 			// Test the ServerPublicKey option.
-			{bServer, "__(...)/mountpoint/server", options.ServerPublicKey{bServer.PublicKey()}, noErrID, ""},
-			{bServer, "__(...)/mountpoint/server", options.ServerPublicKey{tsecurity.NewPrincipal("irrelevant").PublicKey()}, verror.ErrNotTrusted, publicKeyErr},
-			// Server presents two blessings: One that satisfies
-			// the pattern provided to StartCall and one that
-			// satisfies the AllowedServersPolicy, so the server is
-			// authorized.
-			{bTwoBlessings, "__(root/serverWithTPCaveats)/mountpoint/server", options.AllowedServersPolicy{"root/server"}, noErrID, ""},
+			{bOther, "mountpoint/server", O{options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{bOther.PublicKey()}}, noErrID, ""},
+			{bOther, "mountpoint/server", O{options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{tsecurity.NewPrincipal("irrelevant").PublicKey()}}, verror.ErrNotTrusted, publicKeyErr},
+
+			// Test the "paranoid" names, where the pattern is provided in the name.
+			{bServer, "__(root/server)/mountpoint/server", nil, noErrID, ""},
+			{bServer, "__(root/other)/mountpoint/server", nil, verror.ErrNotTrusted, allowedErr},
+			{bTwoBlessings, "__(root/server)/mountpoint/server", O{options.AllowedServersPolicy{"root/other"}}, noErrID, ""},
 		}
 	)
-
-	ctx, shutdown := initForTest()
-	defer shutdown()
-
 	// Start the discharge server.
 	_, dischargeServer := startServer(t, ctx, pdischarger, mgr, ns, "mountpoint/dischargeserver", testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
 	defer stopServer(t, ctx, dischargeServer, ns, "mountpoint/dischargeserver")
@@ -542,28 +529,36 @@
 	// pprovider
 	pclient.AddToRoots(pprovider.BlessingStore().Default())
 	pserver.AddToRoots(pprovider.BlessingStore().Default())
-	// Set a blessing that the client is willing to share with servers with
-	// blessings from pprovider.
+	// Set a blessing that the client is willing to share with servers
+	// (that are blessed by pprovider).
 	pclient.BlessingStore().Set(bless(pprovider, pclient, "client"), "root")
 
+	clientCtx, _ := v23.SetPrincipal(ctx, pclient)
+	client, err := InternalNewClient(mgr, ns)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer client.Close()
+
+	var server rpc.Server
+	stop := func() {
+		if server != nil {
+			stopServer(t, ctx, server, ns, "mountpoint/server")
+		}
+	}
+	defer stop()
 	for i, test := range tests {
-		name := fmt.Sprintf("(#%d: Name:%q, Server:%q, opt:%v)", i, test.name, test.server, test.opt)
+		stop() // Stop any server started in the previous test.
+		name := fmt.Sprintf("(#%d: Name:%q, Server:%q, opts:%v)", i, test.name, test.server, test.opts)
 		if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
 			t.Fatalf("SetDefault failed on server's BlessingStore: %v", err)
 		}
 		if _, err := pserver.BlessingStore().Set(test.server, "root"); err != nil {
 			t.Fatalf("Set failed on server's BlessingStore: %v", err)
 		}
-		_, server := startServer(t, ctx, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
-		// Recreate client in each test (so as to not re-use VCs to the server).
-		client, err := InternalNewClient(mgr, ns)
-		if err != nil {
-			t.Errorf("%s: failed to create client: %v", name, err)
-			continue
-		}
-		ctx, _ = v23.SetPrincipal(ctx, pclient)
-		ctx, cancel := context.WithCancel(ctx)
-		call, err := client.StartCall(ctx, test.name, "Method", nil, test.opt)
+		_, server = startServer(t, ctx, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
+		clientCtx, cancel := context.WithCancel(clientCtx)
+		call, err := client.StartCall(clientCtx, test.name, "Method", nil, test.opts...)
 		if !matchesErrorPattern(err, test.errID, test.err) {
 			t.Errorf(`%s: client.StartCall: got error "%v", want to match "%v"`, name, err, test.err)
 		} else if call != nil {
@@ -580,16 +575,25 @@
 			}
 		}
 		cancel()
-		client.Close()
-		stopServer(t, ctx, server, ns, "mountpoint/server")
 	}
 }
 
 func TestServerManInTheMiddleAttack(t *testing.T) {
-	// Test scenario: A server mounts itself, but then some other service
-	// somehow "takes over" the endpoint, thus trying to steal traffic.
 	ctx, shutdown := initForTest()
 	defer shutdown()
+	// Test scenario: A server mounts itself, but then some other service
+	// somehow "takes over" the network endpoint (a naughty router
+	// perhaps), thus trying to steal traffic.
+	var (
+		pclient   = tsecurity.NewPrincipal("client")
+		pserver   = tsecurity.NewPrincipal("server")
+		pattacker = tsecurity.NewPrincipal("attacker")
+	)
+	// Client recognizes both the server and the attacker's blessings.
+	// (Though, it doesn't need to do the latter for the purposes of this
+	// test).
+	pclient.AddToRoots(pserver.BlessingStore().Default())
+	pclient.AddToRoots(pattacker.BlessingStore().Default())
 
 	// Start up the attacker's server.
 	attacker, err := testInternalNewServer(
@@ -599,7 +603,7 @@
 		// namespace that the client will use, provide it with a
 		// different namespace).
 		tnaming.NewSimpleNamespace(),
-		tsecurity.NewPrincipal("attacker"))
+		pattacker)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -617,9 +621,10 @@
 	}
 
 	// The legitimate server would have mounted the same endpoint on the
-	// namespace.
+	// namespace, but with different blessings.
 	ns := tnaming.NewSimpleNamespace()
-	if err := ns.Mount(ctx, "mountpoint/server", ep.Name(), time.Hour, naming.MountedServerBlessingsOpt{"server"}); err != nil {
+	ep.(*inaming.Endpoint).Blessings = []string{"server"}
+	if err := ns.Mount(ctx, "mountpoint/server", ep.Name(), time.Hour); err != nil {
 		t.Fatal(err)
 	}
 
@@ -628,19 +633,18 @@
 	// the mounttable trusted by the client.
 	client, err := InternalNewClient(
 		imanager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc)),
-		ns,
-	)
+		ns)
 	if err != nil {
 		t.Fatal(err)
 	}
 	defer client.Close()
-	ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("client"))
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	if _, err := client.StartCall(ctx, "mountpoint/server", "Closure", nil); !verror.Is(err, verror.ErrNotTrusted.ID) {
 		t.Errorf("Got error %v (errorid=%v), want errorid=%v", err, verror.ErrorID(err), verror.ErrNotTrusted.ID)
 	}
 	// But the RPC should succeed if the client explicitly
 	// decided to skip server authorization.
-	if _, err := client.StartCall(ctx, "mountpoint/server", "Closure", nil, options.SkipResolveAuthorization{}); err != nil {
+	if _, err := client.StartCall(ctx, "mountpoint/server", "Closure", nil, options.SkipServerEndpointAuthorization{}); err != nil {
 		t.Errorf("Unexpected error(%v) when skipping server authorization", err)
 	}
 }
@@ -675,6 +679,8 @@
 }
 
 func testRPC(t *testing.T, shouldCloseSend closeSendMode, shouldUseWebsocket websocketMode) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
 	type v []interface{}
 	type testcase struct {
 		name       string
@@ -705,18 +711,11 @@
 			return fmt.Sprintf("%s.%s(%v)", t.name, t.method, t.args)
 		}
 
-		pserver = tsecurity.NewPrincipal("server")
-		pclient = tsecurity.NewPrincipal("client")
-
-		ctx, shutdown = initForTest()
-
-		b = createBundleWS(t, ctx, pserver, &testServer{}, shouldUseWebsocket)
+		pclient, pserver = newClientServerPrincipals()
+		b                = createBundleWS(t, ctx, pserver, &testServer{}, shouldUseWebsocket)
 	)
-	defer shutdown()
 	defer b.cleanup(t, ctx)
 	ctx, _ = v23.SetPrincipal(ctx, pclient)
-	// The server needs to recognize the client's root certificate.
-	pserver.AddToRoots(pclient.BlessingStore().Default())
 	for _, test := range tests {
 		vlog.VI(1).Infof("%s client.StartCall", name(test))
 		vname := test.name
@@ -778,9 +777,12 @@
 	ctx, shutdown := initForTest()
 	defer shutdown()
 	type v []interface{}
-	b := createBundle(t, ctx, tsecurity.NewPrincipal("server"), &testServer{})
+	var (
+		pclient, pserver = newClientServerPrincipals()
+		b                = createBundle(t, ctx, pserver, &testServer{})
+	)
 	defer b.cleanup(t, ctx)
-	ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("client"))
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "Echo", v{"foo"})
 	if err != nil {
 		t.Fatalf(`client.StartCall got error "%v"`, err)
@@ -807,16 +809,14 @@
 
 func TestGranter(t *testing.T) {
 	var (
-		pclient       = tsecurity.NewPrincipal("client")
-		pserver       = tsecurity.NewPrincipal("server")
-		ctx, shutdown = initForTest()
-		b             = createBundle(t, ctx, pserver, &testServer{})
+		pclient, pserver = newClientServerPrincipals()
+		ctx, shutdown    = initForTest()
+		b                = createBundle(t, ctx, pserver, &testServer{})
 	)
 	defer shutdown()
 	defer b.cleanup(t, ctx)
 
 	ctx, _ = v23.SetPrincipal(ctx, pclient)
-
 	tests := []struct {
 		granter                       rpc.Granter
 		startErrID, finishErrID       verror.IDAction
@@ -869,6 +869,8 @@
 }
 
 func TestDischargeImpetusAndContextPropagation(t *testing.T) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
 	var (
 		pserver     = tsecurity.NewPrincipal("server")
 		pdischarger = tsecurity.NewPrincipal("discharger")
@@ -876,8 +878,8 @@
 		sm          = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 		ns          = tnaming.NewSimpleNamespace()
 
-		mkClient = func(req security.ThirdPartyRequirements) security.Principal {
-			// Setup the client so that it shares a blessing with a third-party caveat with the server.
+		// Setup the client so that it shares a blessing with a third-party caveat with the server.
+		setClientBlessings = func(req security.ThirdPartyRequirements) security.Principal {
 			cav, err := security.NewPublicKeyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", req, security.UnconstrainedUse())
 			if err != nil {
 				t.Fatalf("Failed to create ThirdPartyCaveat(%+v): %v", req, err)
@@ -890,21 +892,10 @@
 			return pclient
 		}
 	)
-	ctx, shutdown := initForTest()
-	defer shutdown()
 	// Initialize the client principal.
 	// It trusts both the application server and the discharger.
 	pclient.AddToRoots(pserver.BlessingStore().Default())
 	pclient.AddToRoots(pdischarger.BlessingStore().Default())
-	// Share a blessing without any third-party caveats with the discharger.
-	// It could share the same blessing as generated by setupClientBlessing, but
-	// that will lead to possibly debugging confusion (since it will try to fetch
-	// a discharge to talk to the discharge service).
-	if b, err := pclient.BlessSelf("client_for_discharger"); err != nil {
-		t.Fatalf("BlessSelf failed: %v", err)
-	} else {
-		pclient.BlessingStore().Set(b, "discharger")
-	}
 
 	// Setup the discharge server.
 	var tester dischargeTestServer
@@ -968,7 +959,7 @@
 	}
 
 	for _, test := range tests {
-		pclient := mkClient(test.Requirements)
+		pclient := setClientBlessings(test.Requirements)
 		ctx, _ = v23.SetPrincipal(ctx, pclient)
 		client, err := InternalNewClient(sm, ns)
 		if err != nil {
@@ -1149,72 +1140,70 @@
 	}
 }
 
-// maliciousBlessingStore implements security.BlessingStore. It is a
+// singleBlessingStore implements security.BlessingStore. It is a
 // BlessingStore that marks the last blessing that was set on it as
 // shareable with any peer. It does not care about the public key that
 // blessing being set is bound to.
-type maliciousBlessingStore struct {
+type singleBlessingStore struct {
 	b security.Blessings
 }
 
-func (s *maliciousBlessingStore) Set(b security.Blessings, _ security.BlessingPattern) (security.Blessings, error) {
+func (s *singleBlessingStore) Set(b security.Blessings, _ security.BlessingPattern) (security.Blessings, error) {
 	s.b = b
 	return security.Blessings{}, nil
 }
-func (s *maliciousBlessingStore) ForPeer(...string) security.Blessings {
+func (s *singleBlessingStore) ForPeer(...string) security.Blessings {
 	return s.b
 }
-func (*maliciousBlessingStore) SetDefault(b security.Blessings) error {
+func (*singleBlessingStore) SetDefault(b security.Blessings) error {
 	return nil
 }
-func (*maliciousBlessingStore) Default() security.Blessings {
+func (*singleBlessingStore) Default() security.Blessings {
 	return security.Blessings{}
 }
-func (*maliciousBlessingStore) PublicKey() security.PublicKey {
+func (*singleBlessingStore) PublicKey() security.PublicKey {
 	return nil
 }
-func (*maliciousBlessingStore) DebugString() string {
+func (*singleBlessingStore) DebugString() string {
 	return ""
 }
-func (*maliciousBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
+func (*singleBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
 	return nil
 }
 
-// maliciousPrincipal implements security.Principal. It is a wrapper over
+// singleBlessingPrincipal implements security.Principal. It is a wrapper over
 // a security.Principal that intercepts  all invocations on the
-// principal's BlessingStore and serves them via a maliciousBlessingStore.
-type maliciousPrincipal struct {
+// principal's BlessingStore and serves them via a singleBlessingStore.
+type singleBlessingPrincipal struct {
 	security.Principal
-	b maliciousBlessingStore
+	b singleBlessingStore
 }
 
-func (p *maliciousPrincipal) BlessingStore() security.BlessingStore {
+func (p *singleBlessingPrincipal) BlessingStore() security.BlessingStore {
 	return &p.b
 }
 
 func TestRPCClientBlessingsPublicKey(t *testing.T) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
 	var (
 		pprovider, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal("server")
-		pclient            = &maliciousPrincipal{Principal: tsecurity.NewPrincipal("client")}
+		pclient            = &singleBlessingPrincipal{Principal: tsecurity.NewPrincipal("client")}
 
 		bserver = bless(pprovider, pserver, "server")
 		bclient = bless(pprovider, pclient, "client")
 		bvictim = bless(pprovider, tsecurity.NewPrincipal("victim"), "victim")
-
-		ctx, shutdown = initForTest()
-		b             = createBundle(t, ctx, pserver, &testServer{})
 	)
-	defer shutdown()
-	defer b.cleanup(t, ctx)
-
-	ctx, _ = v23.SetPrincipal(ctx, pclient)
-
 	// Make the client and server trust blessings from pprovider.
 	pclient.AddToRoots(pprovider.BlessingStore().Default())
 	pserver.AddToRoots(pprovider.BlessingStore().Default())
 
-	// Make the server present bserver to all clients.
+	// Make the server present bserver to all clients and start the server.
 	pserver.BlessingStore().SetDefault(bserver)
+	b := createBundle(t, ctx, pserver, &testServer{})
+	defer b.cleanup(t, ctx)
+
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	tests := []struct {
 		blessings security.Blessings
 		errID     verror.IDAction
@@ -1224,14 +1213,11 @@
 		// server disallows clients from authenticating with blessings not bound to
 		// the client principal's public key
 		{blessings: bvictim, errID: verror.ErrNoAccess, err: "bound to a different public key"},
-		// or authenticating with the server's blessings
 		{blessings: bserver, errID: verror.ErrNoAccess, err: "bound to a different public key"},
 	}
 	for i, test := range tests {
 		name := fmt.Sprintf("%d: Client RPCing with blessings %v", i, test.blessings)
-
 		pclient.BlessingStore().Set(test.blessings, "root")
-
 		call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "Closure", nil)
 		if err != nil {
 			t.Errorf("%v: StartCall failed: %v", name, err)
@@ -1245,8 +1231,10 @@
 }
 
 func TestServerLocalBlessings(t *testing.T) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
 	var (
-		pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal()
+		pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server")
 		pdischarger                 = pprovider
 
 		mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
@@ -1257,10 +1245,6 @@
 		bserver = bless(pprovider, pserver, "server", tpCav)
 		bclient = bless(pprovider, pclient, "client")
 	)
-
-	ctx, shutdown := initForTest()
-	defer shutdown()
-
 	// Make the client and server principals trust root certificates from
 	// pprovider.
 	pclient.AddToRoots(pprovider.BlessingStore().Default())
@@ -1279,7 +1263,6 @@
 	// Make the client present bclient to all servers that are blessed
 	// by pprovider.
 	pclient.BlessingStore().Set(bclient, "root")
-
 	client, err := InternalNewClient(mgr, ns)
 	if err != nil {
 		t.Fatalf("InternalNewClient failed: %v", err)
@@ -1303,6 +1286,9 @@
 }
 
 func TestDischargePurgeFromCache(t *testing.T) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
+
 	var (
 		pserver     = tsecurity.NewPrincipal("server")
 		pdischarger = pserver // In general, the discharger can be a separate principal. In this test, it happens to be the server.
@@ -1310,17 +1296,14 @@
 		// Client is blessed with a third-party caveat. The discharger service issues discharges with a fakeTimeCaveat.
 		// This blessing is presented to "server".
 		bclient = bless(pserver, pclient, "client", mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/server/discharger", security.UnconstrainedUse()))
+
+		b = createBundle(t, ctx, pserver, &testServer{})
 	)
+	defer b.cleanup(t, ctx)
 	// Setup the client to recognize the server's blessing and present bclient to it.
 	pclient.AddToRoots(pserver.BlessingStore().Default())
 	pclient.BlessingStore().Set(bclient, "server")
 
-	ctx, shutdown := initForTest()
-	defer shutdown()
-
-	b := createBundle(t, ctx, pserver, &testServer{})
-	defer b.cleanup(t, ctx)
-
 	var err error
 	if b.client, err = InternalNewClient(b.sm, b.ns); err != nil {
 		t.Fatalf("InternalNewClient failed: %v", err)
@@ -1329,11 +1312,11 @@
 	call := func() error {
 		call, err := b.client.StartCall(ctx, "mountpoint/server/aclAuth", "Echo", []interface{}{"batman"})
 		if err != nil {
-			return err //fmt.Errorf("client.StartCall failed: %v", err)
+			return err
 		}
 		var got string
 		if err := call.Finish(&got); err != nil {
-			return err //fmt.Errorf("client.Finish failed: %v", err)
+			return err
 		}
 		if want := `method:"Echo",suffix:"aclAuth",arg:"batman"`; got != want {
 			return verror.Convert(verror.ErrBadArg, nil, fmt.Errorf("Got [%v] want [%v]", got, want))
@@ -1401,11 +1384,14 @@
 func TestCancel(t *testing.T) {
 	ctx, shutdown := initForTest()
 	defer shutdown()
-	ts := newCancelTestServer(t)
-	b := createBundle(t, ctx, tsecurity.NewPrincipal("server"), ts)
+	var (
+		ts               = newCancelTestServer(t)
+		pclient, pserver = newClientServerPrincipals()
+		b                = createBundle(t, ctx, pserver, ts)
+	)
 	defer b.cleanup(t, ctx)
 
-	ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("client"))
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	ctx, cancel := context.WithCancel(ctx)
 	_, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "CancelStreamReader", []interface{}{})
 	if err != nil {
@@ -1419,11 +1405,14 @@
 func TestCancelWithFullBuffers(t *testing.T) {
 	ctx, shutdown := initForTest()
 	defer shutdown()
-	ts := newCancelTestServer(t)
-	b := createBundle(t, ctx, tsecurity.NewPrincipal("server"), ts)
+	var (
+		ts               = newCancelTestServer(t)
+		pclient, pserver = newClientServerPrincipals()
+		b                = createBundle(t, ctx, pserver, ts)
+	)
 	defer b.cleanup(t, ctx)
 
-	ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("client"))
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	ctx, cancel := context.WithCancel(ctx)
 	call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "CancelStreamIgnorer", []interface{}{})
 	if err != nil {
@@ -1459,11 +1448,14 @@
 func TestStreamReadTerminatedByServer(t *testing.T) {
 	ctx, shutdown := initForTest()
 	defer shutdown()
-	s := &streamRecvInGoroutineServer{c: make(chan error, 1)}
-	b := createBundle(t, ctx, tsecurity.NewPrincipal("server"), s)
+	var (
+		pclient, pserver = newClientServerPrincipals()
+		s                = &streamRecvInGoroutineServer{c: make(chan error, 1)}
+		b                = createBundle(t, ctx, pserver, s)
+	)
 	defer b.cleanup(t, ctx)
 
-	ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("client"))
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "RecvInGoroutine", []interface{}{})
 	if err != nil {
 		t.Fatalf("StartCall failed: %v", err)
@@ -1495,7 +1487,10 @@
 func TestConnectWithIncompatibleServers(t *testing.T) {
 	ctx, shutdown := initForTest()
 	defer shutdown()
-	b := createBundle(t, ctx, tsecurity.NewPrincipal("server"), &testServer{})
+	var (
+		pclient, pserver = newClientServerPrincipals()
+		b                = createBundle(t, ctx, pserver, &testServer{})
+	)
 	defer b.cleanup(t, ctx)
 
 	// Publish some incompatible endpoints.
@@ -1506,7 +1501,7 @@
 	publisher.AddServer("/@2@tcp@localhost:10000@@1000000@2000000@@", false)
 	publisher.AddServer("/@2@tcp@localhost:10001@@2000000@3000000@@", false)
 
-	ctx, _ = v23.SetPrincipal(ctx, tsecurity.NewPrincipal("client"))
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	_, err := b.client.StartCall(ctx, "incompatible/suffix", "Echo", []interface{}{"foo"}, options.NoRetry{})
 	if !verror.Is(err, verror.ErrNoServers.ID) {
 		t.Errorf("Expected error %s, found: %v", verror.ErrNoServers, err)
@@ -1799,6 +1794,9 @@
 	if err = pdischargeClient.BlessingStore().SetDefault(blessings); err != nil {
 		t.Fatalf("failed to set blessings: %v", err)
 	}
+	// The client will only talk to the discharge services if it recognizes them.
+	pdischargeClient.AddToRoots(pdischarger1.BlessingStore().Default())
+	pdischargeClient.AddToRoots(pdischarger2.BlessingStore().Default())
 
 	ns := tnaming.NewSimpleNamespace()
 
@@ -1951,11 +1949,11 @@
 
 	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	// The call should succeed when the server presents the same public as the opt...
-	if _, err = client.StartCall(ctx, mountName, "Closure", nil, options.ServerPublicKey{pserver.PublicKey()}); err != nil {
+	if _, err = client.StartCall(ctx, mountName, "Closure", nil, options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{pserver.PublicKey()}); err != nil {
 		t.Errorf("Expected call to succeed but got %v", err)
 	}
 	// ...but fail if they differ.
-	if _, err = client.StartCall(ctx, mountName, "Closure", nil, options.ServerPublicKey{pother.PublicKey()}); !verror.Is(err, verror.ErrNotTrusted.ID) {
+	if _, err = client.StartCall(ctx, mountName, "Closure", nil, options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{pother.PublicKey()}); !verror.Is(err, verror.ErrNotTrusted.ID) {
 		t.Errorf("got %v, want %v", verror.ErrorID(err), verror.ErrNotTrusted.ID)
 	}
 }
@@ -1989,19 +1987,16 @@
 }
 
 func TestDischargeClientFetchExpiredDischarges(t *testing.T) {
-	var (
-		pdischarger = tsecurity.NewPrincipal("discharger")
-	)
 	ctx, shutdown := initForTest()
 	defer shutdown()
-
-	// Bless the client with a ThirdPartyCaveat.
-	tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
-
-	ns := tnaming.NewSimpleNamespace()
+	var (
+		pclient, pdischarger = newClientServerPrincipals()
+		tpcav                = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+		ns                   = tnaming.NewSimpleNamespace()
+		discharger           = &expiryDischarger{}
+	)
 
 	// Setup the disharge server.
-	discharger := &expiryDischarger{}
 	defer runServer(t, ctx, ns, pdischarger, "mountpoint/discharger", discharger).Shutdown()
 
 	// Create a discharge client.
@@ -2016,10 +2011,11 @@
 		t.Fatalf("failed to create client: %v", err)
 	}
 	defer client.Close()
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	dc := InternalNewDischargeClient(ctx, client, 0)
 
 	// Fetch discharges for tpcav.
-	dis := dc.PrepareDischarges(nil, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
+	dis := dc.PrepareDischarges(ctx, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
 	// Check that the discharges is not yet expired, but is expired after 100 milliseconds.
 	expiry := dis.Expiry()
 	// The discharge should expire.
@@ -2031,12 +2027,28 @@
 	}
 	// Preparing Discharges again to get fresh discharges.
 	now := time.Now()
-	dis = dc.PrepareDischarges(nil, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
+	dis = dc.PrepareDischarges(ctx, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
 	if expiry = dis.Expiry(); expiry.Before(now) {
 		t.Fatalf("discharge has expired %v, but should be fresh", dis)
 	}
 }
 
+// newClientServerPrincipals creates a pair of principals and sets them up to
+// recognize each others default blessings.
+//
+// If the client does not recognize the blessings presented by the server,
+// then it will not even send it the request.
+//
+// If the server does not recognize the blessings presented by the client,
+// it is likely to deny access (unless the server authorizes all principals).
+func newClientServerPrincipals() (client, server security.Principal) {
+	client = tsecurity.NewPrincipal("client")
+	server = tsecurity.NewPrincipal("server")
+	client.AddToRoots(server.BlessingStore().Default())
+	server.AddToRoots(client.BlessingStore().Default())
+	return
+}
+
 func init() {
 	rpc.RegisterUnknownProtocol("wsh", websocket.HybridDial, websocket.HybridListener)
 	security.RegisterCaveatValidator(fakeTimeCaveat, func(_ security.Call, t int64) error {
diff --git a/profiles/internal/rpc/resolve_test.go b/profiles/internal/rpc/resolve_test.go
index 40f9c23..04743a8 100644
--- a/profiles/internal/rpc/resolve_test.go
+++ b/profiles/internal/rpc/resolve_test.go
@@ -22,7 +22,6 @@
 	irpc "v.io/x/ref/profiles/internal/rpc"
 	grt "v.io/x/ref/profiles/internal/rt"
 	mounttable "v.io/x/ref/services/mounttable/lib"
-	"v.io/x/ref/test"
 	"v.io/x/ref/test/expect"
 	"v.io/x/ref/test/modules"
 )
@@ -103,16 +102,15 @@
 
 func TestResolveToEndpoint(t *testing.T) {
 	setupRuntime()
-	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
+	ctx, shutdown := v23.Init()
+	defer shutdown()
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("modules.NewShell failed: %s", err)
 	}
 	defer sh.Cleanup(nil, nil)
 	root := startMT(t, sh)
 
-	ctx, shutdown := test.InitForTest()
-	defer shutdown()
-
 	ns := v23.GetNamespace(ctx)
 	ns.SetRoots(root)
 
diff --git a/profiles/internal/rpc/server_authorizer.go b/profiles/internal/rpc/server_authorizer.go
index 4d12a49..c9e5852 100644
--- a/profiles/internal/rpc/server_authorizer.go
+++ b/profiles/internal/rpc/server_authorizer.go
@@ -18,8 +18,8 @@
 var (
 	errNoBlessings = verror.Register(pkgPath+".noBlessings", verror.NoRetry, "server has not presented any blessings")
 
-	errAuthNoPatternMatch = verror.Register(pkgPath+".authNoPatternMatch",
-		verror.NoRetry, "server blessings {3} do not match pattern {4}{:5}")
+	errAuthPossibleManInTheMiddle = verror.Register(pkgPath+".authPossibleManInTheMiddle",
+		verror.NoRetry, "server blessings {3} do not match expectations set by endpoint {4}, possible man-in-the-middle or the server blessings are not accepted by the client? (endpoint: {5}, rejected blessings: {6})")
 
 	errAuthServerNotAllowed = verror.Register(pkgPath+".authServerNotAllowed",
 		verror.NoRetry, "server blessings {3} do not match any allowed server patterns {4}{:5}")
@@ -30,21 +30,20 @@
 
 // serverAuthorizer implements security.Authorizer.
 type serverAuthorizer struct {
-	patternsFromNameResolution []security.BlessingPattern
-	allowedServerPolicies      [][]security.BlessingPattern
-	serverPublicKey            security.PublicKey
+	allowedServerPolicies     [][]security.BlessingPattern
+	serverPublicKey           security.PublicKey
+	ignoreBlessingsInEndpoint bool
 }
 
 // newServerAuthorizer returns a security.Authorizer for authorizing the server
-// during a flow. The authorization policy is based on enforcing any server
-// patterns obtained by resolving the server's name, and any server authorization
-// options supplied to the call that initiated the flow.
+// during a flow. The authorization policy is based on options supplied to the
+// call that initiated the flow. Additionally, if pattern is non-empty then
+// the server will be authorized only if it presents at least one blessing
+// that matches pattern.
 //
 // This method assumes that canCreateServerAuthorizer(opts) is nil.
-func newServerAuthorizer(ctx *context.T, patternsFromNameResolution []security.BlessingPattern, opts ...rpc.CallOpt) security.Authorizer {
-	auth := &serverAuthorizer{
-		patternsFromNameResolution: patternsFromNameResolution,
-	}
+func newServerAuthorizer(pattern security.BlessingPattern, opts ...rpc.CallOpt) security.Authorizer {
+	auth := &serverAuthorizer{}
 	for _, o := range opts {
 		// TODO(ataly, ashankar): Consider creating an authorizer for each of the
 		// options below and then take the intersection of the authorizers.
@@ -53,28 +52,45 @@
 			auth.serverPublicKey = v.PublicKey
 		case options.AllowedServersPolicy:
 			auth.allowedServerPolicies = append(auth.allowedServerPolicies, v)
-		case options.SkipResolveAuthorization:
-			auth.patternsFromNameResolution = []security.BlessingPattern{security.AllPrincipals}
+		case options.SkipServerEndpointAuthorization:
+			auth.ignoreBlessingsInEndpoint = true
 		}
 	}
+	if len(pattern) > 0 {
+		auth.allowedServerPolicies = append(auth.allowedServerPolicies, []security.BlessingPattern{pattern})
+	}
 	return auth
 }
 
 func (a *serverAuthorizer) Authorize(ctx *context.T) error {
 	call := security.GetCall(ctx)
-	// TODO(ashankar): Remove this check?
 	if call.RemoteBlessings().IsZero() {
 		return verror.New(errNoBlessings, ctx)
 	}
 	serverBlessings, rejectedBlessings := security.RemoteBlessingNames(ctx)
 
-	if !matchedBy(a.patternsFromNameResolution, serverBlessings) {
-		return verror.New(errAuthNoPatternMatch, ctx, serverBlessings, a.patternsFromNameResolution, rejectedBlessings)
-	} else if enableSecureServerAuth {
-		// No server patterns were obtained while resolving the name, authorize
-		// the server using the default authorization policy.
+	if epb := call.RemoteEndpoint().BlessingNames(); len(epb) > 0 && !a.ignoreBlessingsInEndpoint {
+		matched := false
+		for _, b := range epb {
+			// TODO(ashankar,ataly): Should this be
+			// security.BlessingPattern(b).MakeNonExtendable().MatchedBy()?
+			// Because, without that, a delegate of the real server
+			// can be a man-in-the-middle without failing
+			// authorization. Is that a desirable property?
+			if security.BlessingPattern(b).MatchedBy(serverBlessings...) {
+				matched = true
+				break
+			}
+		}
+		if !matched {
+			return verror.New(errAuthPossibleManInTheMiddle, ctx, serverBlessings, epb, call.RemoteEndpoint(), rejectedBlessings)
+		}
+	} else if enableSecureServerAuth && len(epb) == 0 {
+		// No blessings in the endpoint to set expectations on the
+		// "identity" of the server.  Use the default authorization
+		// policy.
 		if err := (defaultAuthorizer{}).Authorize(ctx); err != nil {
-			return verror.New(errDefaultAuthDenied, ctx, serverBlessings)
+			return err
 		}
 	}
 
diff --git a/profiles/internal/rpc/server_authorizer_test.go b/profiles/internal/rpc/server_authorizer_test.go
index 5cbd381..866e0bd 100644
--- a/profiles/internal/rpc/server_authorizer_test.go
+++ b/profiles/internal/rpc/server_authorizer_test.go
@@ -8,6 +8,7 @@
 	"v.io/v23"
 	"v.io/v23/options"
 	"v.io/v23/security"
+	"v.io/x/ref/profiles/internal/naming"
 )
 
 func TestServerAuthorizer(t *testing.T) {
@@ -42,26 +43,30 @@
 	}
 	// All tests are run as if pclient is the client end and pserver is remote end.
 	tests := []struct {
+		serverBlessingNames []string
 		auth                security.Authorizer
 		authorizedServers   []security.Blessings
 		unauthorizedServers []security.Blessings
 	}{
 		{
-			// All servers with a non-zero blessing are authorized
-			newServerAuthorizer(ctx, nil),
+			// No blessings in the endpoint means that all servers are authorized.
+			nil,
+			newServerAuthorizer(""),
 			[]security.Blessings{ali, otherAli, bob, che},
 			[]security.Blessings{zero},
 		},
 		{
-			// Only ali, otherAli and bob are authorized
-			newServerAuthorizer(ctx, []security.BlessingPattern{"ali", "bob"}),
+			// Endpoint sets the expectations for "ali" and "bob".
+			[]string{"ali", "bob"},
+			newServerAuthorizer(""),
 			[]security.Blessings{ali, otherAli, bob, U(ali, che), U(bob, che)},
 			[]security.Blessings{che},
 		},
 		{
 			// Still only ali, otherAli and bob are authorized (che is not
 			// authorized since it is not recognized by the client)
-			newServerAuthorizer(ctx, []security.BlessingPattern{"ali", "bob", "che"}, nil),
+			[]string{"ali", "bob", "che"},
+			newServerAuthorizer(""),
 			[]security.Blessings{ali, otherAli, bob, U(ali, che), U(bob, che)},
 			[]security.Blessings{che},
 		},
@@ -69,31 +74,70 @@
 
 			// Only ali and otherAli are authorized (since there is an
 			// allowed-servers policy that does not allow "bob")
-			newServerAuthorizer(ctx, []security.BlessingPattern{"ali", "bob", "che"}, options.AllowedServersPolicy{"ali", "bob"}, options.AllowedServersPolicy{"ali"}),
+			[]string{"ali", "bob", "che"},
+			newServerAuthorizer("", options.AllowedServersPolicy{"ali", "bob"}, options.AllowedServersPolicy{"ali"}),
 			[]security.Blessings{ali, otherAli, U(ali, che), U(ali, bob)},
 			[]security.Blessings{bob, che},
 		},
 		{
+			// Multiple AllowedServersPolicy are treated as an AND (and individual ones are "ORs")
+			nil,
+			newServerAuthorizer("", options.AllowedServersPolicy{"ali", "che"}, options.AllowedServersPolicy{"bob", "che"}),
+			[]security.Blessings{U(ali, bob)},
+			[]security.Blessings{ali, bob, che, U(ali, che), U(bob, che)},
+		},
+		{
 			// Only otherAli is authorized (since only pother's public key is
 			// authorized)
-			newServerAuthorizer(ctx, nil, options.ServerPublicKey{pother.PublicKey()}),
+			[]string{"ali"},
+			newServerAuthorizer("", options.ServerPublicKey{pother.PublicKey()}),
 			[]security.Blessings{otherAli},
 			[]security.Blessings{ali, bob, che},
 		},
+		{
+			// Blessings in endpoint can be ignored.
+			[]string{"ali"},
+			newServerAuthorizer("", options.SkipServerEndpointAuthorization{}),
+			[]security.Blessings{ali, bob, che, otherAli},
+			nil,
+		},
+		{
+			// Pattern specified is respected
+			nil,
+			newServerAuthorizer("bob"),
+			[]security.Blessings{bob, U(ali, bob)},
+			[]security.Blessings{ali, otherAli, che},
+		},
+		{
+			// And concatenated with any existing AllowedServersPolicy
+			[]string{"ali", "bob", "che"},
+			newServerAuthorizer("bob", options.AllowedServersPolicy{"bob", "che"}),
+			[]security.Blessings{bob, U(ali, bob), U(ali, bob, che)},
+			[]security.Blessings{ali, che},
+		},
+		{
+			// And if the intersection of AllowedServersPolicy and the pattern be empty, then so be it!
+			[]string{"ali", "bob", "che"},
+			newServerAuthorizer("bob", options.AllowedServersPolicy{"ali", "che"}),
+			[]security.Blessings{U(ali, bob), U(ali, bob, che)},
+			[]security.Blessings{ali, otherAli, bob, che, U(ali, che)},
+		},
 	}
 	for _, test := range tests {
 		for _, s := range test.authorizedServers {
 			if err := test.auth.Authorize(security.SetCall(ctx, &mockCall{
-				p: pclient,
-				r: s,
+				p:   pclient,
+				r:   s,
+				rep: &naming.Endpoint{Blessings: test.serverBlessingNames},
 			})); err != nil {
 				t.Errorf("serverAuthorizer: %#v failed to authorize server: %v", test.auth, s)
 			}
 		}
 		for _, s := range test.unauthorizedServers {
 			if err := test.auth.Authorize(security.SetCall(ctx, &mockCall{
-				p: pclient,
-				r: s,
+				p:   pclient,
+				r:   s,
+				rep: &naming.Endpoint{Blessings: test.serverBlessingNames},
 			})); err == nil {
 				t.Errorf("serverAuthorizer: %#v authorized server: %v", test.auth, s)
 			}
diff --git a/profiles/internal/rpc/server_test.go b/profiles/internal/rpc/server_test.go
index 997524f..36d7453 100644
--- a/profiles/internal/rpc/server_test.go
+++ b/profiles/internal/rpc/server_test.go
@@ -41,12 +41,13 @@
 // TestBadObject ensures that Serve handles bad receiver objects gracefully (in
 // particular, it doesn't panic).
 func TestBadObject(t *testing.T) {
+	ctx, shutdown := initForTest()
+	defer shutdown()
 	sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
 	defer sm.Shutdown()
 	ns := tnaming.NewSimpleNamespace()
-	ctx, shutdown := initForTest()
-	defer shutdown()
-	server, err := testInternalNewServer(ctx, sm, ns, tsecurity.NewPrincipal("test"))
+	pclient, pserver := newClientServerPrincipals()
+	server, err := testInternalNewServer(ctx, sm, ns, pserver)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -71,6 +72,7 @@
 	if err != nil {
 		t.Fatalf("InternalNewClient failed: %v", err)
 	}
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	ctx, _ = context.WithDeadline(ctx, time.Now().Add(10*time.Second))
 	call, err := client.StartCall(ctx, "servername", "SomeMethod", nil)
 	if err != nil {
diff --git a/profiles/internal/rpc/test/client_test.go b/profiles/internal/rpc/test/client_test.go
index d39dac7..4642181 100644
--- a/profiles/internal/rpc/test/client_test.go
+++ b/profiles/internal/rpc/test/client_test.go
@@ -350,6 +350,8 @@
 	defer fn()
 
 	ctx1, err := v23.SetPrincipal(ctx, tsecurity.NewPrincipal("test-blessing"))
+	// Client must recognize the server, otherwise it won't even send the request.
+	v23.GetPrincipal(ctx1).AddToRoots(v23.GetPrincipal(ctx).BlessingStore().Default())
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/profiles/internal/rpc/test/proxy_test.go b/profiles/internal/rpc/test/proxy_test.go
index 689a10f..a117653 100644
--- a/profiles/internal/rpc/test/proxy_test.go
+++ b/profiles/internal/rpc/test/proxy_test.go
@@ -166,6 +166,7 @@
 	defer shutdown()
 	var (
 		pserver   = tsecurity.NewPrincipal("server")
+		pclient   = tsecurity.NewPrincipal("client")
 		serverKey = pserver.PublicKey()
 		// We use different stream managers for the client and server
 		// to prevent VIF re-use (in other words, we want to test VIF
@@ -188,15 +189,19 @@
 	}
 	defer server.Stop()
 
+	// The client must recognize the server's blessings, otherwise it won't
+	// communicate with it.
+	pclient.AddToRoots(pserver.BlessingStore().Default())
+
 	// If no address is specified then we'll only 'listen' via
 	// the proxy.
 	hasLocalListener := len(spec.Addrs) > 0 && len(spec.Addrs[0].Address) != 0
 
 	name := "mountpoint/server/suffix"
 	makeCall := func(opts ...rpc.CallOpt) (string, error) {
-		ctx, _ := context.WithDeadline(ctx, time.Now().Add(5*time.Second))
-		// Let's fail fast so that the tests don't take as long to run.
-		call, err := client.StartCall(ctx, name, "Echo", []interface{}{"batman"}, opts...)
+		clientCtx, _ := v23.SetPrincipal(ctx, pclient)
+		clientCtx, _ = context.WithDeadline(clientCtx, time.Now().Add(5*time.Second))
+		call, err := client.StartCall(clientCtx, name, "Echo", []interface{}{"batman"}, opts...)
 		if err != nil {
 			// proxy is down, we should return here/.... prepend
 			// the error with a well known string so that we can test for that.
diff --git a/profiles/internal/rpc/testutil_test.go b/profiles/internal/rpc/testutil_test.go
index 13f1fa7..4ec9e17 100644
--- a/profiles/internal/rpc/testutil_test.go
+++ b/profiles/internal/rpc/testutil_test.go
@@ -94,11 +94,12 @@
 
 // mockCall implements security.Call
 type mockCall struct {
-	p      security.Principal
-	l, r   security.Blessings
-	m      string
-	ld, rd security.Discharge
-	c      *context.T
+	p        security.Principal
+	l, r     security.Blessings
+	m        string
+	ld, rd   security.Discharge
+	lep, rep naming.Endpoint
+	c        *context.T
 }
 
 func (c *mockCall) Timestamp() (t time.Time) { return }
@@ -111,8 +112,8 @@
 func (c *mockCall) RemoteDischarges() map[string]security.Discharge {
 	return map[string]security.Discharge{c.rd.ID(): c.rd}
 }
-func (c *mockCall) LocalEndpoint() naming.Endpoint      { return nil }
-func (c *mockCall) RemoteEndpoint() naming.Endpoint     { return nil }
+func (c *mockCall) LocalEndpoint() naming.Endpoint      { return c.lep }
+func (c *mockCall) RemoteEndpoint() naming.Endpoint     { return c.rep }
 func (c *mockCall) LocalPrincipal() security.Principal  { return c.p }
 func (c *mockCall) LocalBlessings() security.Blessings  { return c.l }
 func (c *mockCall) RemoteBlessings() security.Blessings { return c.r }
diff --git a/profiles/internal/rt/ipc_test.go b/profiles/internal/rt/ipc_test.go
index 2fdcdab..a9b6f21 100644
--- a/profiles/internal/rt/ipc_test.go
+++ b/profiles/internal/rt/ipc_test.go
@@ -100,38 +100,30 @@
 	defer shutdown()
 
 	var (
-		rootAlpha, rootBeta, rootUnrecognized = tsecurity.NewIDProvider("alpha"), tsecurity.NewIDProvider("beta"), tsecurity.NewIDProvider("unrecognized")
-		clientCtx, serverCtx                  = newCtxPrincipal(ctx), newCtxPrincipal(ctx)
-		pclient                               = v23.GetPrincipal(clientCtx)
-		pserver                               = v23.GetPrincipal(serverCtx)
+		rootAlpha, rootBeta  = tsecurity.NewIDProvider("alpha"), tsecurity.NewIDProvider("beta")
+		clientCtx, serverCtx = newCtxPrincipal(ctx), newCtxPrincipal(ctx)
+		pclient              = v23.GetPrincipal(clientCtx)
+		pserver              = v23.GetPrincipal(serverCtx)
 
 		// A bunch of blessings
-		alphaClient        = mkBlessings(rootAlpha.NewBlessings(pclient, "client"))
-		betaClient         = mkBlessings(rootBeta.NewBlessings(pclient, "client"))
-		unrecognizedClient = mkBlessings(rootUnrecognized.NewBlessings(pclient, "client"))
+		alphaClient = mkBlessings(rootAlpha.NewBlessings(pclient, "client"))
+		betaClient  = mkBlessings(rootBeta.NewBlessings(pclient, "client"))
 
 		alphaServer = mkBlessings(rootAlpha.NewBlessings(pserver, "server"))
 		betaServer  = mkBlessings(rootBeta.NewBlessings(pserver, "server"))
-		selfServer  = mkBlessings(pserver.BlessSelf("serverself"))
 	)
 	// Setup the client's blessing store
 	pclient.BlessingStore().Set(alphaClient, "alpha/server")
 	pclient.BlessingStore().Set(betaClient, "beta")
-	pclient.BlessingStore().Set(unrecognizedClient, security.AllPrincipals)
 
 	tests := []struct {
 		server security.Blessings // Blessings presented by the server.
 
 		// Expected output
 		wantServer []string // Client's view of the server's blessings
-		wantClient []string // Server's view fo the client's blessings
+		wantClient []string // Server's view of the client's blessings
 	}{
 		{
-			server:     selfServer,
-			wantServer: nil,
-			wantClient: nil,
-		},
-		{
 			server:     alphaServer,
 			wantServer: []string{"alpha/server"},
 			wantClient: []string{"alpha/client"},
@@ -152,10 +144,6 @@
 			}
 		}
 	}
-	// And server trusts itself as a root
-	if err := pserver.AddToRoots(selfServer); err != nil {
-		t.Fatal(err)
-	}
 	// Let it rip!
 	for _, test := range tests {
 		if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
diff --git a/profiles/internal/rt/runtime.go b/profiles/internal/rt/runtime.go
index 07dbd78..b994257 100644
--- a/profiles/internal/rt/runtime.go
+++ b/profiles/internal/rt/runtime.go
@@ -386,6 +386,9 @@
 
 func (r *Runtime) setNewNamespace(ctx *context.T, roots ...string) (*context.T, ns.Namespace, error) {
 	ns, err := namespace.New(roots...)
+	if err != nil {
+		return nil, nil, err
+	}
 
 	if oldNS := r.GetNamespace(ctx); oldNS != nil {
 		ns.CacheCtl(oldNS.CacheCtl()...)
diff --git a/profiles/internal/vtrace/vtrace_test.go b/profiles/internal/vtrace/vtrace_test.go
index 822fdde..65ad363 100644
--- a/profiles/internal/vtrace/vtrace_test.go
+++ b/profiles/internal/vtrace/vtrace_test.go
@@ -10,6 +10,7 @@
 	"v.io/v23/naming"
 	"v.io/v23/naming/ns"
 	"v.io/v23/rpc"
+	"v.io/v23/security"
 	"v.io/v23/vtrace"
 	"v.io/x/lib/vlog"
 
@@ -84,13 +85,13 @@
 	return nil
 }
 
-func makeTestServer(ctx *context.T, ns ns.Namespace, name, child string, forceCollect bool) (*testServer, error) {
+func makeTestServer(ctx *context.T, principal security.Principal, ns ns.Namespace, name, child string, forceCollect bool) (*testServer, error) {
 	sm := manager.InternalNew(naming.FixedRoutingID(0x111111111))
 	client, err := irpc.InternalNewClient(sm, ns)
 	if err != nil {
 		return nil, err
 	}
-	s, err := irpc.InternalNewServer(ctx, sm, ns, client, tsecurity.NewPrincipal("test"))
+	s, err := irpc.InternalNewServer(ctx, sm, ns, client, principal)
 	if err != nil {
 		return nil, err
 	}
@@ -192,22 +193,32 @@
 }
 
 func runCallChain(t *testing.T, ctx *context.T, force1, force2 bool) {
-	sm := manager.InternalNew(naming.FixedRoutingID(0x555555555))
-	ns := tnaming.NewSimpleNamespace()
-
+	var (
+		sm       = manager.InternalNew(naming.FixedRoutingID(0x555555555))
+		ns       = tnaming.NewSimpleNamespace()
+		pclient  = tsecurity.NewPrincipal("client")
+		pserver1 = tsecurity.NewPrincipal("server1")
+		pserver2 = tsecurity.NewPrincipal("server2")
+	)
+	for _, p1 := range []security.Principal{pclient, pserver1, pserver2} {
+		for _, p2 := range []security.Principal{pclient, pserver1, pserver2} {
+			p1.AddToRoots(p2.BlessingStore().Default())
+		}
+	}
+	ctx, _ = v23.SetPrincipal(ctx, pclient)
 	client, err := irpc.InternalNewClient(sm, ns)
 	if err != nil {
 		t.Error(err)
 	}
 	ctx1, _ := vtrace.SetNewTrace(ctx)
-	c1, err := makeTestServer(ctx1, ns, "c1", "c2", force1)
+	c1, err := makeTestServer(ctx1, pserver1, ns, "c1", "c2", force1)
 	if err != nil {
 		t.Fatal("Can't start server:", err)
 	}
 	defer c1.stop()
 
 	ctx2, _ := vtrace.SetNewTrace(ctx)
-	c2, err := makeTestServer(ctx2, ns, "c2", "", force2)
+	c2, err := makeTestServer(ctx2, pserver2, ns, "c2", "", force2)
 	if err != nil {
 		t.Fatal("Can't start server:", err)
 	}
diff --git a/services/mgmt/device/impl/impl_test.go b/services/mgmt/device/impl/impl_test.go
index c2cdca1..080f1d6 100644
--- a/services/mgmt/device/impl/impl_test.go
+++ b/services/mgmt/device/impl/impl_test.go
@@ -908,7 +908,7 @@
 	// Unclaimed devices cannot do anything but be claimed.
 	// TODO(ashankar,caprita): The line below will currently fail with
 	// ErrUnclaimedDevice != NotTrusted. NotTrusted can be avoided by
-	// passing options.SkipResolveAuthorization{} to the "Install" RPC.
+	// passing options.SkipServerEndpointAuthorization{} to the "Install" RPC.
 	// Refactor the helper function to make this possible.
 	//installAppExpectError(t, octx, impl.ErrUnclaimedDevice.ID)
 
@@ -921,9 +921,10 @@
 	// the devicemanager.
 	appID := installApp(t, claimantCtx)
 
-	// octx will not install the app now since it doesn't recognize
-	// the device's blessings.
-	installAppExpectError(t, octx, verror.ErrNotTrusted.ID)
+	// octx will not install the app now since it doesn't recognize the
+	// device's blessings. The error returned will be ErrNoServers as that
+	// is what the IPC stack does when there are no authorized servers.
+	installAppExpectError(t, octx, verror.ErrNoServers.ID)
 	// Even if it does recognize the device (by virtue of recognizing the
 	// claimant), the device will not allow it to install.
 	if err := v23.GetPrincipal(octx).AddToRoots(v23.GetPrincipal(claimantCtx).BlessingStore().Default()); err != nil {
@@ -1360,15 +1361,18 @@
 		t.Fatal(err)
 	}
 
-	// By default, the two processes (selfCtx and octx) will have blessings generated based on
-	// the username/machine name running this process. Since these blessings
-	// will appear in AccessLists, give them recognizable names.
+	// By default, the two processes (selfCtx and octx) will have blessings
+	// generated based on the username/machine name running this process.
+	// Since these blessings will appear in AccessLists, give them
+	// recognizable names.
 	idp := tsecurity.NewIDProvider("root")
-	selfCtx := ctx
-	if err := idp.Bless(v23.GetPrincipal(selfCtx), "self"); err != nil {
-		t.Fatal(err)
-	}
+	selfCtx := ctxWithNewPrincipal(t, ctx, idp, "self")
 	otherCtx := ctxWithNewPrincipal(t, selfCtx, idp, "other")
+	// Both the "external" processes must recognize the root mounttable's
+	// blessings, otherwise they will not talk to it.
+	for _, c := range []*context.T{selfCtx, otherCtx} {
+		v23.GetPrincipal(c).AddToRoots(v23.GetPrincipal(ctx).BlessingStore().Default())
+	}
 
 	dmh := mgmttest.RunCommand(t, sh, nil, deviceManagerCmd, "dm", root, "unused_helper", "unused_app_repo_name", "unused_curr_link")
 	pid := mgmttest.ReadPID(t, dmh)
@@ -1382,7 +1386,7 @@
 	}
 
 	// self claims the device manager.
-	claimDevice(t, ctx, "dm", "alice", noPairingToken)
+	claimDevice(t, selfCtx, "dm", "alice", noPairingToken)
 
 	vlog.VI(2).Info("Verify that associations start out empty.")
 	listAndVerifyAssociations(t, selfCtx, deviceStub, []device.Association(nil))
diff --git a/services/mgmt/device/impl/util_test.go b/services/mgmt/device/impl/util_test.go
index 78f8e2d..bab9d57 100644
--- a/services/mgmt/device/impl/util_test.go
+++ b/services/mgmt/device/impl/util_test.go
@@ -94,7 +94,7 @@
 func claimDevice(t *testing.T, ctx *context.T, name, extension, pairingToken string) {
 	// Setup blessings to be granted to the claimed device
 	g := &granter{p: v23.GetPrincipal(ctx), extension: extension}
-	s := options.SkipResolveAuthorization{}
+	s := options.SkipServerEndpointAuthorization{}
 	// Call the Claim RPC: Skip server authorization because the unclaimed
 	// device presents nothing that can be used to recognize it.
 	if err := device.ClaimableClient(name).Claim(ctx, pairingToken, g, s); err != nil {
@@ -120,7 +120,7 @@
 func claimDeviceExpectError(t *testing.T, ctx *context.T, name, extension, pairingToken string, errID verror.ID) {
 	// Setup blessings to be granted to the claimed device
 	g := &granter{p: v23.GetPrincipal(ctx), extension: extension}
-	s := options.SkipResolveAuthorization{}
+	s := options.SkipServerEndpointAuthorization{}
 	// Call the Claim RPC
 	if err := device.ClaimableClient(name).Claim(ctx, pairingToken, g, s); !verror.Is(err, errID) {
 		t.Fatalf(testutil.FormatLogLine(2, "%q.Claim(%q) expected to fail with %v, got %v [%v]", name, pairingToken, errID, verror.ErrorID(err), err))
diff --git a/services/wsprd/app/app_test.go b/services/wsprd/app/app_test.go
index aa9c8ee..54ba33d 100644
--- a/services/wsprd/app/app_test.go
+++ b/services/wsprd/app/app_test.go
@@ -427,6 +427,9 @@
 	// Get the client that is relevant to the controller so it talks
 	// to the right mounttable.
 	client := v23.GetClient(rt.controller.Context())
+	// And have the client recognize the server, otherwise it won't
+	// authorize calls to it.
+	v23.GetPrincipal(rt.controller.Context()).AddToRoots(v23.GetPrincipal(ctx).BlessingStore().Default())
 
 	if err != nil {
 		t.Fatalf("unable to create client: %v", err)