ref: BlessingsForPeer -> PeerAuthorizer.

Client now authorizes server during conn establishment.

MultiPart: 2/2

Change-Id: Ie80b83b36e7ec467c46d8b5414ec089abe0622c7
diff --git a/runtime/internal/flow/conn/auth.go b/runtime/internal/flow/conn/auth.go
index 40337ec..c057c2a 100644
--- a/runtime/internal/flow/conn/auth.go
+++ b/runtime/internal/flow/conn/auth.go
@@ -14,6 +14,7 @@
 	"golang.org/x/crypto/nacl/box"
 	"v.io/v23"
 	"v.io/v23/context"
+	"v.io/v23/flow"
 	"v.io/v23/flow/message"
 	"v.io/v23/rpc/version"
 	"v.io/v23/security"
@@ -27,7 +28,7 @@
 	authAcceptorTag = []byte("AuthAcpt\x00")
 )
 
-func (c *Conn) dialHandshake(ctx *context.T, versions version.RPCVersionRange) error {
+func (c *Conn) dialHandshake(ctx *context.T, versions version.RPCVersionRange, auth flow.PeerAuthorizer) error {
 	binding, err := c.setup(ctx, versions)
 	if err != nil {
 		return err
@@ -37,12 +38,16 @@
 	bflow.worker.Release(ctx, DefaultBytesBufferedPerFlow)
 	c.blessingsFlow = newBlessingsFlow(ctx, &c.loopWG, bflow, true)
 
-	if err = c.readRemoteAuth(ctx, authAcceptorTag, binding); err != nil {
+	rDischarges, err := c.readRemoteAuth(ctx, authAcceptorTag, binding)
+	if err != nil {
 		return err
 	}
 	if c.rBlessings.IsZero() {
 		return NewErrAcceptorBlessingsMissing(ctx)
 	}
+	if _, _, err := auth.AuthorizePeer(ctx, c.local, c.remote, c.rBlessings, rDischarges); err != nil {
+		return err
+	}
 	signedBinding, err := v23.GetPrincipal(ctx).Sign(append(authDialerTag, binding...))
 	if err != nil {
 		return err
@@ -82,7 +87,8 @@
 	if err = c.mp.writeMsg(ctx, lAuth); err != nil {
 		return err
 	}
-	return c.readRemoteAuth(ctx, authDialerTag, binding)
+	_, err = c.readRemoteAuth(ctx, authDialerTag, binding)
+	return err
 }
 
 func (c *Conn) setup(ctx *context.T, versions version.RPCVersionRange) ([]byte, error) {
@@ -141,38 +147,39 @@
 	return binding, nil
 }
 
-func (c *Conn) readRemoteAuth(ctx *context.T, tag []byte, binding []byte) error {
+func (c *Conn) readRemoteAuth(ctx *context.T, tag, binding []byte) (map[string]security.Discharge, error) {
 	var rauth *message.Auth
 	for {
 		msg, err := c.mp.readMsg(ctx)
 		if err != nil {
-			return NewErrRecv(ctx, c.remote.String(), err)
+			return nil, NewErrRecv(ctx, c.remote.String(), err)
 		}
 		if rauth, _ = msg.(*message.Auth); rauth != nil {
 			break
 		}
 		if err = c.handleMessage(ctx, msg); err != nil {
-			return err
+			return nil, err
 		}
 	}
+	var rDischarges map[string]security.Discharge
 	if rauth.BlessingsKey != 0 {
 		var err error
 		// TODO(mattr): Make sure we cancel out of this at some point.
-		c.rBlessings, _, err = c.blessingsFlow.get(ctx, rauth.BlessingsKey, rauth.DischargeKey)
+		c.rBlessings, rDischarges, err = c.blessingsFlow.get(ctx, rauth.BlessingsKey, rauth.DischargeKey)
 		if err != nil {
-			return err
+			return nil, err
 		}
 		c.rPublicKey = c.rBlessings.PublicKey()
 	} else {
 		c.rPublicKey = rauth.PublicKey
 	}
 	if c.rPublicKey == nil {
-		return NewErrNoPublicKey(ctx)
+		return nil, NewErrNoPublicKey(ctx)
 	}
 	if !rauth.ChannelBinding.Verify(c.rPublicKey, append(tag, binding...)) {
-		return NewErrInvalidChannelBinding(ctx)
+		return nil, NewErrInvalidChannelBinding(ctx)
 	}
-	return nil
+	return rDischarges, nil
 }
 
 func (c *Conn) refreshDischarges(ctx *context.T) (bkey, dkey uint64, err error) {
diff --git a/runtime/internal/flow/conn/auth_test.go b/runtime/internal/flow/conn/auth_test.go
index c64bc5b..62eb294 100644
--- a/runtime/internal/flow/conn/auth_test.go
+++ b/runtime/internal/flow/conn/auth_test.go
@@ -16,6 +16,7 @@
 	"v.io/v23/verror"
 	vsecurity "v.io/x/ref/lib/security"
 	"v.io/x/ref/runtime/factories/fake"
+	"v.io/x/ref/runtime/internal/flow/flowtest"
 	"v.io/x/ref/test/goroutines"
 	"v.io/x/ref/test/testutil"
 )
@@ -41,7 +42,7 @@
 }
 
 func dialFlow(t *testing.T, ctx *context.T, dc *Conn, b security.Blessings) flow.Flow {
-	df, err := dc.Dial(ctx, makeBFP(b))
+	df, err := dc.Dial(ctx, peerAuthorizer{b})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -129,7 +130,7 @@
 
 	// We should not be able to dial in the other direction, because that flow
 	// manager is not willing to accept flows.
-	_, err := ac.Dial(actx, testBFP)
+	_, err := ac.Dial(actx, flowtest.AllowAllPeersAuthorizer{})
 	if verror.ErrorID(err) != ErrDialingNonServer.ID {
 		t.Errorf("got %v, wanted ErrDialingNonServer", err)
 	}
diff --git a/runtime/internal/flow/conn/close_test.go b/runtime/internal/flow/conn/close_test.go
index 7ba0062..74a6c49 100644
--- a/runtime/internal/flow/conn/close_test.go
+++ b/runtime/internal/flow/conn/close_test.go
@@ -12,6 +12,7 @@
 	"v.io/v23"
 	"v.io/v23/context"
 	_ "v.io/x/ref/runtime/factories/fake"
+	"v.io/x/ref/runtime/internal/flow/flowtest"
 	"v.io/x/ref/test/goroutines"
 )
 
@@ -64,10 +65,10 @@
 	d.Close(ctx, fmt.Errorf("Closing randomly."))
 	<-d.Closed()
 	<-a.Closed()
-	if _, err := d.Dial(ctx, testBFP); err == nil {
+	if _, err := d.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err == nil {
 		t.Errorf("Nil error dialing on dialer")
 	}
-	if _, err := a.Dial(ctx, testBFP); err == nil {
+	if _, err := a.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err == nil {
 		t.Errorf("Nil error dialing on acceptor")
 	}
 }
diff --git a/runtime/internal/flow/conn/conn.go b/runtime/internal/flow/conn/conn.go
index 846fce3..8baf303 100644
--- a/runtime/internal/flow/conn/conn.go
+++ b/runtime/internal/flow/conn/conn.go
@@ -95,6 +95,7 @@
 	conn flow.MsgReadWriteCloser,
 	local, remote naming.Endpoint,
 	versions version.RPCVersionRange,
+	auth flow.PeerAuthorizer,
 	handshakeTimeout time.Duration,
 	handler FlowHandler,
 	events chan<- StatusUpdate) (*Conn, error) {
@@ -116,7 +117,7 @@
 	// TODO(mattr): This scheme for deadlines is nice, but it doesn't
 	// provide for cancellation when ctx is canceled.
 	t := time.AfterFunc(handshakeTimeout, func() { conn.Close() })
-	err := c.dialHandshake(ctx, versions)
+	err := c.dialHandshake(ctx, versions, auth)
 	if stopped := t.Stop(); !stopped {
 		err = verror.NewErrTimeout(ctx)
 	}
@@ -179,7 +180,7 @@
 }
 
 // Dial dials a new flow on the Conn.
-func (c *Conn) Dial(ctx *context.T, fn flow.BlessingsForPeer) (flow.Flow, error) {
+func (c *Conn) Dial(ctx *context.T, auth flow.PeerAuthorizer) (flow.Flow, error) {
 	if c.rBlessings.IsZero() {
 		return nil, NewErrDialingNonServer(ctx)
 	}
@@ -187,10 +188,15 @@
 	if err != nil {
 		return nil, err
 	}
-	blessings, discharges, err := fn(ctx, c.local, c.remote, c.rBlessings, rDischarges)
+	// TODO(suharshs): On the first flow dial, find a way to not call this twice.
+	rbnames, rejected, err := auth.AuthorizePeer(ctx, c.local, c.remote, c.rBlessings, rDischarges)
 	if err != nil {
 		return nil, err
 	}
+	blessings, discharges, err := auth.BlessingsForPeer(ctx, rbnames)
+	if err != nil {
+		return nil, NewErrNoBlessingsForPeer(ctx, rbnames, rejected, err)
+	}
 	bkey, dkey, err := c.blessingsFlow.put(ctx, blessings, discharges)
 	if err != nil {
 		return nil, err
diff --git a/runtime/internal/flow/conn/conn_test.go b/runtime/internal/flow/conn/conn_test.go
index ce1961b..cc18f1c 100644
--- a/runtime/internal/flow/conn/conn_test.go
+++ b/runtime/internal/flow/conn/conn_test.go
@@ -100,7 +100,7 @@
 	q1, q2 := make(chan flow.Flow, 1), make(chan flow.Flow, 1)
 	fh1, fh2 := fh(q1), fh(q2)
 	go func() {
-		d, err := NewDialed(ctx, dmrw, ep, ep, versions, time.Minute, nil, nil)
+		d, err := NewDialed(ctx, dmrw, ep, ep, versions, flowtest.AllowAllPeersAuthorizer{}, time.Minute, nil, nil)
 		if err != nil {
 			panic(err)
 		}
@@ -115,7 +115,7 @@
 	}()
 	d, a := <-dch, <-ach
 	var f flow.Flow
-	if f, err = d.Dial(ctx, flowtest.BlessingsForPeer); err != nil {
+	if f, err = d.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err != nil {
 		t.Fatal(err)
 	}
 	// Write a byte to send the openFlow message.
@@ -126,7 +126,7 @@
 	<-q1
 	// After updating to fh2 the flow should be accepted in fh2.
 	a.UpdateFlowHandler(ctx, fh2)
-	if f, err = d.Dial(ctx, flowtest.BlessingsForPeer); err != nil {
+	if f, err = d.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err != nil {
 		t.Fatal(err)
 	}
 	// Write a byte to send the openFlow message.
diff --git a/runtime/internal/flow/conn/errors.vdl b/runtime/internal/flow/conn/errors.vdl
index 42b56bf..dcd8c02 100644
--- a/runtime/internal/flow/conn/errors.vdl
+++ b/runtime/internal/flow/conn/errors.vdl
@@ -4,6 +4,8 @@
 
 package conn
 
+import "v.io/v23/security"
+
 // These messages are constructed so as to avoid embedding a component/method name
 // and are thus more suitable for inclusion in other verrors.
 // This practice of omitting {1}{2} should be used throughout the flow implementations
@@ -26,4 +28,5 @@
   AcceptorBlessingsMissing() {"en": "The acceptor did not send blessings."}
   UpdatingNilFlowHandler() {"en": "nil flowHandler cannot be updated to non-nil value."}
   BlessingsNotBound() {"en": "blessings not bound to connection remote public key"}
+  NoBlessingsForPeer(peerNames []string, rejected []security.RejectedBlessing, err error) {"en": "no blessings tagged for peer {peerNames}, rejected:{rejected}{:err}"}
 )
diff --git a/runtime/internal/flow/conn/errors.vdl.go b/runtime/internal/flow/conn/errors.vdl.go
index 506f283..f4d3110 100644
--- a/runtime/internal/flow/conn/errors.vdl.go
+++ b/runtime/internal/flow/conn/errors.vdl.go
@@ -12,6 +12,9 @@
 	"v.io/v23/context"
 	"v.io/v23/i18n"
 	"v.io/v23/verror"
+
+	// VDL user imports
+	"v.io/v23/security"
 )
 
 var (
@@ -30,6 +33,7 @@
 	ErrAcceptorBlessingsMissing = verror.Register("v.io/x/ref/runtime/internal/flow/conn.AcceptorBlessingsMissing", verror.NoRetry, "{1:}{2:} The acceptor did not send blessings.")
 	ErrUpdatingNilFlowHandler   = verror.Register("v.io/x/ref/runtime/internal/flow/conn.UpdatingNilFlowHandler", verror.NoRetry, "{1:}{2:} nil flowHandler cannot be updated to non-nil value.")
 	ErrBlessingsNotBound        = verror.Register("v.io/x/ref/runtime/internal/flow/conn.BlessingsNotBound", verror.NoRetry, "{1:}{2:} blessings not bound to connection remote public key")
+	ErrNoBlessingsForPeer       = verror.Register("v.io/x/ref/runtime/internal/flow/conn.NoBlessingsForPeer", verror.NoRetry, "{1:}{2:} no blessings tagged for peer {3}, rejected:{4}{:5}")
 )
 
 func init() {
@@ -48,6 +52,7 @@
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrAcceptorBlessingsMissing.ID), "{1:}{2:} The acceptor did not send blessings.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrUpdatingNilFlowHandler.ID), "{1:}{2:} nil flowHandler cannot be updated to non-nil value.")
 	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrBlessingsNotBound.ID), "{1:}{2:} blessings not bound to connection remote public key")
+	i18n.Cat().SetWithBase(i18n.LangID("en"), i18n.MsgID(ErrNoBlessingsForPeer.ID), "{1:}{2:} no blessings tagged for peer {3}, rejected:{4}{:5}")
 }
 
 // NewErrMissingSetupOption returns an error with the ErrMissingSetupOption ID.
@@ -124,3 +129,8 @@
 func NewErrBlessingsNotBound(ctx *context.T) error {
 	return verror.New(ErrBlessingsNotBound, ctx)
 }
+
+// NewErrNoBlessingsForPeer returns an error with the ErrNoBlessingsForPeer ID.
+func NewErrNoBlessingsForPeer(ctx *context.T, peerNames []string, rejected []security.RejectedBlessing, err error) error {
+	return verror.New(ErrNoBlessingsForPeer, ctx, peerNames, rejected, err)
+}
diff --git a/runtime/internal/flow/conn/lameduck_test.go b/runtime/internal/flow/conn/lameduck_test.go
index b2f1def..67f0be8 100644
--- a/runtime/internal/flow/conn/lameduck_test.go
+++ b/runtime/internal/flow/conn/lameduck_test.go
@@ -12,6 +12,7 @@
 
 	"v.io/v23"
 	"v.io/v23/flow"
+	"v.io/x/ref/runtime/internal/flow/flowtest"
 	"v.io/x/ref/test/goroutines"
 )
 
@@ -41,7 +42,7 @@
 	}()
 
 	// Dial a flow and write it (which causes it to open).
-	f1, err := dc.Dial(ctx, testBFP)
+	f1, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -49,11 +50,11 @@
 		t.Fatal(err)
 	}
 	// Dial more flows, but don't write to them yet.
-	f2, err := dc.Dial(ctx, testBFP)
+	f2, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
 	if err != nil {
 		t.Fatal(err)
 	}
-	f3, err := dc.Dial(ctx, testBFP)
+	f3, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -65,7 +66,7 @@
 	}
 
 	// Now we shouldn't be able to dial from dc because it's in lame duck mode.
-	if _, err := dc.Dial(ctx, testBFP); err == nil {
+	if _, err := dc.Dial(ctx, flowtest.AllowAllPeersAuthorizer{}); err == nil {
 		t.Fatalf("expected an error, got nil")
 	}
 
diff --git a/runtime/internal/flow/conn/util_test.go b/runtime/internal/flow/conn/util_test.go
index eeb7207..1454c60 100644
--- a/runtime/internal/flow/conn/util_test.go
+++ b/runtime/internal/flow/conn/util_test.go
@@ -51,7 +51,7 @@
 		if dflows != nil {
 			handler = fh(dflows)
 		}
-		d, err := NewDialed(dctx, dmrw, ep, ep, versions, time.Minute, handler, events)
+		d, err := NewDialed(dctx, dmrw, ep, ep, versions, flowtest.AllowAllPeersAuthorizer{}, time.Minute, handler, events)
 		if err != nil {
 			panic(err)
 		}
@@ -79,31 +79,28 @@
 		dctx, actx = actx, dctx
 		aflows, dflows = dflows, aflows
 	}
-	df, err := d.Dial(dctx, testBFP)
+	df, err := d.Dial(dctx, flowtest.AllowAllPeersAuthorizer{})
 	if err != nil {
 		t.Fatalf("Unexpected error: %v", err)
 	}
 	return df, aflows, func() { d.Close(dctx, nil); a.Close(actx, nil) }
 }
 
-func testBFP(
+type peerAuthorizer struct {
+	blessings security.Blessings
+}
+
+func (peerAuthorizer) AuthorizePeer(
 	ctx *context.T,
 	localEndpoint, remoteEndpoint naming.Endpoint,
 	remoteBlessings security.Blessings,
 	remoteDischarges map[string]security.Discharge,
-) (security.Blessings, map[string]security.Discharge, error) {
-	return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
+) ([]string, []security.RejectedBlessing, error) {
+	return nil, nil, nil
 }
 
-func makeBFP(in security.Blessings) flow.BlessingsForPeer {
-	return func(
-		ctx *context.T,
-		localEndpoint, remoteEndpoint naming.Endpoint,
-		remoteBlessings security.Blessings,
-		remoteDischarges map[string]security.Discharge,
-	) (security.Blessings, map[string]security.Discharge, error) {
-		dis := securitylib.PrepareDischarges(
-			ctx, in, security.DischargeImpetus{}, time.Minute)
-		return in, dis, nil
-	}
+func (a peerAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+	security.Blessings, map[string]security.Discharge, error) {
+	dis := securitylib.PrepareDischarges(ctx, a.blessings, security.DischargeImpetus{}, time.Minute)
+	return a.blessings, dis, nil
 }
diff --git a/runtime/internal/flow/flowtest/flowtest.go b/runtime/internal/flow/flowtest/flowtest.go
index b9a9907..d330015 100644
--- a/runtime/internal/flow/flowtest/flowtest.go
+++ b/runtime/internal/flow/flowtest/flowtest.go
@@ -98,11 +98,18 @@
 	return nil
 }
 
-func BlessingsForPeer(
+type AllowAllPeersAuthorizer struct{}
+
+func (AllowAllPeersAuthorizer) AuthorizePeer(
 	ctx *context.T,
 	localEndpoint, remoteEndpoint naming.Endpoint,
 	remoteBlessings security.Blessings,
 	remoteDischarges map[string]security.Discharge,
-) (security.Blessings, map[string]security.Discharge, error) {
+) ([]string, []security.RejectedBlessing, error) {
+	return nil, nil, nil
+}
+
+func (AllowAllPeersAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+	security.Blessings, map[string]security.Discharge, error) {
 	return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
 }
diff --git a/runtime/internal/flow/manager/conncache_test.go b/runtime/internal/flow/manager/conncache_test.go
index 4dcc990..f277b84 100644
--- a/runtime/internal/flow/manager/conncache_test.go
+++ b/runtime/internal/flow/manager/conncache_test.go
@@ -296,7 +296,7 @@
 	ach := make(chan *connpackage.Conn)
 	go func() {
 		d, err := connpackage.NewDialed(ctx, dmrw, ep, ep,
-			version.RPCVersionRange{Min: 1, Max: 5}, time.Minute, nil, nil)
+			version.RPCVersionRange{Min: 1, Max: 5}, flowtest.AllowAllPeersAuthorizer{}, time.Minute, nil, nil)
 		if err != nil {
 			t.Fatalf("Unexpected error: %v", err)
 		}
@@ -313,7 +313,7 @@
 	}()
 	conn := <-dch
 	<-ach
-	f, err := conn.Dial(ctx, flowtest.BlessingsForPeer)
+	f, err := conn.Dial(ctx, flowtest.AllowAllPeersAuthorizer{})
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/runtime/internal/flow/manager/manager.go b/runtime/internal/flow/manager/manager.go
index 044ae8a..185ff12 100644
--- a/runtime/internal/flow/manager/manager.go
+++ b/runtime/internal/flow/manager/manager.go
@@ -190,7 +190,7 @@
 			return
 		default:
 		}
-		f, c, err := m.internalDial(ctx, ep, proxyBlessingsForPeer{}.run)
+		f, c, err := m.internalDial(ctx, ep, proxyAuthorizer{})
 		if err != nil {
 			ctx.Error(err)
 			continue
@@ -239,11 +239,20 @@
 	return res.Endpoints, nil
 }
 
-type proxyBlessingsForPeer struct{}
-
 // TODO(suharshs): Figure out what blessings to present here. And present discharges.
-func (proxyBlessingsForPeer) run(ctx *context.T, lep, rep naming.Endpoint, rb security.Blessings,
-	rd map[string]security.Discharge) (security.Blessings, map[string]security.Discharge, error) {
+type proxyAuthorizer struct{}
+
+func (proxyAuthorizer) AuthorizePeer(
+	ctx *context.T,
+	localEndpoint, remoteEndpoint naming.Endpoint,
+	remoteBlessings security.Blessings,
+	remoteDischarges map[string]security.Discharge,
+) ([]string, []security.RejectedBlessing, error) {
+	return nil, nil, nil
+}
+
+func (a proxyAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+	security.Blessings, map[string]security.Discharge, error) {
 	return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
 }
 
@@ -379,17 +388,17 @@
 	}
 }
 
-// Dial creates a Flow to the provided remote endpoint, using 'fn' to
+// Dial creates a Flow to the provided remote endpoint, using 'auth' to
 // determine the blessings that will be sent to the remote end.
 //
 // To maximize re-use of connections, the Manager will also Listen on Dialed
 // connections for the lifetime of the connection.
-func (m *manager) Dial(ctx *context.T, remote naming.Endpoint, fn flow.BlessingsForPeer) (flow.Flow, error) {
-	f, _, err := m.internalDial(ctx, remote, fn)
+func (m *manager) Dial(ctx *context.T, remote naming.Endpoint, auth flow.PeerAuthorizer) (flow.Flow, error) {
+	f, _, err := m.internalDial(ctx, remote, auth)
 	return f, err
 }
 
-func (m *manager) internalDial(ctx *context.T, remote naming.Endpoint, fn flow.BlessingsForPeer) (flow.Flow, *conn.Conn, error) {
+func (m *manager) internalDial(ctx *context.T, remote naming.Endpoint, auth flow.PeerAuthorizer) (flow.Flow, *conn.Conn, error) {
 	// Disallow making connections to ourselves.
 	// TODO(suharshs): Figure out the right thing to do here. We could create a "localflow"
 	// that bypasses auth and is added to the accept queue immediately.
@@ -445,6 +454,7 @@
 			localEndpoint(flowConn, m.rid),
 			remote,
 			version.Supported,
+			auth,
 			handshakeTimeout,
 			fh,
 			events,
@@ -460,7 +470,7 @@
 			return nil, nil, flow.NewErrBadState(ctx, err)
 		}
 	}
-	f, err := c.Dial(ctx, fn)
+	f, err := c.Dial(ctx, auth)
 	if err != nil {
 		return nil, nil, flow.NewErrDialFailed(ctx, err)
 	}
@@ -477,6 +487,7 @@
 			proxyConn.LocalEndpoint(),
 			remote,
 			version.Supported,
+			auth,
 			handshakeTimeout,
 			fh,
 			events)
@@ -490,7 +501,7 @@
 		if err := m.cache.InsertWithRoutingID(c); err != nil {
 			return nil, nil, flow.NewErrBadState(ctx, err)
 		}
-		f, err = c.Dial(ctx, fn)
+		f, err = c.Dial(ctx, auth)
 		if err != nil {
 			proxyConn.Close(ctx, err)
 			return nil, nil, flow.NewErrDialFailed(ctx, err)
diff --git a/runtime/internal/flow/manager/manager_test.go b/runtime/internal/flow/manager/manager_test.go
index c151586..7efc876 100644
--- a/runtime/internal/flow/manager/manager_test.go
+++ b/runtime/internal/flow/manager/manager_test.go
@@ -37,7 +37,7 @@
 	}
 	dm := New(ctx, naming.FixedRoutingID(0x1111))
 
-	testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+	testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
 
 	shutdown()
 	<-am.Closed()
@@ -59,14 +59,14 @@
 		t.Fatalf("got cache size %v, want %v", got, want)
 	}
 	// After dialing a connection the cache should hold one connection.
-	testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+	testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
 	if got, want := len(dm.(*manager).cache.addrCache), 1; got != want {
 		t.Fatalf("got cache size %v, want %v", got, want)
 	}
 	old := dm.(*manager).cache.ridCache[am.RoutingID()]
 	// After dialing another connection the cache should still hold one connection
 	// because the connections should be reused.
-	testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+	testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
 	if got, want := len(dm.(*manager).cache.addrCache), 1; got != want {
 		t.Errorf("got cache size %v, want %v", got, want)
 	}
@@ -89,9 +89,9 @@
 	}
 
 	dm := New(ctx, naming.FixedRoutingID(0x1111))
-	testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+	testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
 	// Now am should be able to make a flow to dm even though dm is not listening.
-	testFlows(t, ctx, am, dm, flowtest.BlessingsForPeer)
+	testFlows(t, ctx, am, dm, flowtest.AllowAllPeersAuthorizer{})
 
 	shutdown()
 	<-am.Closed()
@@ -107,13 +107,13 @@
 		t.Fatal(err)
 	}
 	nulldm := New(ctx, naming.NullRoutingID)
-	_, af := testFlows(t, ctx, nulldm, am, flowtest.BlessingsForPeer)
+	_, af := testFlows(t, ctx, nulldm, am, flowtest.AllowAllPeersAuthorizer{})
 	// Ensure that the remote blessings of the underlying conn of the accepted flow are zero.
 	if rBlessings := af.Conn().(*conn.Conn).RemoteBlessings(); !rBlessings.IsZero() {
 		t.Errorf("got %v, want zero-value blessings", rBlessings)
 	}
 	dm := New(ctx, naming.FixedRoutingID(0x1111))
-	_, af = testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+	_, af = testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
 	// Ensure that the remote blessings of the underlying conn of the accepted flow are
 	// non-zero if we did specify a RoutingID.
 	if rBlessings := af.Conn().(*conn.Conn).RemoteBlessings(); rBlessings.IsZero() {
@@ -135,11 +135,11 @@
 		t.Fatal(err)
 	}
 	dm := New(ctx, naming.FixedRoutingID(0x1111))
-	testFlows(t, ctx, dm, am, flowtest.BlessingsForPeer)
+	testFlows(t, ctx, dm, am, flowtest.AllowAllPeersAuthorizer{})
 
 	am.StopListening(ctx)
 
-	if f, err := dm.Dial(ctx, am.ListeningEndpoints()[0], flowtest.BlessingsForPeer); err == nil {
+	if f, err := dm.Dial(ctx, am.ListeningEndpoints()[0], flowtest.AllowAllPeersAuthorizer{}); err == nil {
 		t.Errorf("dialing a lame duck should fail, but didn't %#v.", f)
 	}
 
@@ -148,10 +148,10 @@
 	<-dm.Closed()
 }
 
-func testFlows(t *testing.T, ctx *context.T, dm, am flow.Manager, bFn flow.BlessingsForPeer) (df, af flow.Flow) {
+func testFlows(t *testing.T, ctx *context.T, dm, am flow.Manager, auth flow.PeerAuthorizer) (df, af flow.Flow) {
 	ep := am.ListeningEndpoints()[0]
 	var err error
-	df, err = dm.Dial(ctx, ep, bFn)
+	df, err = dm.Dial(ctx, ep, auth)
 	if err != nil {
 		t.Fatal(err)
 	}
diff --git a/runtime/internal/rpc/benchmark/simple/main.go b/runtime/internal/rpc/benchmark/simple/main.go
index fb1d52c..fb30f0a 100644
--- a/runtime/internal/rpc/benchmark/simple/main.go
+++ b/runtime/internal/rpc/benchmark/simple/main.go
@@ -58,7 +58,7 @@
 		if ref.RPCTransitionState() >= ref.XServers {
 			m := fmanager.New(nctx, naming.FixedRoutingID(0xc))
 			b.StartTimer()
-			_, err := m.Dial(nctx, serverEP, flowtest.BlessingsForPeer)
+			_, err := m.Dial(nctx, serverEP, flowtest.AllowAllPeersAuthorizer{})
 			if err != nil {
 				ctx.Fatalf("Dial failed: %v", err)
 			}
diff --git a/runtime/internal/rpc/client.go b/runtime/internal/rpc/client.go
index 33db6e7..1d62312 100644
--- a/runtime/internal/rpc/client.go
+++ b/runtime/internal/rpc/client.go
@@ -62,7 +62,7 @@
 	errNoBlessingsForPeer        = reg(".errNoBlessingsForPeer", "no blessings tagged for peer {3}{:4}")
 	errBlessingGrant             = reg(".errBlessingGrant", "failed to grant blessing to server with blessings{:3}")
 	errBlessingAdd               = reg(".errBlessingAdd", "failed to add blessing granted to server{:3}")
-	errServerAuthorizeFailed     = reg(".errServerAuthorizedFailed", "failed to authorize flow with remote blessings{:3} {:4}")
+	errPeerAuthorizeFailed       = reg(".errPeerAuthorizedFailed", "failed to authorize flow with remote blessings{:3} {:4}")
 
 	errPrepareBlessingsAndDischarges = reg(".prepareBlessingsAndDischarges", "failed to prepare blessings and discharges: remote blessings{:3} {:4}")
 
@@ -390,9 +390,9 @@
 		Suffix:           status.suffix,
 	})
 	if err := auth.Authorize(ctx, seccall); err != nil {
-		// We will test for errServerAuthorizeFailed in failedTryCall and report
+		// We will test for errPeerAuthorizeFailed in failedTryCall and report
 		// verror.ErrNotTrusted
-		status.serverErr = suberr(verror.New(errServerAuthorizeFailed, ctx, status.flow.RemoteBlessings(), err))
+		status.serverErr = suberr(verror.New(errPeerAuthorizeFailed, ctx, status.flow.RemoteBlessings(), err))
 		ctx.VI(2).Infof("rpc: Failed to authorize Flow created with server %v: %s", server, status.serverErr.Err)
 		status.flow.Close()
 		status.flow = nil
@@ -630,7 +630,7 @@
 	for _, r := range responses {
 		if r != nil && r.serverErr != nil && r.serverErr.Err != nil {
 			switch verror.ErrorID(r.serverErr.Err) {
-			case stream.ErrNotTrusted.ID, verror.ErrNotTrusted.ID, errServerAuthorizeFailed.ID:
+			case stream.ErrNotTrusted.ID, verror.ErrNotTrusted.ID, errPeerAuthorizeFailed.ID:
 				topLevelError = verror.ErrNotTrusted
 				topLevelAction = verror.NoRetry
 				onlyErrNetwork = false
diff --git a/runtime/internal/rpc/xclient.go b/runtime/internal/rpc/xclient.go
index c96d14a..04cc52d 100644
--- a/runtime/internal/rpc/xclient.go
+++ b/runtime/internal/rpc/xclient.go
@@ -186,8 +186,8 @@
 		status.serverErr = suberr(verror.New(errInvalidEndpoint, ctx))
 		return
 	}
-	bfp := blessingsForPeer{auth, method, suffix, args}.run
-	flow, err := c.flowMgr.Dial(ctx, ep, bfp)
+	peerAuth := peerAuthorizer{auth, method, suffix, args}
+	flow, err := c.flowMgr.Dial(ctx, ep, peerAuth)
 	if err != nil {
 		ctx.VI(2).Infof("rpc: failed to create Flow with %v: %v", server, err)
 		status.serverErr = suberr(err)
@@ -197,7 +197,7 @@
 		// Create a type flow, note that we use c.ctx instead of ctx.
 		// This is because type flows have a longer lifetime than the
 		// main flow being constructed.
-		tflow, err := c.flowMgr.Dial(c.ctx, ep, bfp)
+		tflow, err := c.flowMgr.Dial(c.ctx, ep, peerAuth)
 		if err != nil {
 			status.serverErr = suberr(newErrTypeFlowFailure(ctx, err))
 			flow.Close()
@@ -226,18 +226,18 @@
 	status.flow = flow
 }
 
-type blessingsForPeer struct {
+type peerAuthorizer struct {
 	auth   security.Authorizer
 	method string
 	suffix string
 	args   []interface{}
 }
 
-func (x blessingsForPeer) run(
+func (x peerAuthorizer) AuthorizePeer(
 	ctx *context.T,
 	localEP, remoteEP naming.Endpoint,
 	remoteBlessings security.Blessings,
-	remoteDischarges map[string]security.Discharge) (security.Blessings, map[string]security.Discharge, error) {
+	remoteDischarges map[string]security.Discharge) ([]string, []security.RejectedBlessing, error) {
 	localPrincipal := v23.GetPrincipal(ctx)
 	call := security.NewCall(&security.CallParams{
 		Timestamp:        time.Now(),
@@ -250,16 +250,24 @@
 		RemoteEndpoint:   remoteEP,
 	})
 	if err := x.auth.Authorize(ctx, call); err != nil {
-		return security.Blessings{}, nil, verror.New(errServerAuthorizeFailed, ctx, call.RemoteBlessings(), err)
+		return nil, nil, verror.New(errPeerAuthorizeFailed, ctx, call.RemoteBlessings(), err)
 	}
-	serverB, serverBRejected := security.RemoteBlessingNames(ctx, call)
-	clientB := localPrincipal.BlessingStore().ForPeer(serverB...)
+	peerNames, rejectedPeerNames := security.RemoteBlessingNames(ctx, call)
+	return peerNames, rejectedPeerNames, nil
+}
+
+func (x peerAuthorizer) BlessingsForPeer(ctx *context.T, peerNames []string) (
+	security.Blessings, map[string]security.Discharge, error) {
+	localPrincipal := v23.GetPrincipal(ctx)
+	clientB := localPrincipal.BlessingStore().ForPeer(peerNames...)
 	if clientB.IsZero() {
 		// TODO(ataly, ashankar): We need not error out here and instead can just
 		// send the <nil> blessings to the server.
-		return security.Blessings{}, nil, verror.New(errNoBlessingsForPeer, ctx, serverB, serverBRejected)
+		// TODO(suharshs): Make this a different error when we are making all the vdl errors
+		// in a errors.vdl file.
+		return security.Blessings{}, nil, verror.New(errNoBlessingsForPeer, ctx, nil, nil)
 	}
-	impetus, err := mkDischargeImpetus(serverB, x.method, x.args)
+	impetus, err := mkDischargeImpetus(peerNames, x.method, x.args)
 	if err != nil {
 		return security.Blessings{}, nil, err
 	}
@@ -446,7 +454,7 @@
 	for _, r := range responses {
 		if r != nil && r.serverErr != nil && r.serverErr.Err != nil {
 			switch verror.ErrorID(r.serverErr.Err) {
-			case /*stream.ErrNotTrusted.ID,*/ verror.ErrNotTrusted.ID, errServerAuthorizeFailed.ID:
+			case /*stream.ErrNotTrusted.ID,*/ verror.ErrNotTrusted.ID, errPeerAuthorizeFailed.ID:
 				topLevelError = verror.ErrNotTrusted
 				topLevelAction = verror.NoRetry
 				onlyErrNetwork = false
@@ -601,7 +609,7 @@
 		Suffix:           suffix,
 	})
 	// TODO(suharshs): Its unfortunate that we compute these here and also in the
-	// blessingsForPeer.run function. Find a way to only do this once.
+	// peerAuthorizer struct. Find a way to only do this once.
 	fc.remoteBNames, _ = security.RemoteBlessingNames(ctx, call)
 	var grantedB security.Blessings
 	for _, o := range opts {
diff --git a/services/xproxyd/proxy_test.go b/services/xproxyd/proxy_test.go
index 5343d26..58bd616 100644
--- a/services/xproxyd/proxy_test.go
+++ b/services/xproxyd/proxy_test.go
@@ -184,7 +184,7 @@
 func testEndToEndConnection(t *testing.T, ctx *context.T, dm, am flow.Manager, aep naming.Endpoint) error {
 	// The dialing flow.Manager dials a flow to the accepting flow.Manager.
 	want := "Do you read me?"
-	df, err := dm.Dial(ctx, aep, bfp)
+	df, err := dm.Dial(ctx, aep, allowAllPeersAuthorizer{})
 	if err != nil {
 		return err
 	}
@@ -232,12 +232,19 @@
 	return err
 }
 
-func bfp(
+type allowAllPeersAuthorizer struct{}
+
+func (allowAllPeersAuthorizer) AuthorizePeer(
 	ctx *context.T,
 	localEndpoint, remoteEndpoint naming.Endpoint,
 	remoteBlessings security.Blessings,
 	remoteDischarges map[string]security.Discharge,
-) (security.Blessings, map[string]security.Discharge, error) {
+) ([]string, []security.RejectedBlessing, error) {
+	return nil, nil, nil
+}
+
+func (allowAllPeersAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+	security.Blessings, map[string]security.Discharge, error) {
 	return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
 }
 
diff --git a/services/xproxyd/proxyd.go b/services/xproxyd/proxyd.go
index 1ead875..b0c1941 100644
--- a/services/xproxyd/proxyd.go
+++ b/services/xproxyd/proxyd.go
@@ -137,7 +137,7 @@
 			return nil, err
 		}
 	}
-	fout, err := p.m.Dial(ctx, ep, proxyBlessingsForPeer{}.run)
+	fout, err := p.m.Dial(ctx, ep, proxyAuthorizer{})
 	if err != nil {
 		return nil, err
 	}
@@ -207,7 +207,7 @@
 			return
 		default:
 		}
-		f, err := p.m.Dial(ctx, ep, proxyBlessingsForPeer{}.run)
+		f, err := p.m.Dial(ctx, ep, proxyAuthorizer{})
 		if err != nil {
 			ctx.Error(err)
 			continue
diff --git a/services/xproxyd/util.go b/services/xproxyd/util.go
index e14e23e..a42779d 100644
--- a/services/xproxyd/util.go
+++ b/services/xproxyd/util.go
@@ -75,11 +75,20 @@
 	return blessingOpts
 }
 
-type proxyBlessingsForPeer struct{}
-
 // TODO(suharshs): Figure out what blessings to present here. And present discharges.
-func (proxyBlessingsForPeer) run(ctx *context.T, lep, rep naming.Endpoint, rb security.Blessings,
-	rd map[string]security.Discharge) (security.Blessings, map[string]security.Discharge, error) {
+type proxyAuthorizer struct{}
+
+func (proxyAuthorizer) AuthorizePeer(
+	ctx *context.T,
+	localEndpoint, remoteEndpoint naming.Endpoint,
+	remoteBlessings security.Blessings,
+	remoteDischarges map[string]security.Discharge,
+) ([]string, []security.RejectedBlessing, error) {
+	return nil, nil, nil
+}
+
+func (a proxyAuthorizer) BlessingsForPeer(ctx *context.T, _ []string) (
+	security.Blessings, map[string]security.Discharge, error) {
 	return v23.GetPrincipal(ctx).BlessingStore().Default(), nil, nil
 }