diff --git a/authmate/authmate.go b/authmate/authmate.go
index 6266dbb..2dd7c0a 100644
--- a/authmate/authmate.go
+++ b/authmate/authmate.go
@@ -140,28 +140,17 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
 		return err
 	}
 
-	oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
-	if err != nil {
-		return err
-	}
-
-	a.log.Info("prepare eACL table")
-	bearerRules, err := buildEACLTable(cid, options.EACLRules)
-	if err != nil {
-		return fmt.Errorf("failed to build eacl table: %w", err)
-	}
-
-	gatesData, err := buildBearerTokens(options.NeoFSKey, bearerRules, options.GatesPublicKeys)
+	gatesData, err := createTokens(options, cid)
 	if err != nil {
 		return fmt.Errorf("failed to build bearer token: %w", err)
 	}
 
-	sessionTkn, err := createSessionToken(options, oid)
+	box, secrets, err := accessbox.PackTokens(gatesData)
 	if err != nil {
-		return fmt.Errorf("failed to create session token: %w", err)
+		return err
 	}
 
-	box, secrets, err := accessbox.PackTokens(gatesData, sessionTkn)
+	oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
 	if err != nil {
 		return err
 	}
@@ -291,8 +280,8 @@ func buildContext(rules []byte) (*session.ContainerContext, error) {
 	return sessionCtx, nil
 }
 
-func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.PublicKey) (*token.BearerToken, error) {
-	oid, err := ownerIDFromNeoFSKey(ownerKey)
+func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, gateKey *ecdsa.PublicKey) (*token.BearerToken, error) {
+	oid, err := ownerIDFromNeoFSKey(gateKey)
 	if err != nil {
 		return nil, err
 	}
@@ -305,19 +294,19 @@ func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.
 	return bearerToken, bearerToken.SignToken(key)
 }
 
-func buildBearerTokens(key *ecdsa.PrivateKey, table *eacl.Table, ownerKeys []*ecdsa.PublicKey) ([]*accessbox.GateData, error) {
-	gatesData := make([]*accessbox.GateData, 0, len(ownerKeys))
-	for _, ownerKey := range ownerKeys {
-		tkn, err := buildBearerToken(key, table, ownerKey)
+func buildBearerTokens(key *ecdsa.PrivateKey, table *eacl.Table, gatesKeys []*ecdsa.PublicKey) ([]*token.BearerToken, error) {
+	bearerTokens := make([]*token.BearerToken, 0, len(gatesKeys))
+	for _, gateKey := range gatesKeys {
+		tkn, err := buildBearerToken(key, table, gateKey)
 		if err != nil {
 			return nil, err
 		}
-		gatesData = append(gatesData, accessbox.NewGateData(tkn, ownerKey))
+		bearerTokens = append(bearerTokens, tkn)
 	}
-	return gatesData, nil
+	return bearerTokens, nil
 }
 
-func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext) (*session.Token, error) {
+func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext, gateKey *ecdsa.PublicKey) (*session.Token, error) {
 	tok := session.NewToken()
 	tok.SetContext(ctx)
 	uid, err := uuid.New().MarshalBinary()
@@ -326,19 +315,58 @@ func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.Contai
 	}
 	tok.SetID(uid)
 	tok.SetOwnerID(oid)
+	tok.SetSessionKey(crypto.MarshalPublicKey(gateKey))
 
 	return tok, tok.Sign(key)
 }
 
-func createSessionToken(options *IssueSecretOptions, oid *owner.ID) (*session.Token, error) {
+func buildSessionTokens(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext, gatesKeys []*ecdsa.PublicKey) ([]*session.Token, error) {
+	sessionTokens := make([]*session.Token, 0, len(gatesKeys))
+	for _, gateKey := range gatesKeys {
+		tkn, err := buildSessionToken(key, oid, ctx, gateKey)
+		if err != nil {
+			return nil, err
+		}
+		sessionTokens = append(sessionTokens, tkn)
+	}
+	return sessionTokens, nil
+}
+
+func createTokens(options *IssueSecretOptions, cid *cid.ID) ([]*accessbox.GateData, error) {
+	gates := make([]*accessbox.GateData, len(options.GatesPublicKeys))
+
+	table, err := buildEACLTable(cid, options.EACLRules)
+	if err != nil {
+		return nil, fmt.Errorf("failed to build eacl table: %w", err)
+	}
+	bearerTokens, err := buildBearerTokens(options.NeoFSKey, table, options.GatesPublicKeys)
+	if err != nil {
+		return nil, fmt.Errorf("failed to build bearer tokens: %w", err)
+	}
+	for i, gateKey := range options.GatesPublicKeys {
+		gates[i] = accessbox.NewGateData(gateKey, bearerTokens[i])
+	}
+
 	if options.SessionTkn {
 		sessionRules, err := buildContext(options.ContextRules)
 		if err != nil {
 			return nil, fmt.Errorf("failed to build context for session token: %w", err)
 		}
-		return buildSessionToken(options.NeoFSKey, oid, sessionRules)
+		oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
+		if err != nil {
+			return nil, err
+		}
+
+		sessionTokens, err := buildSessionTokens(options.NeoFSKey, oid, sessionRules, options.GatesPublicKeys)
+		if err != nil {
+			return nil, err
+		}
+		for i, sessionToken := range sessionTokens {
+			gates[i].SessionToken = sessionToken
+		}
 	}
-	return nil, nil
+
+	return gates, nil
 }
 
 func ownerIDFromNeoFSKey(key *ecdsa.PublicKey) (*owner.ID, error) {
diff --git a/creds/accessbox/accessbox.go b/creds/accessbox/accessbox.go
index d792def..d2126f7 100644
--- a/creds/accessbox/accessbox.go
+++ b/creds/accessbox/accessbox.go
@@ -24,12 +24,12 @@ type GateData struct {
 	AccessKey    string
 	BearerToken  *token.BearerToken
 	SessionToken *session.Token
-	OwnerKey     *ecdsa.PublicKey
+	GateKey      *ecdsa.PublicKey
 }
 
-// NewGateData returns GateData from provided bearer token and public key.
-func NewGateData(bearerTkn *token.BearerToken, ownerKey *ecdsa.PublicKey) *GateData {
-	return &GateData{BearerToken: bearerTkn, OwnerKey: ownerKey}
+// NewGateData returns GateData from provided bearer token and public gate key.
+func NewGateData(gateKey *ecdsa.PublicKey, bearerTkn *token.BearerToken) *GateData {
+	return &GateData{GateKey: gateKey, BearerToken: bearerTkn}
 }
 
 // Secrets represents AccessKey and key to encrypt gate tokens.
@@ -50,7 +50,7 @@ func (x *AccessBox) Unmarshal(data []byte) error {
 
 // PackTokens adds a bearer and session tokens to BearerTokens and SessionToken lists respectively.
 // Session token can be nil.
-func PackTokens(gatesData []*GateData, sess *session.Token) (*AccessBox, *Secrets, error) {
+func PackTokens(gatesData []*GateData) (*AccessBox, *Secrets, error) {
 	box := &AccessBox{}
 	ephemeralKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 	if err != nil {
@@ -63,7 +63,7 @@ func PackTokens(gatesData []*GateData, sess *session.Token) (*AccessBox, *Secret
 		return nil, nil, fmt.Errorf("failed to generate accessKey as hex: %w", err)
 	}
 
-	if err := box.addTokens(gatesData, ephemeralKey, sess, secret); err != nil {
+	if err := box.addTokens(gatesData, ephemeralKey, secret); err != nil {
 		return nil, nil, fmt.Errorf("failed to add tokens to accessbox: %w", err)
 	}
 
@@ -89,14 +89,14 @@ func (x *AccessBox) GetTokens(owner *ecdsa.PrivateKey) (*GateData, error) {
 	return nil, fmt.Errorf("no gate data for key  %x was found", ownerKey)
 }
 
-func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *ecdsa.PrivateKey, sess *session.Token, secret []byte) error {
+func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *ecdsa.PrivateKey, secret []byte) error {
 	for i, gate := range gatesData {
 		encBearer, err := gate.BearerToken.Marshal()
 		if err != nil {
 			return fmt.Errorf("%w, sender = %d", err, i)
 		}
 		var encSession []byte
-		if sess != nil {
+		if gate.SessionToken != nil {
 			encSession, err = gate.SessionToken.Marshal()
 			if err != nil {
 				return fmt.Errorf("%w, sender = %d", err, i)
@@ -108,7 +108,7 @@ func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *ecdsa.Private
 		tokens.BearerToken = encBearer
 		tokens.SessionToken = encSession
 
-		boxGate, err := encodeGate(ephemeralKey, gate.OwnerKey, tokens)
+		boxGate, err := encodeGate(ephemeralKey, gate.GateKey, tokens)
 		if err != nil {
 			return err
 		}
@@ -153,7 +153,7 @@ func decodeGate(gate *AccessBox_Gate, owner *ecdsa.PrivateKey, sender *ecdsa.Pub
 		return nil, err
 	}
 
-	gateData := NewGateData(bearerTkn, &owner.PublicKey)
+	gateData := NewGateData(&owner.PublicKey, bearerTkn)
 	gateData.SessionToken = sessionTkn
 	gateData.AccessKey = hex.EncodeToString(tokens.AccessKey)
 	return gateData, nil
diff --git a/creds/accessbox/bearer_token_test.go b/creds/accessbox/bearer_token_test.go
index 22fff57..d9263c7 100644
--- a/creds/accessbox/bearer_token_test.go
+++ b/creds/accessbox/bearer_token_test.go
@@ -6,8 +6,11 @@ import (
 	"crypto/rand"
 	"testing"
 
+	"github.com/google/uuid"
 	"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
+	"github.com/nspcc-dev/neofs-api-go/pkg/session"
 	"github.com/nspcc-dev/neofs-api-go/pkg/token"
+	crypto "github.com/nspcc-dev/neofs-crypto"
 	"github.com/stretchr/testify/require"
 )
 
@@ -56,8 +59,8 @@ func Test_bearer_token_in_access_box(t *testing.T) {
 	tkn.SetEACLTable(eacl.NewTable())
 	require.NoError(t, tkn.SignToken(sec))
 
-	gate := NewGateData(tkn, &cred.PublicKey)
-	box, _, err = PackTokens([]*GateData{gate}, nil)
+	gate := NewGateData(&cred.PublicKey, tkn)
+	box, _, err = PackTokens([]*GateData{gate})
 	require.NoError(t, err)
 
 	data, err := box.Marshal()
@@ -72,6 +75,44 @@ func Test_bearer_token_in_access_box(t *testing.T) {
 	require.Equal(t, tkn, tkns.BearerToken)
 }
 
+func Test_session_token_in_access_box(t *testing.T) {
+	var (
+		box  *AccessBox
+		box2 AccessBox
+		tkn  = session.NewToken()
+	)
+
+	sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	require.NoError(t, err)
+
+	cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	require.NoError(t, err)
+
+	tok := session.NewToken()
+	tok.SetContext(session.NewContainerContext())
+	uid, err := uuid.New().MarshalBinary()
+	require.NoError(t, err)
+	tok.SetID(uid)
+	tok.SetSessionKey(crypto.MarshalPublicKey(&sec.PublicKey))
+	require.NoError(t, tkn.Sign(sec))
+
+	gate := NewGateData(&cred.PublicKey, token.NewBearerToken())
+	gate.SessionToken = tkn
+	box, _, err = PackTokens([]*GateData{gate})
+	require.NoError(t, err)
+
+	data, err := box.Marshal()
+	require.NoError(t, err)
+
+	err = box2.Unmarshal(data)
+	require.NoError(t, err)
+
+	tkns, err := box2.GetTokens(cred)
+	require.NoError(t, err)
+
+	require.Equal(t, tkn, tkns.SessionToken)
+}
+
 func Test_accessbox_multiple_keys(t *testing.T) {
 	var (
 		box *AccessBox
@@ -92,12 +133,12 @@ func Test_accessbox_multiple_keys(t *testing.T) {
 			cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 			require.NoError(t, err)
 
-			gates = append(gates, NewGateData(tkn, &cred.PublicKey))
+			gates = append(gates, NewGateData(&cred.PublicKey, tkn))
 			keys = append(keys, cred)
 		}
 	}
 
-	box, _, err = PackTokens(gates, nil)
+	box, _, err = PackTokens(gates)
 	require.NoError(t, err)
 
 	for i, k := range keys {
@@ -125,8 +166,8 @@ func Test_unknown_key(t *testing.T) {
 	tkn.SetEACLTable(eacl.NewTable())
 	require.NoError(t, tkn.SignToken(sec))
 
-	gate := NewGateData(tkn, &cred.PublicKey)
-	box, _, err = PackTokens([]*GateData{gate}, nil)
+	gate := NewGateData(&cred.PublicKey, tkn)
+	box, _, err = PackTokens([]*GateData{gate})
 	require.NoError(t, err)
 
 	_, err = box.GetTokens(wrongCred)