Repository: TBD54566975/ssi-service
Pull request #376 (2023-04-10 23:11:41)

Uptake latest SDK: Adding support for KIDs
# Overview
- Integrated key ids (kids) everywhere
- noted some future places for refactoring
- updated some error messages along the way

codecov-commenter: ## [Codecov](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) Report
> Merging [#376](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (8192652) into [main](https://codecov.io/gh/TBD54566975/ssi-service/commit/35eb2e474154d45c0cd6582560e04cc3b1a6f65f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (35eb2e4) will **decrease** coverage by `0.11%`.
> The diff coverage is `14.17%`.

```diff
@@            Coverage Diff             @@
##             main     #376      +/-   ##
==========================================
- Coverage   20.46%   20.35%   -0.11%     
==========================================
  Files          48       48              
  Lines        5454     5403      -51     
==========================================
- Hits         1116     1100      -16     
+ Misses       4172     4139      -33     
+ Partials      166      164       -2     
```


| [Impacted Files](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) | Coverage Δ | |
|---|---|---|
| [integration/common.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-aW50ZWdyYXRpb24vY29tbW9uLmdv) | `0.00% <0.00%> (ø)` | |
| [internal/did/access.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-aW50ZXJuYWwvZGlkL2FjY2Vzcy5nbw==) | `0.00% <0.00%> (-16.37%)` | :arrow_down: |
| [pkg/server/router/credential.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvY3JlZGVudGlhbC5nbw==) | `3.47% <0.00%> (-0.02%)` | :arrow_down: |
| [pkg/server/router/presentation.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvcHJlc2VudGF0aW9uLmdv) | `3.37% <0.00%> (-0.02%)` | :arrow_down: |
| [pkg/server/router/schema.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvc2NoZW1hLmdv) | `8.69% <0.00%> (-0.50%)` | :arrow_down: |
| [pkg/server/server.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9zZXJ2ZXIuZ28=) | `81.06% <0.00%> (ø)` | |
| [pkg/service/credential/model.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZpY2UvY3JlZGVudGlhbC9tb2RlbC5nbw==) | `0.00% <ø> (ø)` | |
| [pkg/service/credential/service.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZpY2UvY3JlZGVudGlhbC9zZXJ2aWNlLmdv) | `0.00% <0.00%> (ø)` | |
| [pkg/service/credential/storage.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZpY2UvY3JlZGVudGlhbC9zdG9yYWdlLmdv) | `1.68% <0.00%> (-0.01%)` | :arrow_down: |
| [pkg/service/did/key.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZpY2UvZGlkL2tleS5nbw==) | `0.00% <0.00%> (ø)` | |
| ... and [6 more](https://codecov.io/gh/TBD54566975/ssi-service/pull/376?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975)

decentralgabe: since a few APIs have changed to include `kid` the end to end test will be broken until after this merge. I opened https://github.com/TBD54566975/web5-components-tests/issues/17 to track

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2591474..191be51 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
       - name: Set up Go
         uses: actions/setup-go@v3
         with:
-          go-version: 1.20.2
+          go-version: 1.20.3
           cache: true
 
       - name: Install Mage
@@ -37,7 +37,7 @@ jobs:
     - name: Set up Go
       uses: actions/setup-go@v3
       with:
-        go-version: 1.20.2
+        go-version: 1.20.3
         cache: true
 
     - name: Install mage
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 2075916..019470b 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -20,7 +20,7 @@ jobs:
       - name: Set up Go
         uses: actions/setup-go@v3
         with:
-          go-version: 1.20.2
+          go-version: 1.20.3
           cache: true
 
       - name: golangci-lint
diff --git a/.github/workflows/steelthread.yml b/.github/workflows/steelthread.yml
index 8b75e54..14df4f8 100644
--- a/.github/workflows/steelthread.yml
+++ b/.github/workflows/steelthread.yml
@@ -20,7 +20,7 @@ jobs:
     - name: Set up Go
       uses: actions/setup-go@v3
       with:
-        go-version: 1.20.2
+        go-version: 1.20.3
         cache: true
 
     - name: Install Mage
diff --git a/.github/workflows/swagger-doc.yml b/.github/workflows/swagger-doc.yml
index 48333b2..dad0c32 100644
--- a/.github/workflows/swagger-doc.yml
+++ b/.github/workflows/swagger-doc.yml
@@ -15,7 +15,7 @@ jobs:
     - name: Set up Go
       uses: actions/setup-go@v3
       with:
-        go-version: 1.20.2
+        go-version: 1.20.3
         cache: true
 
     - name: Install Mage
diff --git a/build/Dockerfile b/build/Dockerfile
index ca6732d..3078a4b 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.20.2-alpine
+FROM golang:1.20.3-alpine
 
 # Create directory for our app inside the container
 WORKDIR /app
diff --git a/go.mod b/go.mod
index 7cd9aa9..afb73cd 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.20
 
 require (
 	github.com/BurntSushi/toml v1.2.1
-	github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230401051839-bca28f8b0fea
+	github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410220001-cbd9818e8367
 	github.com/alicebob/miniredis/v2 v2.30.1
 	github.com/ardanlabs/conf v1.5.0
 	github.com/benbjohnson/clock v1.3.0
diff --git a/go.sum b/go.sum
index 2d58dcd..5fce8ee 100644
--- a/go.sum
+++ b/go.sum
@@ -29,6 +29,16 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
 github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230401051839-bca28f8b0fea h1:+0dl8nqYYkewqiiYKxhk3RK7ivOOzweeYa08DFOU3fE=
 github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230401051839-bca28f8b0fea/go.mod h1:9SNGqEkRihpNbgilFDRRmgi8Gi/l7/l0eyO+3Prubro=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230407190356-7a28bcc93aa7 h1:0hpEShDTX43lmVcN7Q5pTupUq7za72ElaK1MdjybzMk=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230407190356-7a28bcc93aa7/go.mod h1:Ro9+HDADuYcLnCYKIL8pu92XWITKetTPOqfwLThplO0=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410182513-ac2084ff8094 h1:N0t7vG6XixCrav2vte6wLqEUWH3x2iabic5Yqdf3mdo=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410182513-ac2084ff8094/go.mod h1:Ro9+HDADuYcLnCYKIL8pu92XWITKetTPOqfwLThplO0=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410184545-8e1086c3822a h1:QwoAvRTQkYUlwKuuC256FIgUm0YT6NGb5X2hekNqTaU=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410184545-8e1086c3822a/go.mod h1:Ro9+HDADuYcLnCYKIL8pu92XWITKetTPOqfwLThplO0=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410205511-7a5730cdd712 h1:err5jP/g05qrJTn71t2qr8YX24G4w+BbPEWU2pDGRZI=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410205511-7a5730cdd712/go.mod h1:Ro9+HDADuYcLnCYKIL8pu92XWITKetTPOqfwLThplO0=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410220001-cbd9818e8367 h1:dYkvkaLS7fLBPy06PDal2DZBHYiD79Z//1sOjaojR1U=
+github.com/TBD54566975/ssi-sdk v0.0.3-alpha.0.20230410220001-cbd9818e8367/go.mod h1:Ro9+HDADuYcLnCYKIL8pu92XWITKetTPOqfwLThplO0=
 github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
 github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
diff --git a/integration/common.go b/integration/common.go
index 8e9f3ee..eb3d1b0 100644
--- a/integration/common.go
+++ b/integration/common.go
@@ -99,6 +99,7 @@ func CreateKYCSchema() (string, error) {
 
 type credInputParams struct {
 	IssuerID  string
+	IssuerKID string
 	SchemaID  string
 	SubjectID string
 }
@@ -171,8 +172,9 @@ func resolveTemplate(input any, fileName string) (string, error) {
 }
 
 type credManifestParams struct {
-	IssuerID string
-	SchemaID string
+	IssuerID  string
+	IssuerKID string
+	SchemaID  string
 }
 
 func CreateCredentialManifest(credManifest credManifestParams) (string, error) {
@@ -194,7 +196,7 @@ type credApplicationParams struct {
 	ManifestID   string
 }
 
-func CreateCredentialApplicationJWT(credApplication credApplicationParams, credentialJWT, aliceDID, aliceDIDPrivateKey string) (string, error) {
+func CreateCredentialApplicationJWT(credApplication credApplicationParams, credentialJWT, aliceDID, aliceKID, aliceDIDPrivateKey string) (string, error) {
 	logrus.Println("\n\nCreate an Application JWT:")
 	applicationJSON, err := resolveTemplate(credApplication, "application-input.json")
 	if err != nil {
@@ -211,7 +213,7 @@ func CreateCredentialApplicationJWT(credApplication credApplicationParams, crede
 		return "", errors.Wrap(err, "bytes to priv key")
 	}
 
-	signer, err := keyaccess.NewJWKKeyAccess(aliceDID, alicePrivKey)
+	signer, err := keyaccess.NewJWKKeyAccess(aliceDID, aliceKID, alicePrivKey)
 	if err != nil {
 		return "", errors.Wrap(err, "creating signer")
 	}
@@ -227,7 +229,8 @@ func CreateCredentialApplicationJWT(credApplication credApplicationParams, crede
 }
 
 type definitionParams struct {
-	Author string
+	Author    string
+	AuthorKID string
 }
 
 func CreatePresentationDefinition(params definitionParams) (string, error) {
@@ -257,6 +260,7 @@ func ReviewSubmission(id string) (string, error) {
 
 type submissionParams struct {
 	HolderID      string
+	HolderKID     string
 	DefinitionID  string
 	CredentialJWT string
 	SubmissionID  string
@@ -283,7 +287,7 @@ func CreateSubmission(params submissionParams, holderPrivateKey string) (string,
 		return "", errors.Wrap(err, "bytes to priv key")
 	}
 
-	signer, err := keyaccess.NewJWKKeyAccess(params.HolderID, pkCrypto)
+	signer, err := keyaccess.NewJWKKeyAccess(params.HolderID, params.HolderKID, pkCrypto)
 	if err != nil {
 		return "", errors.Wrap(err, "creating signer")
 	}
@@ -479,6 +483,7 @@ type issuanceTemplateParams struct {
 	SchemaID   string
 	ManifestID string
 	IssuerID   string
+	IssuerKID  string
 }
 
 func CreateIssuanceTemplate(params issuanceTemplateParams) (string, error) {
diff --git a/internal/credential/model.go b/internal/credential/model.go
index 4730a24..f0fec06 100644
--- a/internal/credential/model.go
+++ b/internal/credential/model.go
@@ -17,6 +17,7 @@ import (
 type Container struct {
 	// Credential ID
 	ID            string
+	IssuerKID     string
 	Credential    *credential.VerifiableCredential
 	CredentialJWT *keyaccess.JWT
 	Revoked       bool
@@ -45,7 +46,7 @@ func (c Container) HasJWTCredential() bool {
 
 // NewCredentialContainerFromJWT attempts to parse a VC-JWT credential from a string into a Container
 func NewCredentialContainerFromJWT(credentialJWT string) (*Container, error) {
-	cred, err := signing.ParseVerifiableCredentialFromJWT(credentialJWT)
+	_, _, cred, err := signing.ParseVerifiableCredentialFromJWT(credentialJWT)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not parse credential from JWT")
 	}
@@ -115,3 +116,14 @@ func NewCredentialContainerFromArray(creds []any) ([]Container, error) {
 	}
 	return containers, nil
 }
+
+// CopyCredential copies a credential into a new credential
+func CopyCredential(c credential.VerifiableCredential) (*credential.VerifiableCredential, error) {
+	var cred credential.VerifiableCredential
+	credBytes, err := json.Marshal(c)
+	if err != nil {
+		return nil, err
+	}
+	err = json.Unmarshal(credBytes, &cred)
+	return &cred, err
+}
diff --git a/internal/credential/verification.go b/internal/credential/verification.go
index d7317a8..8c718f9 100644
--- a/internal/credential/verification.go
+++ b/internal/credential/verification.go
@@ -2,14 +2,15 @@ package credential
 
 import (
 	"context"
-	"crypto"
 	"fmt"
 
 	credsdk "github.com/TBD54566975/ssi-sdk/credential"
 	"github.com/TBD54566975/ssi-sdk/credential/signing"
 	"github.com/TBD54566975/ssi-sdk/credential/verification"
+	"github.com/TBD54566975/ssi-sdk/crypto"
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	"github.com/goccy/go-json"
+	"github.com/lestrrat-go/jwx/jws"
 	"github.com/pkg/errors"
 
 	didint "github.com/tbd54566975/ssi-service/internal/did"
@@ -52,30 +53,32 @@ func NewCredentialVerifier(didResolver didsdk.Resolver, schemaResolver schema.Re
 // a set of static verification checks on the credential as per the credential service's configuration.
 func (v Verifier) VerifyJWTCredential(ctx context.Context, token keyaccess.JWT) error {
 	// first, parse the token to see if it contains a valid verifiable credential
-	cred, err := signing.ParseVerifiableCredentialFromJWT(token.String())
+	gotHeaders, _, cred, err := signing.ParseVerifiableCredentialFromJWT(token.String())
 	if err != nil {
 		return util.LoggingErrorMsg(err, "could not parse credential from JWT")
 	}
 
-	// TODO(gabe) support resolving keys by ID
-	jwtKID, err := util.GetKeyIDFromJWT(token)
-	if err != nil {
-		return util.LoggingErrorMsg(err, "could not get key ID from JWT")
+	kid, ok := gotHeaders.Get(jws.KeyIDKey)
+	if !ok {
+		return util.LoggingNewError("could not find key ID in JWT headers")
+	}
+	jwtKID, ok := kid.(string)
+	if !ok {
+		return util.LoggingNewErrorf("could not convert key ID to string: %v", kid)
 	}
 
 	// resolve the issuer's key material
-	kid, pubKey, err := v.resolveCredentialIssuerKey(ctx, *cred)
+	issuerDID, ok := cred.Issuer.(string)
+	if !ok {
+		return util.LoggingNewErrorf("could not convert issuer to string: %v", cred.Issuer)
+	}
+	pubKey, err := didint.ResolveKeyForDID(ctx, v.didResolver, issuerDID, jwtKID)
 	if err != nil {
 		return util.LoggingError(err)
 	}
 
-	if jwtKID != kid {
-		errMsg := fmt.Sprintf("JWT<%s> and credential<%s> key IDs do not match", jwtKID, kid)
-		return util.LoggingErrorMsg(err, errMsg)
-	}
-
 	// construct a signature verifier from the verification information
-	verifier, err := keyaccess.NewJWKKeyAccessVerifier(kid, pubKey)
+	verifier, err := keyaccess.NewJWKKeyAccessVerifier(issuerDID, jwtKID, pubKey)
 	if err != nil {
 		return util.LoggingErrorMsg(err, "could not create verifier")
 	}
@@ -92,15 +95,29 @@ func (v Verifier) VerifyJWTCredential(ctx context.Context, token keyaccess.JWT)
 // a set of static verification checks on the credential as per the credential service's configuration.
 func (v Verifier) VerifyDataIntegrityCredential(ctx context.Context, credential credsdk.VerifiableCredential) error {
 	// resolve the issuer's key material
-	kid, pubKey, err := v.resolveCredentialIssuerKey(ctx, credential)
+	issuer, ok := credential.Issuer.(string)
+	if !ok {
+		return util.LoggingNewErrorf("could not convert issuer to string: %v", credential.Issuer)
+	}
+
+	maybeVerificationMethod, err := getKeyFromProof(*credential.Proof, "verificationMethod")
+	if err != nil {
+		return util.LoggingErrorMsg(err, "could not get verification method from proof")
+	}
+	verificationMethod, ok := maybeVerificationMethod.(string)
+	if !ok {
+		return util.LoggingNewErrorf("could not convert verification method to string: %v", maybeVerificationMethod)
+	}
+
+	pubKey, err := didint.ResolveKeyForDID(ctx, v.didResolver, issuer, verificationMethod)
 	if err != nil {
 		return util.LoggingError(err)
 	}
 
 	// construct a signature verifier from the verification information
-	verifier, err := keyaccess.NewDataIntegrityKeyAccess(kid, pubKey)
+	verifier, err := keyaccess.NewDataIntegrityKeyAccess(issuer, verificationMethod, pubKey)
 	if err != nil {
-		errMsg := fmt.Sprintf("could not create verifier for kid %s", kid)
+		errMsg := fmt.Sprintf("could not create verifier for kid %s", verificationMethod)
 		return util.LoggingErrorMsg(err, errMsg)
 	}
 
@@ -112,15 +129,41 @@ func (v Verifier) VerifyDataIntegrityCredential(ctx context.Context, credential
 	return v.staticVerificationChecks(ctx, credential)
 }
 
+func getKeyFromProof(proof crypto.Proof, key string) (any, error) {
+	proofBytes, err := json.Marshal(proof)
+	if err != nil {
+		return nil, err
+	}
+	var proofMap map[string]any
+	if err = json.Unmarshal(proofBytes, &proofMap); err != nil {
+		return nil, err
+	}
+	return proofMap[key], nil
+}
+
 func (v Verifier) VerifyJWT(ctx context.Context, did string, token keyaccess.JWT) error {
-	// resolve the did's key material
-	kid, pubKey, err := didint.ResolveKeyForDID(ctx, v.didResolver, did)
+	// parse headers
+	headers, err := keyaccess.GetJWTHeaders([]byte(token))
+	if err != nil {
+		return util.LoggingErrorMsg(err, "could not parse JWT headers")
+	}
+	jwtKID, ok := headers.Get(jws.KeyIDKey)
+	if !ok {
+		return util.LoggingNewError("JWT does not contain a kid")
+	}
+	kid, ok := jwtKID.(string)
+	if !ok {
+		return util.LoggingNewError("JWT kid is not a string")
+	}
+
+	// resolve key material from the DID
+	pubKey, err := didint.ResolveKeyForDID(ctx, v.didResolver, did, kid)
 	if err != nil {
 		return util.LoggingError(err)
 	}
 
 	// construct a signature verifier from the verification information
-	verifier, err := keyaccess.NewJWKKeyAccessVerifier(kid, pubKey)
+	verifier, err := keyaccess.NewJWKKeyAccessVerifier(did, kid, pubKey)
 	if err != nil {
 		return util.LoggingErrorMsgf(err, "could not create verifier for kid %s", kid)
 	}
@@ -133,14 +176,6 @@ func (v Verifier) VerifyJWT(ctx context.Context, did string, token keyaccess.JWT
 	return nil
 }
 
-// resolveCredentialIssuerKey resolves the issuer's public key from the credential's issuer DID.
-// TODO(gabe): perhaps this should be a verification method referenced on the proof object, not the issuer
-// TODO(gabe): support issuers that are not strings, but objects
-func (v Verifier) resolveCredentialIssuerKey(ctx context.Context, credential credsdk.VerifiableCredential) (kid string, pubKey crypto.PublicKey, err error) {
-	issuerDID := credential.Issuer.(string)
-	return didint.ResolveKeyForDID(ctx, v.didResolver, issuerDID)
-}
-
 // staticVerificationChecks runs a set of static verification checks on the credential as per the credential
 // service's configuration, such as checking the credential's schema, expiration, and object validity.
 func (v Verifier) staticVerificationChecks(ctx context.Context, credential credsdk.VerifiableCredential) error {
diff --git a/internal/did/access.go b/internal/did/access.go
index ca0ceca..c0613dc 100644
--- a/internal/did/access.go
+++ b/internal/did/access.go
@@ -3,125 +3,47 @@ package did
 import (
 	"context"
 	"crypto"
-	"fmt"
 
-	"github.com/TBD54566975/ssi-sdk/cryptosuite"
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	"github.com/TBD54566975/ssi-sdk/util"
-	"github.com/goccy/go-json"
-	"github.com/lestrrat-go/jwx/jwk"
-	"github.com/mr-tron/base58"
-	"github.com/multiformats/go-multibase"
-	"github.com/multiformats/go-varint"
 	"github.com/pkg/errors"
-	"github.com/sirupsen/logrus"
 
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 )
 
-// GetVerificationInformation resolves a DID and provides a kid and public key needed for data verification
-// it is possible that a DID has multiple verification methods, in which case a kid must be provided, otherwise
-// resolution will fail.
-func GetVerificationInformation(did didsdk.Document, maybeKID string) (kid string, pubKey crypto.PublicKey, err error) {
-	if did.IsEmpty() {
-		return "", nil, errors.Errorf("did doc: %+v is empty", did)
-	}
-	verificationMethods := did.VerificationMethod
-	if len(verificationMethods) == 0 {
-		return "", nil, errors.Errorf("did doc: %s has no verification methods", did.ID)
-	}
-
-	// handle the case where a kid is provided && there are multiple verification methods
-	if len(verificationMethods) > 1 {
-		if maybeKID == "" {
-			return "", nil, errors.Errorf("kid is required for did: %s, which has multiple verification methods", did.ID)
-		}
-		for _, method := range verificationMethods {
-			if method.ID == maybeKID {
-				kid = method.ID
-				pubKey, err = extractKeyFromVerificationMethod(method)
-				return
-			}
-		}
-	}
-	// TODO(gabe): some DIDs, like did:key have KIDs that aren't used, so we need to know when to use a kid vs the DID
-	kid = did.ID
-	pubKey, err = extractKeyFromVerificationMethod(verificationMethods[0])
-	return
-}
-
-func extractKeyFromVerificationMethod(method didsdk.VerificationMethod) (pubKey crypto.PublicKey, err error) {
-	switch {
-	case method.PublicKeyMultibase != "":
-		pubKeyBytes, multiBaseErr := multibaseToPubKeyBytes(method.PublicKeyMultibase)
-		if multiBaseErr != nil {
-			err = multiBaseErr
-			return
-		}
-		pubKey, err = cryptosuite.PubKeyBytesToTypedKey(pubKeyBytes, method.Type)
-		return
-	case method.PublicKeyBase58 != "":
-		pubKeyDecoded, b58Err := base58.Decode(method.PublicKeyBase58)
-		if b58Err != nil {
-			err = b58Err
-			return
-		}
-		pubKey, err = cryptosuite.PubKeyBytesToTypedKey(pubKeyDecoded, method.Type)
-		return
-	case method.PublicKeyJWK != nil:
-		jwkBytes, jwkErr := json.Marshal(method.PublicKeyJWK)
-		if jwkErr != nil {
-			err = jwkErr
-			return
-		}
-		parsed, parseErr := jwk.ParseKey(jwkBytes)
-		if parseErr != nil {
-			err = parseErr
-			return
-		}
-		if err = parsed.Raw(&pubKey); err != nil {
-			return
-		}
-
-		return
-	}
-	err = errors.New("no public key found in verification method")
-	return
-}
-
-// ResolveKeyForDID resolves a public key from a DID.
-func ResolveKeyForDID(ctx context.Context, resolver didsdk.Resolver, did string) (kid string, pubKey crypto.PublicKey, err error) {
+// ResolveKeyForDID resolves a public key from a DID for a given KID.
+func ResolveKeyForDID(ctx context.Context, resolver didsdk.Resolver, did, kid string) (pubKey crypto.PublicKey, err error) {
 	resolved, err := resolver.Resolve(ctx, did, nil)
 	if err != nil {
 		err = errors.Wrapf(err, "resolving DID: %s", did)
-		return "", nil, err
+		return nil, err
 	}
 
 	// next, get the verification information (key) from the did document
-	kid, pubKey, err = GetVerificationInformation(resolved.Document, "")
+	pubKey, err = didsdk.GetKeyFromVerificationMethod(resolved.Document, kid)
 	if err != nil {
 		err = errors.Wrapf(err, "getting verification information from DID Document: %s", did)
-		return "", nil, err
+		return nil, err
 	}
-	return kid, pubKey, err
+	return pubKey, err
 }
 
 // VerifyTokenFromDID verifies that the information in the token was digitally signed by the public key associated with
 // the public key of the verification method of the did's document. The passed in resolver is used to map from the did
 // to the did document.
-func VerifyTokenFromDID(ctx context.Context, resolver didsdk.Resolver, did string, token keyaccess.JWT) error {
+func VerifyTokenFromDID(ctx context.Context, resolver didsdk.Resolver, did, kid string, token keyaccess.JWT) error {
 	resolved, err := resolver.Resolve(ctx, did)
 	if err != nil {
 		return errors.Wrapf(err, "resolving DID: %s", did)
 	}
 
 	// get the verification information from the DID document
-	kid, pubKey, err := GetVerificationInformation(resolved.Document, "")
+	pubKey, err := didsdk.GetKeyFromVerificationMethod(resolved.Document, kid)
 	if err != nil {
 		return errors.Wrapf(err, "getting verification information from the DID document: %s", did)
 	}
 
-	verifier, err := keyaccess.NewJWKKeyAccessVerifier(kid, pubKey)
+	verifier, err := keyaccess.NewJWKKeyAccessVerifier(did, kid, pubKey)
 	if err != nil {
 		return util.LoggingErrorMsg(err, "could not create application verifier")
 	}
@@ -130,34 +52,3 @@ func VerifyTokenFromDID(ctx context.Context, resolver didsdk.Resolver, did strin
 	}
 	return nil
 }
-
-// multibaseToPubKey converts a multibase encoded public key to public key bytes for known multibase encodings
-func multibaseToPubKeyBytes(mb string) ([]byte, error) {
-	if mb == "" {
-		err := fmt.Errorf("could not decode value: %s", mb)
-		logrus.WithError(err).Error()
-		return nil, err
-	}
-
-	encoding, decoded, err := multibase.Decode(mb)
-	if err != nil {
-		logrus.WithError(err).Error("could not decode did:key")
-		return nil, err
-	}
-	if encoding != didsdk.Base58BTCMultiBase {
-		err = fmt.Errorf("expected %d encoding but found %d", didsdk.Base58BTCMultiBase, encoding)
-		logrus.WithError(err).Error()
-		return nil, err
-	}
-
-	// n = # bytes for the int, which we expect to be two from our multicodec
-	_, n, err := varint.FromUvarint(decoded)
-	if err != nil {
-		return nil, err
-	}
-	if n != 2 {
-		return nil, errors.New("error parsing did:key varint")
-	}
-	pubKeyBytes := decoded[n:]
-	return pubKeyBytes, nil
-}
diff --git a/internal/keyaccess/dataintegrity.go b/internal/keyaccess/dataintegrity.go
index ecbbb2c..442a6e8 100644
--- a/internal/keyaccess/dataintegrity.go
+++ b/internal/keyaccess/dataintegrity.go
@@ -19,9 +19,9 @@ type DataIntegrityKeyAccess struct {
 	cryptosuite.CryptoSuite
 }
 
-// NewDataIntegrityKeyAccess creates a new DataIntegrityKeyAccess object from a key id and private key, generating both
+// NewDataIntegrityKeyAccess creates a new DataIntegrityKeyAccess object from an id, key id, and private key, generating both
 // JSON Web Key Signer and Verifier objects.
-func NewDataIntegrityKeyAccess(kid string, key gocrypto.PrivateKey) (*DataIntegrityKeyAccess, error) {
+func NewDataIntegrityKeyAccess(id, kid string, key gocrypto.PrivateKey) (*DataIntegrityKeyAccess, error) {
 	if kid == "" {
 		return nil, errors.New("kid cannot be empty")
 	}
@@ -32,11 +32,11 @@ func NewDataIntegrityKeyAccess(kid string, key gocrypto.PrivateKey) (*DataIntegr
 	if err != nil {
 		return nil, errors.Wrapf(err, "could not convert private key to JWK: %s", kid)
 	}
-	signer, err := cryptosuite.NewJSONWebKeySigner(kid, *privateKeyJWK, cryptosuite.AssertionMethod)
+	signer, err := cryptosuite.NewJSONWebKeySigner(id, kid, *privateKeyJWK, cryptosuite.AssertionMethod)
 	if err != nil {
 		return nil, errors.Wrapf(err, "could not create JWK signer: %s", kid)
 	}
-	verifier, err := cryptosuite.NewJSONWebKeyVerifier(kid, *publicKeyJWK)
+	verifier, err := cryptosuite.NewJSONWebKeyVerifier(id, kid, *publicKeyJWK)
 	if err != nil {
 		return nil, errors.Wrapf(err, "could not create JWK verifier: %s", kid)
 	}
diff --git a/internal/keyaccess/jwt.go b/internal/keyaccess/jwt.go
index 339e123..1907f6c 100644
--- a/internal/keyaccess/jwt.go
+++ b/internal/keyaccess/jwt.go
@@ -2,11 +2,13 @@ package keyaccess
 
 import (
 	gocrypto "crypto"
+	"fmt"
 
 	"github.com/TBD54566975/ssi-sdk/credential"
 	"github.com/TBD54566975/ssi-sdk/credential/signing"
 	"github.com/TBD54566975/ssi-sdk/crypto"
 	"github.com/goccy/go-json"
+	"github.com/lestrrat-go/jwx/jws"
 	"github.com/pkg/errors"
 )
 
@@ -15,16 +17,19 @@ type JWKKeyAccess struct {
 	*crypto.JWTVerifier
 }
 
-// NewJWKKeyAccess creates a JWKKeyAccess object from a key id and private key, generating both
+// NewJWKKeyAccess creates a JWKKeyAccess object from an id, key id, and private key, generating both
 // JWT Signer and Verifier objects.
-func NewJWKKeyAccess(kid string, key gocrypto.PrivateKey) (*JWKKeyAccess, error) {
+func NewJWKKeyAccess(id, kid string, key gocrypto.PrivateKey) (*JWKKeyAccess, error) {
+	if id == "" {
+		return nil, errors.New("id cannot be empty")
+	}
 	if kid == "" {
 		return nil, errors.New("kid cannot be empty")
 	}
 	if key == nil {
 		return nil, errors.New("key cannot be nil")
 	}
-	signer, err := crypto.NewJWTSigner(kid, key)
+	signer, err := crypto.NewJWTSigner(id, kid, key)
 	if err != nil {
 		return nil, errors.Wrapf(err, "could not create JWK Key Access object for kid: %s, error creating signer", kid)
 	}
@@ -38,15 +43,18 @@ func NewJWKKeyAccess(kid string, key gocrypto.PrivateKey) (*JWKKeyAccess, error)
 	}, nil
 }
 
-// NewJWKKeyAccessVerifier creates JWKKeyAccess object from a key id and public key, generating a JWT Verifier object.
-func NewJWKKeyAccessVerifier(kid string, key gocrypto.PublicKey) (*JWKKeyAccess, error) {
+// NewJWKKeyAccessVerifier creates JWKKeyAccess object from an id, key id, and public key, generating a JWT Verifier object.
+func NewJWKKeyAccessVerifier(id, kid string, key gocrypto.PublicKey) (*JWKKeyAccess, error) {
+	if id == "" {
+		return nil, errors.New("id cannot be empty")
+	}
 	if kid == "" {
 		return nil, errors.New("kid cannot be empty")
 	}
 	if key == nil {
 		return nil, errors.New("key cannot be nil")
 	}
-	verifier, err := crypto.NewJWTVerifier(kid, key)
+	verifier, err := crypto.NewJWTVerifier(id, kid, key)
 	if err != nil {
 		return nil, errors.Wrapf(err, "could not create JWK Key Access object for kid: %s, error creating verifier", kid)
 	}
@@ -125,17 +133,18 @@ func (ka JWKKeyAccess) VerifyVerifiableCredential(token JWT) (*credential.Verifi
 	if token == "" {
 		return nil, errors.New("token cannot be empty")
 	}
-	return signing.VerifyVerifiableCredentialJWT(*ka.JWTVerifier, token.String())
+	_, _, verifiableCredential, err := signing.VerifyVerifiableCredentialJWT(*ka.JWTVerifier, token.String())
+	return verifiableCredential, err
 }
 
-func (ka JWKKeyAccess) SignVerifiablePresentation(presentation credential.VerifiablePresentation) (*JWT, error) {
+func (ka JWKKeyAccess) SignVerifiablePresentation(audience string, presentation credential.VerifiablePresentation) (*JWT, error) {
 	if ka.JWTSigner == nil {
 		return nil, errors.New("cannot sign with nil signer")
 	}
 	if err := presentation.IsValid(); err != nil {
 		return nil, errors.New("cannot sign invalid presentation")
 	}
-	tokenBytes, err := signing.SignVerifiablePresentationJWT(*ka.JWTSigner, presentation)
+	tokenBytes, err := signing.SignVerifiablePresentationJWT(*ka.JWTSigner, signing.JWTVVPParameters{Audience: audience}, presentation)
 	if err != nil {
 		return nil, errors.Wrap(err, "could not sign presentation")
 	}
@@ -146,5 +155,18 @@ func (ka JWKKeyAccess) VerifyVerifiablePresentation(token JWT) (*credential.Veri
 	if token == "" {
 		return nil, errors.New("token cannot be empty")
 	}
-	return signing.VerifyVerifiablePresentationJWT(*ka.JWTVerifier, token.String())
+	_, _, presentation, err := signing.VerifyVerifiablePresentationJWT(*ka.JWTVerifier, token.String())
+	return presentation, err
+}
+
+// GetJWTHeaders returns the headers of a JWT token, assuming there is only one signature.
+func GetJWTHeaders(token []byte) (jws.Headers, error) {
+	msg, err := jws.Parse(token)
+	if err != nil {
+		return nil, err
+	}
+	if len(msg.Signatures()) != 1 {
+		return nil, fmt.Errorf("expected 1 signature, got %d", len(msg.Signatures()))
+	}
+	return msg.Signatures()[0].ProtectedHeaders(), nil
 }
diff --git a/pkg/server/router/credential.go b/pkg/server/router/credential.go
index 9a2d6fb..0287f2d 100644
--- a/pkg/server/router/credential.go
+++ b/pkg/server/router/credential.go
@@ -8,6 +8,7 @@ import (
 	credsdk "github.com/TBD54566975/ssi-sdk/credential"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+
 	credmodel "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
@@ -43,14 +44,17 @@ type CreateCredentialRequest struct {
 	// The issuer id.
 	Issuer string `json:"issuer" validate:"required" example:"did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp"`
 
+	// The KID used to sign the credential
+	IssuerKID string `json:"issuerKid" validate:"required" example:"#z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp"`
+
 	// The subject id.
 	Subject string `json:"subject" validate:"required" example:"did:key:z6MkiTBz1ymuepAQ4HEHYSF1H8quG5GLVVQR3djdX3mDooWp"`
 
 	// A context is optional. If not present, we'll apply default, required context values.
-	Context string `json:"@context"`
+	Context string `json:"@context,omitempty"`
 
-	// A schema is optional. If present, we'll attempt to look it up and validate the data against it.
-	Schema string `json:"schema"`
+	// A schema ID is optional. If present, we'll attempt to look it up and validate the data against it.
+	SchemaID string `json:"schemaId,omitempty"`
 
 	// Claims about the subject. The keys should be predicates (e.g. "alumniOf"), and the values can be any object.
 	Data map[string]any `json:"data" validate:"required" swaggertype:"object,string" example:"alumniOf:did_for_uni"`
@@ -65,15 +69,16 @@ type CreateCredentialRequest struct {
 	// Whether this credential can be suspended. When true, the created VC will have the "credentialStatus"
 	// property set.
 	Suspendable bool `json:"suspendable"`
-	// TODO(gabe) support more capabilities like signature type, format, status, and more.
+	// TODO(gabe) support more capabilities like signature type, format, and more.
 }
 
 func (c CreateCredentialRequest) ToServiceRequest() credential.CreateCredentialRequest {
 	return credential.CreateCredentialRequest{
 		Issuer:      c.Issuer,
+		IssuerKID:   c.IssuerKID,
 		Subject:     c.Subject,
 		Context:     c.Context,
-		JSONSchema:  c.Schema,
+		SchemaID:    c.SchemaID,
 		Data:        c.Data,
 		Expiry:      c.Expiry,
 		Revocable:   c.Revocable,
diff --git a/pkg/server/router/manifest.go b/pkg/server/router/manifest.go
index a2a58fb..22c5fae 100644
--- a/pkg/server/router/manifest.go
+++ b/pkg/server/router/manifest.go
@@ -8,6 +8,7 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
 	"github.com/goccy/go-json"
+
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 
 	"github.com/tbd54566975/ssi-service/internal/credential"
@@ -34,9 +35,7 @@ func NewManifestRouter(s svcframework.Service) (*ManifestRouter, error) {
 	if !ok {
 		return nil, fmt.Errorf("could not create manifest router with service type: %s", s.Type())
 	}
-	return &ManifestRouter{
-		service: manifestService,
-	}, nil
+	return &ManifestRouter{service: manifestService}, nil
 }
 
 // CreateManifestRequest is the request body for creating a manifest, which populates all remaining fields
@@ -45,6 +44,7 @@ type CreateManifestRequest struct {
 	Name                   *string                          `json:"name,omitempty"`
 	Description            *string                          `json:"description,omitempty"`
 	IssuerDID              string                           `json:"issuerDid" validate:"required"`
+	IssuerKID              string                           `json:"issuerKid" validate:"required"`
 	IssuerName             *string                          `json:"issuerName,omitempty"`
 	ClaimFormat            *exchange.ClaimFormat            `json:"format" validate:"required,dive"`
 	OutputDescriptors      []manifestsdk.OutputDescriptor   `json:"outputDescriptors" validate:"required,dive"`
@@ -56,6 +56,7 @@ func (c CreateManifestRequest) ToServiceRequest() model.CreateManifestRequest {
 		Name:                   c.Name,
 		Description:            c.Description,
 		IssuerDID:              c.IssuerDID,
+		IssuerKID:              c.IssuerKID,
 		IssuerName:             c.IssuerName,
 		OutputDescriptors:      c.OutputDescriptors,
 		ClaimFormat:            c.ClaimFormat,
@@ -227,15 +228,14 @@ const (
 	verifiableCredentialsJSONProperty = "verifiableCredentials"
 )
 
-func (sar SubmitApplicationRequest) ToServiceRequest() (*model.SubmitApplicationRequest, error) {
-	signature, token, err := util.ParseJWT(sar.ApplicationJWT)
+func (sar SubmitApplicationRequest) toServiceRequest() (*model.SubmitApplicationRequest, error) {
+	_, token, err := util.ParseJWT(sar.ApplicationJWT)
 	if err != nil {
-		logrus.WithError(err).Error("could not parse application JWT")
-		return nil, err
+		return nil, util.LoggingErrorMsg(err, "could not parse application JWT")
 	}
-	kid := signature.ProtectedHeaders().KeyID()
-	if kid == "" {
-		return nil, errors.New("Credential Application token missing kid")
+	iss := token.Issuer()
+	if iss == "" {
+		return nil, util.LoggingNewError("credential application token missing iss")
 	}
 
 	// make sure the known properties are present (Application and Credentials)
@@ -250,9 +250,7 @@ func (sar SubmitApplicationRequest) ToServiceRequest() (*model.SubmitApplication
 	}
 	creds, ok = credentials.([]any)
 	if !ok {
-		errMsg := fmt.Sprintf("could not parse Credential Application token, %s is not an array", vcsJSONProperty)
-		logrus.Errorf("%s: %s", errMsg, credentials)
-		return nil, errors.New(errMsg)
+		return nil, util.LoggingNewErrorf("could not parse Credential Application token, %s is not an array", vcsJSONProperty)
 	}
 
 	// marshal known properties into their respective types
@@ -266,9 +264,7 @@ func (sar SubmitApplicationRequest) ToServiceRequest() (*model.SubmitApplication
 	}
 	var application manifestsdk.CredentialApplication
 	if err = json.Unmarshal(applicationTokenBytes, &application); err != nil {
-		errMsg := "could not reconstruct Credential Application"
-		logrus.WithError(err).Error(errMsg)
-		return nil, errors.Wrap(err, errMsg)
+		return nil, util.LoggingErrorMsg(err, "could not reconstruct Credential Application")
 	}
 
 	credContainer, err := credential.NewCredentialContainerFromArray(creds)
@@ -276,7 +272,7 @@ func (sar SubmitApplicationRequest) ToServiceRequest() (*model.SubmitApplication
 		return nil, errors.Wrap(err, "could not parse submitted credentials")
 	}
 	return &model.SubmitApplicationRequest{
-		ApplicantDID:    kid,
+		ApplicantDID:    iss,
 		Application:     application,
 		Credentials:     credContainer,
 		ApplicationJWT:  sar.ApplicationJWT,
@@ -314,7 +310,7 @@ func (mr ManifestRouter) SubmitApplication(ctx context.Context, w http.ResponseW
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
 
-	req, err := request.ToServiceRequest()
+	req, err := request.toServiceRequest()
 	if err != nil {
 		errMsg := "invalid submit application request"
 		logrus.WithError(err).Error(errMsg)
diff --git a/pkg/server/router/presentation.go b/pkg/server/router/presentation.go
index f2f67d3..7d1da19 100644
--- a/pkg/server/router/presentation.go
+++ b/pkg/server/router/presentation.go
@@ -10,6 +10,8 @@ import (
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+	"go.einride.tech/aip/filtering"
+
 	credint "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
@@ -17,7 +19,6 @@ import (
 	svcframework "github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/model"
-	"go.einride.tech/aip/filtering"
 )
 
 type PresentationRouter struct {
@@ -43,9 +44,11 @@ type CreatePresentationDefinitionRequest struct {
 	SubmissionRequirements []exchange.SubmissionRequirement `json:"submissionRequirements,omitempty" validate:"omitempty,dive"`
 
 	// DID of the author of this presentation definition. The DID must have been previously created with the DID API,
-	// or the PrivateKey must have been added independently. The privateKey associated to this DID will be used to
-	// sign an envelope that contains the created presentation definition.
+	// or the PrivateKey must have been added independently.
 	Author string `json:"author" validate:"required"`
+	// The privateKey associated with the KID will be used to sign an envelope that contains
+	// the created presentation definition.
+	AuthorKID string `json:"authorKid" validate:"required"`
 }
 
 type CreatePresentationDefinitionResponse struct {
@@ -86,10 +89,11 @@ func (pr PresentationRouter) CreateDefinition(ctx context.Context, w http.Respon
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
-	serviceResp, err := pr.service.CreatePresentationDefinition(
-		ctx,
-		model.CreatePresentationDefinitionRequest{PresentationDefinition: *def, Author: request.Author},
-	)
+	serviceResp, err := pr.service.CreatePresentationDefinition(ctx, model.CreatePresentationDefinitionRequest{
+		PresentationDefinition: *def,
+		Author:                 request.Author,
+		AuthorKID:              request.AuthorKID,
+	})
 	if err != nil {
 		logrus.WithError(err).Error(errMsg)
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusInternalServerError)
@@ -242,15 +246,15 @@ type CreateSubmissionRequest struct {
 }
 
 func (r CreateSubmissionRequest) toServiceRequest() (*model.CreateSubmissionRequest, error) {
-	sdkVP, err := signing.ParseVerifiablePresentationFromJWT(r.SubmissionJWT.String())
+	_, _, vp, err := signing.ParseVerifiablePresentationFromJWT(r.SubmissionJWT.String())
 	if err != nil {
 		return nil, errors.Wrap(err, "parsing presentation from jwt")
 	}
-	if err := sdkVP.IsValid(); err != nil {
+	if err := vp.IsValid(); err != nil {
 		return nil, errors.Wrap(err, "verifying vp validity")
 	}
 
-	submissionData, err := json.Marshal(sdkVP.PresentationSubmission)
+	submissionData, err := json.Marshal(vp.PresentationSubmission)
 	if err != nil {
 		return nil, errors.Wrap(err, "marshalling presentation_submission")
 	}
@@ -261,15 +265,15 @@ func (r CreateSubmissionRequest) toServiceRequest() (*model.CreateSubmissionRequ
 	if err := s.IsValid(); err != nil {
 		return nil, errors.Wrap(err, "verifying submission validity")
 	}
-	sdkVP.PresentationSubmission = s
+	vp.PresentationSubmission = s
 
-	credContainers, err := credint.NewCredentialContainerFromArray(sdkVP.VerifiableCredential)
+	credContainers, err := credint.NewCredentialContainerFromArray(vp.VerifiableCredential)
 	if err != nil {
 		return nil, errors.Wrap(err, "parsing verifiable credential array")
 	}
 
 	return &model.CreateSubmissionRequest{
-		Presentation:  *sdkVP,
+		Presentation:  *vp,
 		SubmissionJWT: r.SubmissionJWT,
 		Submission:    s,
 		Credentials:   credContainers}, nil
diff --git a/pkg/server/router/schema.go b/pkg/server/router/schema.go
index c7c9ec5..0f3d217 100644
--- a/pkg/server/router/schema.go
+++ b/pkg/server/router/schema.go
@@ -34,8 +34,12 @@ type CreateSchemaRequest struct {
 	Author string               `json:"author" validate:"required"`
 	Name   string               `json:"name" validate:"required"`
 	Schema schemalib.JSONSchema `json:"schema" validate:"required"`
+
 	// Sign represents whether the schema should be signed by the author. Default is false.
+	// If sign is true, the schema will be signed by the author's private key with the specified KID
 	Sign bool `json:"sign"`
+	// AuthorKID represents the KID of the author's private key to sign the schema. Required if sign is true.
+	AuthorKID string `json:"authorKid"`
 }
 
 type CreateSchemaResponse struct {
@@ -46,7 +50,7 @@ type CreateSchemaResponse struct {
 
 // CreateSchema godoc
 //
-// @Summary     Create Schema
+// @Summary     Create SchemaID
 // @Description Create schema
 // @Tags        SchemaAPI
 // @Accept      json
@@ -71,7 +75,13 @@ func (sr SchemaRouter) CreateSchema(ctx context.Context, w http.ResponseWriter,
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
 
-	req := schema.CreateSchemaRequest{Author: request.Author, Name: request.Name, Schema: request.Schema, Sign: request.Sign}
+	if request.Sign && request.AuthorKID == "" {
+		errMsg := "cannot sign schema without authorKID"
+		logrus.Error(errMsg)
+		return framework.NewRequestErrorMsg(errMsg, http.StatusBadRequest)
+	}
+
+	req := schema.CreateSchemaRequest{Author: request.Author, AuthorKID: request.AuthorKID, Name: request.Name, Schema: request.Schema, Sign: request.Sign}
 	createSchemaResponse, err := sr.service.CreateSchema(ctx, req)
 	if err != nil {
 		errMsg := fmt.Sprintf("could not create schema with authoring DID: %s", request.Author)
@@ -85,7 +95,7 @@ func (sr SchemaRouter) CreateSchema(ctx context.Context, w http.ResponseWriter,
 
 // GetSchema godoc
 //
-// @Summary     Get Schema
+// @Summary     Get SchemaID
 // @Description Get a schema by its ID
 // @Tags        SchemaAPI
 // @Accept      json
@@ -161,7 +171,7 @@ type VerifySchemaResponse struct {
 
 // VerifySchema godoc
 //
-// @Summary     Verify Schema
+// @Summary     Verify SchemaID
 // @Description Verify a given schema by its id
 // @Tags        SchemaAPI
 // @Accept      json
@@ -191,7 +201,7 @@ func (sr SchemaRouter) VerifySchema(ctx context.Context, w http.ResponseWriter,
 
 // DeleteSchema godoc
 //
-// @Summary     Delete Schema
+// @Summary     Delete SchemaID
 // @Description Delete a schema by its ID
 // @Tags        SchemaAPI
 // @Accept      json
diff --git a/pkg/server/server.go b/pkg/server/server.go
index 1f2fe13..7c5b227 100644
--- a/pkg/server/server.go
+++ b/pkg/server/server.go
@@ -144,7 +144,7 @@ func (s *SSIServer) DecentralizedIdentityAPI(service svcframework.Service, webho
 	return
 }
 
-// SchemaAPI registers all HTTP router for the Schema Service
+// SchemaAPI registers all HTTP router for the SchemaID Service
 func (s *SSIServer) SchemaAPI(service svcframework.Service, webhookService *webhook.Service) (err error) {
 	schemaRouter, err := router.NewSchemaRouter(service)
 	if err != nil {
@@ -164,7 +164,7 @@ func (s *SSIServer) SchemaAPI(service svcframework.Service, webhookService *webh
 func (s *SSIServer) CredentialAPI(service svcframework.Service, webhookService *webhook.Service) (err error) {
 	credRouter, err := router.NewCredentialRouter(service)
 	if err != nil {
-		return util.LoggingErrorMsg(err, "could not create credential router")
+		return util.LoggingErrorMsg(err, "creating credential router")
 	}
 
 	credentialHandlerPath := V1Prefix + CredentialsPrefix
@@ -187,7 +187,7 @@ func (s *SSIServer) CredentialAPI(service svcframework.Service, webhookService *
 func (s *SSIServer) PresentationAPI(service svcframework.Service) (err error) {
 	pRouter, err := router.NewPresentationRouter(service)
 	if err != nil {
-		return util.LoggingErrorMsg(err, "could not create credential router")
+		return util.LoggingErrorMsg(err, "creating credential router")
 	}
 
 	handlerPath := V1Prefix + PresentationsPrefix + DefinitionsPrefix
diff --git a/pkg/service/credential/model.go b/pkg/service/credential/model.go
index b18b5a6..02627a8 100644
--- a/pkg/service/credential/model.go
+++ b/pkg/service/credential/model.go
@@ -9,12 +9,13 @@ const (
 )
 
 type CreateCredentialRequest struct {
-	Issuer  string `json:"issuer" validate:"required"`
-	Subject string `json:"subject" validate:"required"`
+	Issuer    string `json:"issuer" validate:"required"`
+	IssuerKID string `json:"issuerKid" validate:"required"`
+	Subject   string `json:"subject" validate:"required"`
 	// A context is optional. If not present, we'll apply default, required context values.
 	Context string `json:"context,omitempty"`
-	// A schema is optional. If present, we'll attempt to look it up and validate the data against it.
-	JSONSchema  string         `json:"jsonSchema,omitempty"`
+	// A schema ID is optional. If present, we'll attempt to look it up and validate the data against it.
+	SchemaID    string         `json:"schemaId,omitempty"`
 	Data        map[string]any `json:"data,omitempty"`
 	Expiry      string         `json:"expiry,omitempty"`
 	Revocable   bool           `json:"revocable,omitempty"`
diff --git a/pkg/service/credential/service.go b/pkg/service/credential/service.go
index a9fadda..7386001 100644
--- a/pkg/service/credential/service.go
+++ b/pkg/service/credential/service.go
@@ -101,9 +101,9 @@ func (s Service) CreateCredential(ctx context.Context, request CreateCredentialR
 			statusPurpose = statussdk.StatusSuspension
 		}
 
-		statusListCredentialWatchKey := s.storage.GetStatusListCredentialWatchKey(request.Issuer, request.JSONSchema, string(statusPurpose))
-		statusListCredentialIndexPoolWatchKey := s.storage.GetStatusListIndexPoolWatchKey(request.Issuer, request.JSONSchema, string(statusPurpose))
-		statusListCredentialCurrentIndexWatchKey := s.storage.GetStatusListCurrentIndexWatchKey(request.Issuer, request.JSONSchema, string(statusPurpose))
+		statusListCredentialWatchKey := s.storage.GetStatusListCredentialWatchKey(request.Issuer, request.SchemaID, string(statusPurpose))
+		statusListCredentialIndexPoolWatchKey := s.storage.GetStatusListIndexPoolWatchKey(request.Issuer, request.SchemaID, string(statusPurpose))
+		statusListCredentialCurrentIndexWatchKey := s.storage.GetStatusListCurrentIndexWatchKey(request.Issuer, request.SchemaID, string(statusPurpose))
 
 		watchKeys = append(watchKeys, statusListCredentialWatchKey)
 		watchKeys = append(watchKeys, statusListCredentialIndexPoolWatchKey)
@@ -115,7 +115,6 @@ func (s Service) CreateCredential(ctx context.Context, request CreateCredentialR
 	returnFunc := s.createCredentialFunc(request, slcMetadata)
 
 	returnValue, err := s.storage.db.Execute(ctx, returnFunc, watchKeys)
-
 	if err != nil {
 		return nil, errors.Wrap(err, "execute")
 	}
@@ -169,20 +168,20 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 
 	// if a schema value exists, verify we can access it, validate the data against it, then set it
 	var knownSchema *schemalib.VCJSONSchema
-	if request.JSONSchema != "" {
+	if request.SchemaID != "" {
 		// resolve schema and save it for validation later
-		gotSchema, err := s.schema.GetSchema(ctx, schema.GetSchemaRequest{ID: request.JSONSchema})
+		gotSchema, err := s.schema.GetSchema(ctx, schema.GetSchemaRequest{ID: request.SchemaID})
 		if err != nil {
-			return nil, util.LoggingErrorMsgf(err, "failed to create credential; could not get schema: %s", request.JSONSchema)
+			return nil, util.LoggingErrorMsgf(err, "failed to create credential; could not get schema: %s", request.SchemaID)
 		}
 		knownSchema = &gotSchema.Schema
 
 		credSchema := credential.CredentialSchema{
-			ID:   request.JSONSchema,
+			ID:   request.SchemaID,
 			Type: SchemaLDType,
 		}
 		if err = builder.SetCredentialSchema(credSchema); err != nil {
-			return nil, util.LoggingErrorMsgf(err, "could not set JSON Schema for credential: %s", request.JSONSchema)
+			return nil, util.LoggingErrorMsgf(err, "could not set JSON SchemaID for credential: %s", request.SchemaID)
 		}
 	}
 
@@ -199,10 +198,10 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 	}
 
 	if request.hasStatus() {
-
 		credID := builder.ID
 		issuerID := request.Issuer
-		schemaID := request.JSONSchema
+		issuerKID := request.IssuerKID
+		schemaID := request.SchemaID
 
 		statusPurpose := statussdk.StatusRevocation
 
@@ -227,7 +226,7 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 
 		if statusListCredential == nil {
 			// creates status list credential with random index
-			randomIndex, slCredential, err = createStatusListCredential(ctx, tx, s, statusPurpose, issuerID, schemaID, slcMetadata)
+			randomIndex, slCredential, err = createStatusListCredential(ctx, tx, s, statusPurpose, issuerID, issuerKID, schemaID, slcMetadata)
 			if err != nil {
 				return nil, util.LoggingErrorMsgf(err, "problem with getting status list credential")
 			}
@@ -267,18 +266,23 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 	// verify the built schema complies with the schema we've set
 	if knownSchema != nil {
 		if err = schemalib.IsCredentialValidForVCJSONSchema(*cred, *knownSchema); err != nil {
-			return nil, util.LoggingErrorMsgf(err, "credential data does not comply with the provided schema: %s", request.JSONSchema)
+			return nil, util.LoggingErrorMsgf(err, "credential data does not comply with the provided schema: %s", request.SchemaID)
 		}
 	}
 
 	// TODO(gabe) support Data Integrity creds too https://github.com/TBD54566975/ssi-service/issues/105
-	credJWT, err := s.signCredentialJWT(ctx, request.Issuer, *cred)
+	credCopy, err := credint.CopyCredential(*cred)
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not copy credential")
+	}
+	credJWT, err := s.signCredentialJWT(ctx, request.IssuerKID, *credCopy)
 	if err != nil {
-		return nil, util.LoggingErrorMsg(err, "could not sign credential")
+		return nil, util.LoggingErrorMsg(err, "signing credential")
 	}
 
 	container := credint.Container{
 		ID:            cred.ID,
+		IssuerKID:     request.IssuerKID,
 		Credential:    cred,
 		CredentialJWT: credJWT,
 		Revoked:       false,
@@ -290,14 +294,14 @@ func (s Service) createCredentialBusinessLogic(ctx context.Context, request Crea
 	}
 
 	if err = s.storage.StoreCredentialTx(ctx, tx, credentialStorageRequest); err != nil {
-		return nil, util.LoggingErrorMsg(err, "failed to save vc")
+		return nil, util.LoggingErrorMsg(err, "saving credential")
 	}
 
 	response := CreateCredentialResponse{Container: container}
 	return &response, nil
 }
 
-func createStatusListCredential(ctx context.Context, tx storage.Tx, s Service, statusPurpose statussdk.StatusPurpose, issuerID string, schemaID string, slcMetadata StatusListCredentialMetadata) (int, *credential.VerifiableCredential, error) {
+func createStatusListCredential(ctx context.Context, tx storage.Tx, s Service, statusPurpose statussdk.StatusPurpose, issuerID, issuerKID, schemaID string, slcMetadata StatusListCredentialMetadata) (int, *credential.VerifiableCredential, error) {
 	statusListID := fmt.Sprintf("%s/v1/credentials/status/%s", s.config.ServiceEndpoint, uuid.NewString())
 
 	generatedStatusListCredential, err := statussdk.GenerateStatusList2021Credential(statusListID, issuerID, statusPurpose, []credential.VerifiableCredential{})
@@ -313,13 +317,14 @@ func createStatusListCredential(ctx context.Context, tx storage.Tx, s Service, s
 		generatedStatusListCredential.CredentialSchema = &credSchema
 	}
 
-	statusListCredJWT, err := s.signCredentialJWT(ctx, issuerID, *generatedStatusListCredential)
+	statusListCredJWT, err := s.signCredentialJWT(ctx, issuerKID, *generatedStatusListCredential)
 	if err != nil {
 		return -1, nil, util.LoggingErrorMsg(err, "could not sign status list credential")
 	}
 
 	statusListContainer := credint.Container{
 		ID:            generatedStatusListCredential.ID,
+		IssuerKID:     issuerKID,
 		Credential:    generatedStatusListCredential,
 		CredentialJWT: statusListCredJWT,
 	}
@@ -337,14 +342,17 @@ func createStatusListCredential(ctx context.Context, tx storage.Tx, s Service, s
 }
 
 // signCredentialJWT signs a credential and returns it as a vc-jwt
-func (s Service) signCredentialJWT(ctx context.Context, issuer string, cred credential.VerifiableCredential) (*keyaccess.JWT, error) {
-	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: issuer})
+func (s Service) signCredentialJWT(ctx context.Context, issuerKID string, cred credential.VerifiableCredential) (*keyaccess.JWT, error) {
+	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: issuerKID})
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key for signing credential with key<%s>", issuer)
+		return nil, util.LoggingErrorMsgf(err, "getting key for signing credential<%s>", issuerKID)
+	}
+	if gotKey.Controller != cred.Issuer.(string) {
+		return nil, util.LoggingNewErrorf("key controller<%s> does not match credential issuer<%s> for key<%s>", gotKey.Controller, cred.Issuer, issuerKID)
 	}
-	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	keyAccess, err := keyaccess.NewJWKKeyAccess(issuerKID, gotKey.ID, gotKey.Key)
 	if err != nil {
-		return nil, errors.Wrapf(err, "could not create key access for signing credential with key<%s>", gotKey.ID)
+		return nil, errors.Wrapf(err, "creating key access for signing credential with key<%s>", gotKey.ID)
 	}
 	credToken, err := keyAccess.SignVerifiableCredential(cred)
 	if err != nil {
@@ -391,7 +399,8 @@ func (s Service) VerifyCredential(ctx context.Context, request VerifyCredentialR
 	}
 
 	if request.CredentialJWT != nil {
-		if err := s.verifier.VerifyJWTCredential(ctx, *request.CredentialJWT); err != nil {
+		err := s.verifier.VerifyJWTCredential(ctx, *request.CredentialJWT)
+		if err != nil {
 			return &VerifyCredentialResponse{Verified: false, Reason: err.Error()}, nil
 		}
 	} else {
@@ -608,6 +617,7 @@ func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCr
 	// store the credential with updated status
 	container := credint.Container{
 		ID:            gotCred.ID,
+		IssuerKID:     gotCred.IssuerKID,
 		Credential:    gotCred.Credential,
 		CredentialJWT: gotCred.CredentialJWT,
 		Revoked:       request.Revoked,
@@ -665,7 +675,7 @@ func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCr
 
 	generatedStatusListCredential.CredentialSchema = gotCred.Credential.CredentialSchema
 
-	statusListCredJWT, err := s.signCredentialJWT(ctx, gotCred.Issuer, *generatedStatusListCredential)
+	statusListCredJWT, err := s.signCredentialJWT(ctx, gotCred.IssuerKID, *generatedStatusListCredential)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not sign status list credential")
 	}
@@ -673,6 +683,7 @@ func updateCredentialStatus(ctx context.Context, tx storage.Tx, s Service, gotCr
 	// store the status list credential
 	statusListContainer := credint.Container{
 		ID:            generatedStatusListCredential.ID,
+		IssuerKID:     gotCred.IssuerKID,
 		Credential:    generatedStatusListCredential,
 		CredentialJWT: statusListCredJWT,
 	}
diff --git a/pkg/service/credential/storage.go b/pkg/service/credential/storage.go
index cadc8d0..af987e2 100644
--- a/pkg/service/credential/storage.go
+++ b/pkg/service/credential/storage.go
@@ -13,6 +13,7 @@ import (
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+
 	credint "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
@@ -34,6 +35,7 @@ type StoredCredential struct {
 	CredentialJWT *keyaccess.JWT                   `json:"token,omitempty"`
 
 	Issuer       string `json:"issuer"`
+	IssuerKID    string `json:"issuerKid"`
 	Subject      string `json:"subject"`
 	Schema       string `json:"schema"`
 	IssuanceDate string `json:"issuanceDate"`
@@ -281,7 +283,7 @@ func buildStoredCredential(request StoreCredentialRequest) (*StoredCredential, e
 	// assume we have a Data Integrity credential
 	cred := request.Credential
 	if request.HasJWTCredential() {
-		parsedCred, err := signing.ParseVerifiableCredentialFromJWT(request.CredentialJWT.String())
+		_, _, parsedCred, err := signing.ParseVerifiableCredentialFromJWT(request.CredentialJWT.String())
 		if err != nil {
 			return nil, errors.Wrap(err, "could not parse credential from jwt")
 		}
@@ -306,6 +308,7 @@ func buildStoredCredential(request StoreCredentialRequest) (*StoredCredential, e
 		Credential:    cred,
 		CredentialJWT: request.CredentialJWT,
 		Issuer:        issuer,
+		IssuerKID:     request.IssuerKID,
 		Subject:       subject,
 		Schema:        schema,
 		IssuanceDate:  cred.IssuanceDate,
diff --git a/pkg/service/did/ion.go b/pkg/service/did/ion.go
index fbbc167..2b5f18d 100644
--- a/pkg/service/did/ion.go
+++ b/pkg/service/did/ion.go
@@ -189,7 +189,7 @@ func (h *ionHandler) CreateDID(ctx context.Context, request CreateDIDRequest) (*
 		return nil, errors.Wrap(err, "could not store did:ion recovery private key")
 	}
 
-	keyStoreRequest, err := keyToStoreRequest(ionDID.ID()+"#"+keyID, *privKeyJWK, ionDID.ID())
+	keyStoreRequest, err := keyToStoreRequest(keyID, *privKeyJWK, ionDID.ID())
 	if err != nil {
 		return nil, errors.Wrap(err, "converting private key to store request")
 	}
diff --git a/pkg/service/did/key.go b/pkg/service/did/key.go
index dfb52a4..dc83ac1 100644
--- a/pkg/service/did/key.go
+++ b/pkg/service/did/key.go
@@ -68,7 +68,7 @@ func (h *keyHandler) CreateDID(ctx context.Context, request CreateDIDRequest) (*
 
 	// store private key in key storage
 	keyStoreRequest := keystore.StoreKeyRequest{
-		ID:               id,
+		ID:               expanded.VerificationMethod[0].ID,
 		Type:             request.KeyType,
 		Controller:       id,
 		PrivateKeyBase58: privKeyBase58,
diff --git a/pkg/service/did/service.go b/pkg/service/did/service.go
index 90b5d51..71f4293 100644
--- a/pkg/service/did/service.go
+++ b/pkg/service/did/service.go
@@ -9,7 +9,6 @@ import (
 	"github.com/pkg/errors"
 
 	"github.com/tbd54566975/ssi-service/config"
-	"github.com/tbd54566975/ssi-service/internal/did"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/did/resolution"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
@@ -184,13 +183,13 @@ func (s *Service) GetKeyFromDID(ctx context.Context, request GetKeyFromDIDReques
 	}
 
 	// next, get the verification information (key) from the did document
-	kid, pubKey, err := did.GetVerificationInformation(resolved.Document, request.KeyID)
+	pubKey, err := didsdk.GetKeyFromVerificationMethod(resolved.Document, request.KeyID)
 	if err != nil {
 		return nil, errors.Wrapf(err, "getting verification information from the did document: %s", request.ID)
 	}
 
 	return &GetKeyFromDIDResponse{
-		KeyID:     kid,
+		KeyID:     request.KeyID,
 		PublicKey: pubKey,
 	}, nil
 }
diff --git a/pkg/service/did/web.go b/pkg/service/did/web.go
index 83eaf5e..9c52b9c 100644
--- a/pkg/service/did/web.go
+++ b/pkg/service/did/web.go
@@ -99,8 +99,7 @@ func (h *webHandler) CreateDID(ctx context.Context, request CreateDIDRequest) (*
 
 	// store private key in key storage
 	keyStoreRequest := keystore.StoreKeyRequest{
-		// TODO(gabe): this should be a unique ID for the key
-		ID:               id,
+		ID:               doc.VerificationMethod[0].ID,
 		Type:             request.KeyType,
 		Controller:       id,
 		PrivateKeyBase58: privKeyBase58,
diff --git a/pkg/service/issuing/model.go b/pkg/service/issuing/model.go
index 22b69d5..c452c1d 100644
--- a/pkg/service/issuing/model.go
+++ b/pkg/service/issuing/model.go
@@ -1,6 +1,7 @@
 package issuing
 
 import (
+	"reflect"
 	"time"
 
 	"github.com/TBD54566975/ssi-sdk/util"
@@ -58,10 +59,24 @@ type IssuanceTemplate struct {
 	// ID of the issuer that will be issuing the credentials.
 	Issuer string `json:"issuer" validate:"required"`
 
+	// ID of the key that will be used to sign the credentials.
+	IssuerKID string `json:"issuerKid" validate:"required"`
+
 	// Info required to create a credential from a credential application.
 	Credentials []CredentialTemplate `json:"credentials"`
 }
 
+func (it *IssuanceTemplate) IsEmpty() bool {
+	if it == nil {
+		return true
+	}
+	return reflect.DeepEqual(*it, IssuanceTemplate{})
+}
+
+func (it *IssuanceTemplate) IsValid() bool {
+	return util.IsValidStruct(it) == nil
+}
+
 type GetIssuanceTemplateResponse struct {
 	// The template that was requested.
 	IssuanceTemplate *IssuanceTemplate `json:"issuanceTemplate"`
diff --git a/pkg/service/keystore/service.go b/pkg/service/keystore/service.go
index fdffb14..221c894 100644
--- a/pkg/service/keystore/service.go
+++ b/pkg/service/keystore/service.go
@@ -51,7 +51,7 @@ func NewKeyStoreService(config config.KeyStoreServiceConfig, s storage.ServiceSt
 	// First, generate a service key
 	serviceKey, serviceKeySalt, err := GenerateServiceKey(config.ServiceKeyPassword)
 	if err != nil {
-		return nil, util.LoggingErrorMsg(err, "could not generate service key")
+		return nil, util.LoggingErrorMsg(err, "generating service key")
 	}
 
 	// Next, instantiate the key storage
@@ -60,7 +60,7 @@ func NewKeyStoreService(config config.KeyStoreServiceConfig, s storage.ServiceSt
 		Base58Salt: serviceKeySalt,
 	})
 	if err != nil {
-		return nil, util.LoggingErrorMsg(err, "could not instantiate storage for the keystore service")
+		return nil, util.LoggingErrorMsg(err, "instantiating storage for the keystore service")
 	}
 
 	service := Service{
@@ -90,7 +90,7 @@ func (s Service) StoreKey(ctx context.Context, request StoreKeyRequest) error {
 		CreatedAt:  time.Now().Format(time.RFC3339),
 	}
 	if err := s.storage.StoreKey(ctx, key); err != nil {
-		return util.LoggingErrorMsgf(err, "could not store key: %s", request.ID)
+		return util.LoggingErrorMsgf(err, "storing key: %s", request.ID)
 	}
 	return nil
 }
@@ -101,7 +101,7 @@ func (s Service) GetKey(ctx context.Context, request GetKeyRequest) (*GetKeyResp
 	id := request.ID
 	gotKey, err := s.storage.GetKey(ctx, id)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key for key: %s", id)
+		return nil, util.LoggingErrorMsgf(err, "getting key with id: %s", id)
 	}
 	if gotKey == nil {
 		return nil, util.LoggingErrorMsgf(err, "key with id<%s> could not be found", id)
@@ -165,13 +165,13 @@ func (s Service) GetKeyDetails(ctx context.Context, request GetKeyDetailsRequest
 func GenerateServiceKey(skPassword string) (key, salt string, err error) {
 	saltBytes, err := util.GenerateSalt(util.Argon2SaltSize)
 	if err != nil {
-		err = errors.Wrap(err, "could not generate salt for service key")
+		err = errors.Wrap(err, "generating salt for service key")
 		return "", "", util.LoggingError(err)
 	}
 
 	keyBytes, err := util.Argon2KeyGen(skPassword, saltBytes, chacha20poly1305.KeySize)
 	if err != nil {
-		err = errors.Wrap(err, "could not generate key for service key")
+		err = errors.Wrap(err, "generating key for service key")
 		return "", "", util.LoggingError(err)
 	}
 
@@ -184,7 +184,7 @@ func GenerateServiceKey(skPassword string) (key, salt string, err error) {
 func EncryptKey(serviceKey, key []byte) ([]byte, error) {
 	encryptedKey, err := util.XChaCha20Poly1305Encrypt(serviceKey, key)
 	if err != nil {
-		return nil, errors.Wrap(err, "could not encrypt key with service key")
+		return nil, errors.Wrap(err, "encrypting key with service key")
 	}
 	return encryptedKey, nil
 }
@@ -193,7 +193,7 @@ func EncryptKey(serviceKey, key []byte) ([]byte, error) {
 func DecryptKey(serviceKey, encryptedKey []byte) ([]byte, error) {
 	decryptedKey, err := util.XChaCha20Poly1305Decrypt(serviceKey, encryptedKey)
 	if err != nil {
-		return nil, errors.Wrap(err, "could not decrypt key with service key")
+		return nil, errors.Wrap(err, "decrypting key with service key")
 	}
 	return decryptedKey, nil
 }
@@ -202,15 +202,15 @@ func DecryptKey(serviceKey, encryptedKey []byte) ([]byte, error) {
 func (s Service) Sign(ctx context.Context, keyID string, data any) (*keyaccess.JWT, error) {
 	gotKey, err := s.GetKey(ctx, GetKeyRequest{ID: keyID})
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key for signing schema for keyID<%s>", keyID)
+		return nil, util.LoggingErrorMsgf(err, "getting key with keyID<%s>", keyID)
 	}
-	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not create key access for signing schema for keyID<%s>", keyID)
+		return nil, util.LoggingErrorMsgf(err, "creating key access for keyID<%s>", keyID)
 	}
 	schemaToken, err := keyAccess.SignJSON(data)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not sign schema for keyID<%s>", keyID)
+		return nil, util.LoggingErrorMsgf(err, "signing data with keyID<%s>", keyID)
 	}
 	return schemaToken, nil
 }
diff --git a/pkg/service/keystore/storage.go b/pkg/service/keystore/storage.go
index d165232..2568058 100644
--- a/pkg/service/keystore/storage.go
+++ b/pkg/service/keystore/storage.go
@@ -149,7 +149,7 @@ func (kss *Storage) RevokeKey(ctx context.Context, id string) error {
 func (kss *Storage) GetKey(ctx context.Context, id string) (*StoredKey, error) {
 	storedKeyBytes, err := kss.db.Read(ctx, namespace, id)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key details for key: %s", id)
+		return nil, util.LoggingErrorMsgf(err, "getting key details for key: %s", id)
 	}
 	if len(storedKeyBytes) == 0 {
 		return nil, util.LoggingNewErrorf("could not find key details for key: %s", id)
@@ -169,7 +169,7 @@ func (kss *Storage) GetKey(ctx context.Context, id string) (*StoredKey, error) {
 
 	var stored StoredKey
 	if err = json.Unmarshal(decryptedKey, &stored); err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not unmarshal stored key: %s", id)
+		return nil, util.LoggingErrorMsgf(err, "unmarshalling stored key: %s", id)
 	}
 	return &stored, nil
 }
diff --git a/pkg/service/manifest/application.go b/pkg/service/manifest/application.go
index 066856a..e327165 100644
--- a/pkg/service/manifest/application.go
+++ b/pkg/service/manifest/application.go
@@ -5,7 +5,10 @@ import (
 	"fmt"
 	"strings"
 
+	"github.com/lestrrat-go/jwx/v2/jws"
+
 	didint "github.com/tbd54566975/ssi-service/internal/did"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
@@ -19,8 +22,25 @@ import (
 // is a valid credential application, and complies with its corresponding manifest. it returns the ids of unfulfilled
 // input descriptors along with an error if validation fails.
 func (s Service) validateCredentialApplication(ctx context.Context, credManifest manifest.CredentialManifest, request model.SubmitApplicationRequest) (inputDescriptorIDs []string, err error) {
+	// parse headers
+	headers, err := keyaccess.GetJWTHeaders([]byte(request.ApplicationJWT.String()))
+	if err != nil {
+		err = util.LoggingErrorMsg(err, "could not parse JWT headers")
+		return
+	}
+	jwtKID, ok := headers.Get(jws.KeyIDKey)
+	if !ok {
+		err = util.LoggingNewError("JWT does not contain a kid")
+		return
+	}
+	kid, ok := jwtKID.(string)
+	if !ok {
+		err = util.LoggingNewError("JWT kid is not a string")
+		return
+	}
+
 	// validate the payload's signature
-	if verificationErr := didint.VerifyTokenFromDID(ctx, s.didResolver, request.ApplicantDID, request.ApplicationJWT); verificationErr != nil {
+	if verificationErr := didint.VerifyTokenFromDID(ctx, s.didResolver, request.ApplicantDID, kid, request.ApplicationJWT); verificationErr != nil {
 		err = util.LoggingErrorMsgf(err, "could not verify application<%s>'s signature", request.Application.ID)
 		return
 	}
diff --git a/pkg/service/manifest/manifest.go b/pkg/service/manifest/manifest.go
index 44af41a..3bfe58d 100644
--- a/pkg/service/manifest/manifest.go
+++ b/pkg/service/manifest/manifest.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
 	"github.com/goccy/go-json"
+	"github.com/lestrrat-go/jwx/jws"
 	"github.com/lestrrat-go/jwx/jwt"
 
 	didint "github.com/tbd54566975/ssi-service/internal/did"
@@ -13,13 +14,12 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/service/keystore"
 )
 
-func (s Service) signManifestJWT(ctx context.Context, m CredentialManifestContainer) (*keyaccess.JWT, error) {
-	issuerID := m.Manifest.Issuer.ID
-	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: issuerID})
+func (s Service) signManifestJWT(ctx context.Context, keyID string, m CredentialManifestContainer) (*keyaccess.JWT, error) {
+	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: keyID})
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key for signing manifest with key<%s>", issuerID)
+		return nil, util.LoggingErrorMsgf(err, "could not get key for signing manifest with key<%s>", keyID)
 	}
-	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "could not create key access for signing manifest with key<%s>", gotKey.ID)
 	}
@@ -33,6 +33,21 @@ func (s Service) signManifestJWT(ctx context.Context, m CredentialManifestContai
 }
 
 func (s Service) verifyManifestJWT(ctx context.Context, token keyaccess.JWT) (*manifest.CredentialManifest, error) {
+	// parse headers
+	headers, err := keyaccess.GetJWTHeaders([]byte(token))
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not parse JWT headers")
+	}
+	jwtKID, ok := headers.Get(jws.KeyIDKey)
+	if !ok {
+		return nil, util.LoggingNewError("JWT does not contain a kid")
+	}
+	kid, ok := jwtKID.(string)
+	if !ok {
+		return nil, util.LoggingNewError("JWT kid is not a string")
+	}
+
+	// parse token
 	parsed, err := jwt.Parse([]byte(token))
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not parse JWT")
@@ -49,7 +64,7 @@ func (s Service) verifyManifestJWT(ctx context.Context, token keyaccess.JWT) (*m
 		return nil, util.LoggingErrorMsg(err, "unmarshalling claims into manifest")
 	}
 
-	if err = didint.VerifyTokenFromDID(ctx, s.didResolver, parsedManifest.Manifest.Issuer.ID, token); err != nil {
+	if err = didint.VerifyTokenFromDID(ctx, s.didResolver, parsedManifest.Manifest.Issuer.ID, kid, token); err != nil {
 		return nil, util.LoggingErrorMsg(err, "verifying manifest JWT")
 	}
 	return &parsedManifest.Manifest, nil
diff --git a/pkg/service/manifest/model/model.go b/pkg/service/manifest/model/model.go
index ce43f3b..e1637b5 100644
--- a/pkg/service/manifest/model/model.go
+++ b/pkg/service/manifest/model/model.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
+
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest/storage"
@@ -16,6 +17,7 @@ type CreateManifestRequest struct {
 	Name                   *string                          `json:"name,omitempty"`
 	Description            *string                          `json:"description,omitempty"`
 	IssuerDID              string                           `json:"issuerDid" validate:"required"`
+	IssuerKID              string                           `json:"issuerKid" validate:"required"`
 	IssuerName             *string                          `json:"issuerName,omitempty"`
 	OutputDescriptors      []manifestsdk.OutputDescriptor   `json:"outputDescriptors" validate:"required,dive"`
 	ClaimFormat            *exchange.ClaimFormat            `json:"format" validate:"required,dive"`
diff --git a/pkg/service/manifest/response.go b/pkg/service/manifest/response.go
index 35b3600..45091a3 100644
--- a/pkg/service/manifest/response.go
+++ b/pkg/service/manifest/response.go
@@ -12,6 +12,7 @@ import (
 	"github.com/oliveagle/jsonpath"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
@@ -26,18 +27,14 @@ const (
 	DenialResponse errresp.Type = "DenialResponse"
 )
 
-func (s Service) signCredentialResponseJWT(ctx context.Context, signingDID string, r CredentialResponseContainer) (*keyaccess.JWT, error) {
-	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: signingDID})
+func (s Service) signCredentialResponseJWT(ctx context.Context, issuerKID string, r CredentialResponseContainer) (*keyaccess.JWT, error) {
+	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: issuerKID})
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key for signing response with key<%s>", signingDID)
+		return nil, util.LoggingErrorMsgf(err, "getting key for signing response with key<%s>", issuerKID)
 	}
-	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(
-			err,
-			"could not create key access for signing response with key<%s>",
-			gotKey.ID,
-		)
+		return nil, util.LoggingErrorMsgf(err, "creating key access for signing response with key<%s>", gotKey.ID)
 	}
 
 	// signing the response as a JWT
@@ -48,9 +45,10 @@ func (s Service) signCredentialResponseJWT(ctx context.Context, signingDID strin
 	return responseToken, nil
 }
 
+// TODO(gabe) refactor this method to distinguish between templates and non-templates; remove side effects; handle denial separately https://github.com/TBD54566975/ssi-service/issues/377
 func (s Service) buildCredentialResponse(
 	ctx context.Context,
-	applicantDID, manifestID string,
+	applicantDID, manifestID, issuerKID string,
 	credManifest manifest.CredentialManifest,
 	approved bool,
 	reason string,
@@ -63,15 +61,16 @@ func (s Service) buildCredentialResponse(
 	applicationID := application.ID
 	responseBuilder := manifest.NewCredentialResponseBuilder(manifestID)
 	if err := responseBuilder.SetApplicationID(applicationID); err != nil {
-		return nil, nil, util.LoggingErrorMsgf(
-			err,
-			"could not fulfill credential credentials: could not set credentials id: %s",
-			applicationID,
-		)
+		return nil, nil, util.LoggingErrorMsgf(err,
+			"could not fulfill credential credentials: could not set credentials id: %s", applicationID)
 	}
 
 	templateMap := make(map[string]*issuing.CredentialTemplate)
+	issuingKID := issuerKID
 	if template != nil {
+		if template.IssuerKID != "" {
+			issuingKID = template.IssuerKID
+		}
 		for _, templateCred := range template.Credentials {
 			templateCred := templateCred
 			templateMap[templateCred.ID] = &templateCred
@@ -80,22 +79,15 @@ func (s Service) buildCredentialResponse(
 	creds := make([]cred.Container, 0, len(credManifest.OutputDescriptors))
 	for _, od := range credManifest.OutputDescriptors {
 		credentialRequest := credential.CreateCredentialRequest{
-			Issuer:     credManifest.Issuer.ID,
-			Subject:    applicantDID,
-			JSONSchema: od.Schema,
+			Issuer:    credManifest.Issuer.ID,
+			IssuerKID: issuingKID,
+			Subject:   applicantDID,
+			SchemaID:  od.Schema,
 			// TODO(gabe) need to add in data here to match the request + schema
 			Data: make(map[string]any),
 		}
 		if template != nil {
-			err := s.applyIssuanceTemplate(
-				&credentialRequest,
-				template,
-				templateMap,
-				od,
-				applicationJSON,
-				credManifest,
-				application,
-			)
+			err := s.applyIssuanceTemplate(&credentialRequest, template, templateMap, od, applicationJSON, credManifest, application)
 			if err != nil {
 				return nil, nil, err
 			}
@@ -261,10 +253,7 @@ func fromFormat(format exchange.CredentialFormat, claim any) (any, error) {
 	}
 }
 
-func buildDenialCredentialResponse(
-	manifestID, applicationID, reason string,
-	failedOutputDescriptorIDs ...string,
-) (*manifest.CredentialResponse, error) {
+func buildDenialCredentialResponse(manifestID, applicationID, reason string, failedOutputDescriptorIDs ...string) (*manifest.CredentialResponse, error) {
 	builder := manifest.NewCredentialResponseBuilder(manifestID)
 	if err := builder.SetApplicationID(applicationID); err != nil {
 		return nil, err
diff --git a/pkg/service/manifest/service.go b/pkg/service/manifest/service.go
index cccca36..0476a14 100644
--- a/pkg/service/manifest/service.go
+++ b/pkg/service/manifest/service.go
@@ -166,7 +166,7 @@ func (s Service) CreateManifest(ctx context.Context, request model.CreateManifes
 	}
 
 	// sign the manifest
-	manifestJWT, err := s.signManifestJWT(ctx, CredentialManifestContainer{Manifest: *m})
+	manifestJWT, err := s.signManifestJWT(ctx, request.IssuerKID, CredentialManifestContainer{Manifest: *m})
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not sign manifest")
 	}
@@ -175,6 +175,7 @@ func (s Service) CreateManifest(ctx context.Context, request model.CreateManifes
 	storageRequest := manifeststg.StoredManifest{
 		ID:          m.ID,
 		Issuer:      m.Issuer.ID,
+		IssuerKID:   request.IssuerKID,
 		Manifest:    *m,
 		ManifestJWT: *manifestJWT,
 	}
@@ -261,49 +262,36 @@ func (s Service) ProcessApplicationSubmission(ctx context.Context, request model
 	gotManifest, err := s.storage.GetManifest(ctx, manifestID)
 	applicationID := request.Application.ID
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(
-			err,
-			"problem with retrieving manifest<%s> during application<%s>'s validation",
-			manifestID,
-			applicationID,
-		)
+		return nil, util.LoggingErrorMsgf(err,
+			"problem with retrieving manifest<%s> during application<%s>'s validation", manifestID, applicationID)
 	}
 	if gotManifest == nil {
 		return nil, util.LoggingNewErrorf(
-			"application<%s> is not valid; a manifest does not exist with id: %s",
-			applicationID,
-			manifestID,
-		)
+			"application<%s> is not valid; a manifest does not exist with id: %s", applicationID, manifestID)
 	}
 
 	opID := opcredential.IDFromResponseID(applicationID)
+
 	// validate the application
-	if unfulfilledInputDescriptorIDs, validationErr := s.validateCredentialApplication(
-		ctx, gotManifest.Manifest,
-		request,
-	); validationErr != nil {
+	unfulfilledInputDescriptorIDs, validationErr := s.validateCredentialApplication(ctx, gotManifest.Manifest, request)
+	if validationErr != nil {
 		resp := errresp.GetErrorResponse(validationErr)
 		if resp.ErrorType == DenialResponse {
-			denialResp, err := buildDenialCredentialResponse(
-				manifestID,
-				applicationID,
-				resp.Err.Error(),
-				unfulfilledInputDescriptorIDs...,
-			)
+			denialResp, err := buildDenialCredentialResponse(manifestID, applicationID, resp.Err.Error(), unfulfilledInputDescriptorIDs...)
 			if err != nil {
 				return nil, util.LoggingErrorMsg(err, "could not build denial credential response")
 			}
 			sarData, err := json.Marshal(manifeststg.StoredResponse{Response: *denialResp})
 			if err != nil {
-				return nil, errors.Wrap(err, "marshalling response")
+				return nil, util.LoggingErrorMsg(err, "marshalling response")
 			}
 			storedOp := opstorage.StoredOperation{
 				ID:       opID,
 				Done:     true,
 				Response: sarData,
 			}
-			if err := s.opsStorage.StoreOperation(ctx, storedOp); err != nil {
-				return nil, errors.Wrap(err, "storing operation")
+			if err = s.opsStorage.StoreOperation(ctx, storedOp); err != nil {
+				return nil, util.LoggingErrorMsg(err, "storing operation")
 			}
 
 			return operation.ServiceModel(storedOp)
@@ -326,14 +314,12 @@ func (s Service) ProcessApplicationSubmission(ctx context.Context, request model
 		return nil, util.LoggingErrorMsg(err, "could not store application")
 	}
 
-	storedOp := &opstorage.StoredOperation{
-		ID: opID,
-	}
+	storedOp := &opstorage.StoredOperation{ID: opID}
 	if err = s.opsStorage.StoreOperation(ctx, *storedOp); err != nil {
 		return nil, errors.Wrap(err, "storing operation")
 	}
 
-	autoStoredOp, err := s.maybeIssueAutomatically(ctx, request, manifestID, applicantDID, applicationID, gotManifest)
+	autoStoredOp, err := s.attemptAutomaticIssuance(ctx, request, manifestID, applicantDID, applicationID, *gotManifest)
 	if err != nil {
 		return nil, err
 	}
@@ -344,41 +330,35 @@ func (s Service) ProcessApplicationSubmission(ctx context.Context, request model
 	return operation.ServiceModel(*storedOp)
 }
 
-func (s Service) maybeIssueAutomatically(
-	ctx context.Context,
-	request model.SubmitApplicationRequest,
-	manifestID string,
-	applicantDID string,
-	applicationID string,
-	gotManifest *manifeststg.StoredManifest,
-) (*opstorage.StoredOperation, error) {
+// attemptAutomaticIssuance checks if there is an issuance template for the manifest, and if so,
+// attempts to issue a credential against it
+func (s Service) attemptAutomaticIssuance(ctx context.Context, request model.SubmitApplicationRequest, manifestID,
+	applicantDID, applicationID string, gotManifest manifeststg.StoredManifest) (*opstorage.StoredOperation, error) {
 	issuanceTemplates, err := s.issuanceTemplateStorage.GetIssuanceTemplatesByManifestID(ctx, manifestID)
 	if err != nil {
 		return nil, errors.Wrap(err, "fetching issuance templates by manifest ID")
 	}
 	if len(issuanceTemplates) == 0 {
+		logrus.Warnf("no issuance templates found for manifest<%s>, processing application<%s>", manifestID, applicationID)
 		return nil, nil
 	}
 
 	issuanceTemplate := issuanceTemplates[0].IssuanceTemplate
-
 	if len(issuanceTemplates) > 1 {
-		logrus.Warnf("found multiple issuance templates, using first entry only")
+		logrus.Warnf("found multiple issuance templates for manifest<%s>, using first entry only", manifestID)
 	}
 
-	credResp, creds, err := s.buildCredentialResponse(ctx, applicantDID, manifestID, gotManifest.Manifest, true, "automatic creation via issuance template", &issuanceTemplate, request.Application, request.ApplicationJSON, nil)
+	credResp, creds, err := s.buildCredentialResponse(ctx, applicantDID, manifestID, gotManifest.IssuerKID,
+		gotManifest.Manifest, true, "automatic creation via issuance template", &issuanceTemplate,
+		request.Application, request.ApplicationJSON, nil)
 	if err != nil {
 		return nil, err
 	}
-	credentials := credint.ContainersToInterface(creds)
 
-	responseJWT, err := s.signCredentialResponseJWT(
-		ctx,
-		gotManifest.Issuer, CredentialResponseContainer{
-			Response:    *credResp,
-			Credentials: credentials,
-		},
-	)
+	responseJWT, err := s.signCredentialResponseJWT(ctx, gotManifest.IssuerKID, CredentialResponseContainer{
+		Response:    *credResp,
+		Credentials: credint.ContainersToInterface(creds),
+	})
 	if err != nil {
 		return nil, errors.Wrap(err, "signing credential response")
 	}
@@ -391,14 +371,8 @@ func (s Service) maybeIssueAutomatically(
 		Credentials:  creds,
 		ResponseJWT:  *responseJWT,
 	}
-	_, storedOp, err := s.storage.ReviewApplication(
-		ctx,
-		applicationID,
-		true,
-		"automatic from issuing template",
-		opcredential.IDFromResponseID(applicationID),
-		storedResponse,
-	)
+	_, storedOp, err := s.storage.ReviewApplication(ctx, applicationID, true,
+		"automatic from issuing template", opcredential.IDFromResponseID(applicationID), storedResponse)
 	if err != nil {
 		return nil, errors.Wrap(err, "reviewing application")
 	}
@@ -430,18 +404,8 @@ func (s Service) ReviewApplication(ctx context.Context, request model.ReviewAppl
 	applicantDID := application.ApplicantDID
 
 	// build the credential response
-	credResp, creds, err := s.buildCredentialResponse(
-		ctx,
-		applicantDID,
-		manifestID,
-		credManifest,
-		request.Approved,
-		request.Reason,
-		nil,
-		application.Application,
-		nil,
-		request.CredentialOverrides,
-	)
+	credResp, creds, err := s.buildCredentialResponse(ctx, applicantDID, manifestID, gotManifest.IssuerKID,
+		credManifest, request.Approved, request.Reason, nil, application.Application, nil, request.CredentialOverrides)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not build credential response")
 	}
@@ -450,12 +414,10 @@ func (s Service) ReviewApplication(ctx context.Context, request model.ReviewAppl
 	credentials := credint.ContainersToInterface(creds)
 
 	// sign the response before returning
-	responseJWT, err := s.signCredentialResponseJWT(
-		ctx, gotManifest.Issuer, CredentialResponseContainer{
-			Response:    *credResp,
-			Credentials: credentials,
-		},
-	)
+	responseJWT, err := s.signCredentialResponseJWT(ctx, gotManifest.IssuerKID, CredentialResponseContainer{
+		Response:    *credResp,
+		Credentials: credentials,
+	})
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not sign credential response")
 	}
@@ -469,13 +431,8 @@ func (s Service) ReviewApplication(ctx context.Context, request model.ReviewAppl
 		Credentials:  creds,
 		ResponseJWT:  *responseJWT,
 	}
-	storedResponse, _, err := s.storage.ReviewApplication(
-		ctx, request.ID,
-		request.Approved,
-		request.Reason,
-		opcredential.IDFromResponseID(request.ID),
-		storeResponseRequest,
-	)
+	storedResponse, _, err := s.storage.ReviewApplication(ctx, request.ID, request.Approved, request.Reason,
+		opcredential.IDFromResponseID(request.ID), storeResponseRequest)
 	if err != nil {
 		return nil, errors.Wrap(err, "updating submission")
 	}
@@ -485,7 +442,6 @@ func (s Service) ReviewApplication(ctx context.Context, request model.ReviewAppl
 }
 
 func (s Service) GetApplication(ctx context.Context, request model.GetApplicationRequest) (*model.GetApplicationResponse, error) {
-
 	logrus.Debugf("getting application: %s", request.ID)
 
 	gotApp, err := s.storage.GetApplication(ctx, request.ID)
@@ -498,7 +454,6 @@ func (s Service) GetApplication(ctx context.Context, request model.GetApplicatio
 }
 
 func (s Service) GetApplications(ctx context.Context) (*model.GetApplicationsResponse, error) {
-
 	logrus.Debugf("getting application(s)")
 
 	gotApps, err := s.storage.GetApplications(ctx)
diff --git a/pkg/service/manifest/storage/storage.go b/pkg/service/manifest/storage/storage.go
index 9ddd4b2..69d5514 100644
--- a/pkg/service/manifest/storage/storage.go
+++ b/pkg/service/manifest/storage/storage.go
@@ -2,12 +2,12 @@ package storage
 
 import (
 	"context"
-	"fmt"
 
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
@@ -27,6 +27,7 @@ const (
 type StoredManifest struct {
 	ID          string                      `json:"id"`
 	Issuer      string                      `json:"issuer"`
+	IssuerKID   string                      `json:"issuerKid"`
 	Manifest    manifest.CredentialManifest `json:"manifest"`
 	ManifestJWT keyaccess.JWT               `json:"manifestJwt"`
 }
@@ -65,15 +66,11 @@ func NewManifestStorage(db storage.ServiceStorage) (*Storage, error) {
 func (ms *Storage) StoreManifest(ctx context.Context, manifest StoredManifest) error {
 	id := manifest.Manifest.ID
 	if id == "" {
-		err := errors.New("could not store manifest without an ID")
-		logrus.WithError(err).Error()
-		return err
+		return util.LoggingNewError("could not store manifest without an ID")
 	}
 	manifestBytes, err := json.Marshal(manifest)
 	if err != nil {
-		errMsg := fmt.Sprintf("could not store manifest: %s", id)
-		logrus.WithError(err).Error(errMsg)
-		return errors.Wrapf(err, errMsg)
+		return util.LoggingErrorMsgf(err, "could not store manifest: %s", id)
 	}
 	return ms.db.Write(ctx, manifestNamespace, id, manifestBytes)
 }
@@ -81,20 +78,14 @@ func (ms *Storage) StoreManifest(ctx context.Context, manifest StoredManifest) e
 func (ms *Storage) GetManifest(ctx context.Context, id string) (*StoredManifest, error) {
 	manifestBytes, err := ms.db.Read(ctx, manifestNamespace, id)
 	if err != nil {
-		errMsg := fmt.Sprintf("could not get manifest: %s", id)
-		logrus.WithError(err).Error(errMsg)
-		return nil, errors.Wrapf(err, errMsg)
+		return nil, util.LoggingErrorMsgf(err, "getting manifest: %s", id)
 	}
 	if len(manifestBytes) == 0 {
-		err := fmt.Errorf("manifest not found with id: %s", id)
-		logrus.WithError(err).Error("could not get manifest from storage")
-		return nil, err
+		return nil, util.LoggingNewErrorf("manifest not found with id: %s", id)
 	}
 	var stored StoredManifest
 	if err := json.Unmarshal(manifestBytes, &stored); err != nil {
-		errMsg := fmt.Sprintf("could not unmarshal stored manifest: %s", id)
-		logrus.WithError(err).Error(errMsg)
-		return nil, errors.Wrapf(err, errMsg)
+		return nil, util.LoggingErrorMsgf(err, "unmarshalling stored manifest: %s", id)
 	}
 	return &stored, nil
 }
@@ -103,9 +94,7 @@ func (ms *Storage) GetManifest(ctx context.Context, id string) (*StoredManifest,
 func (ms *Storage) GetManifests(ctx context.Context) ([]StoredManifest, error) {
 	gotManifests, err := ms.db.ReadAll(ctx, manifestNamespace)
 	if err != nil {
-		errMsg := "could not get all manifests"
-		logrus.WithError(err).Error(errMsg)
-		return nil, errors.Wrap(err, errMsg)
+		return nil, util.LoggingErrorMsgf(err, "getting all manifests")
 	}
 	if len(gotManifests) == 0 {
 		logrus.Info("no manifests to get")
@@ -116,6 +105,8 @@ func (ms *Storage) GetManifests(ctx context.Context) ([]StoredManifest, error) {
 		var nextManifest StoredManifest
 		if err = json.Unmarshal(manifestBytes, &nextManifest); err == nil {
 			stored = append(stored, nextManifest)
+		} else {
+			logrus.Errorf("could not unmarshal manifest while getting all manifests: %s", err.Error())
 		}
 	}
 	return stored, nil
@@ -123,7 +114,7 @@ func (ms *Storage) GetManifests(ctx context.Context) ([]StoredManifest, error) {
 
 func (ms *Storage) DeleteManifest(ctx context.Context, id string) error {
 	if err := ms.db.Delete(ctx, manifestNamespace, id); err != nil {
-		return util.LoggingErrorMsgf(err, "could not delete manifest: %s", id)
+		return util.LoggingErrorMsgf(err, "deleting manifest: %s", id)
 	}
 	return nil
 }
@@ -150,7 +141,7 @@ func (ms *Storage) GetApplication(ctx context.Context, id string) (*StoredApplic
 	}
 	var stored StoredApplication
 	if err = json.Unmarshal(applicationBytes, &stored); err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not unmarshal stored application: %s", id)
+		return nil, util.LoggingErrorMsgf(err, "unmarshalling stored application: %s", id)
 	}
 	return &stored, nil
 }
@@ -159,7 +150,7 @@ func (ms *Storage) GetApplication(ctx context.Context, id string) (*StoredApplic
 func (ms *Storage) GetApplications(ctx context.Context) ([]StoredApplication, error) {
 	gotApplications, err := ms.db.ReadAll(ctx, credential.ApplicationNamespace)
 	if err != nil {
-		return nil, util.LoggingErrorMsg(err, "could not get all applications")
+		return nil, util.LoggingErrorMsg(err, "getting all applications")
 	}
 	if len(gotApplications) == 0 {
 		logrus.Info("no applications to get")
@@ -171,7 +162,7 @@ func (ms *Storage) GetApplications(ctx context.Context) ([]StoredApplication, er
 		if err = json.Unmarshal(applicationBytes, &nextApplication); err == nil {
 			stored = append(stored, nextApplication)
 		} else {
-			logrus.WithError(err).Errorf("could not unmarshal stored application: %s", appKey)
+			logrus.WithError(err).Errorf("could not unmarshal stored application while getting all applications: %s", appKey)
 		}
 	}
 	return stored, nil
@@ -179,7 +170,7 @@ func (ms *Storage) GetApplications(ctx context.Context) ([]StoredApplication, er
 
 func (ms *Storage) DeleteApplication(ctx context.Context, id string) error {
 	if err := ms.db.Delete(ctx, credential.ApplicationNamespace, id); err != nil {
-		return util.LoggingErrorMsgf(err, "could not delete application: %s", id)
+		return util.LoggingErrorMsgf(err, "deleting application: %s", id)
 	}
 	return nil
 }
@@ -191,7 +182,7 @@ func (ms *Storage) StoreResponse(ctx context.Context, response StoredResponse) e
 	}
 	responseBytes, err := json.Marshal(response)
 	if err != nil {
-		return util.LoggingErrorMsgf(err, "could not store response: %s", id)
+		return util.LoggingErrorMsgf(err, "storing response: %s", id)
 	}
 	return ms.db.Write(ctx, responseNamespace, id, responseBytes)
 }
@@ -199,14 +190,14 @@ func (ms *Storage) StoreResponse(ctx context.Context, response StoredResponse) e
 func (ms *Storage) GetResponse(ctx context.Context, id string) (*StoredResponse, error) {
 	responseBytes, err := ms.db.Read(ctx, responseNamespace, id)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get response: %s", id)
+		return nil, util.LoggingErrorMsgf(err, "getting response: %s", id)
 	}
 	if len(responseBytes) == 0 {
 		return nil, util.LoggingNewErrorf("response not found with id: %s", id)
 	}
 	var stored StoredResponse
 	if err = json.Unmarshal(responseBytes, &stored); err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not unmarshal stored response: %s", id)
+		return nil, util.LoggingErrorMsgf(err, "unmarshalling stored response: %s", id)
 	}
 	return &stored, nil
 }
@@ -215,7 +206,7 @@ func (ms *Storage) GetResponse(ctx context.Context, id string) (*StoredResponse,
 func (ms *Storage) GetResponses(ctx context.Context) ([]StoredResponse, error) {
 	gotResponses, err := ms.db.ReadAll(ctx, responseNamespace)
 	if err != nil {
-		return nil, util.LoggingErrorMsg(err, "could not get all responses")
+		return nil, util.LoggingErrorMsg(err, "getting all responses")
 	}
 	if len(gotResponses) == 0 {
 		logrus.Info("no responses to get")
@@ -227,7 +218,7 @@ func (ms *Storage) GetResponses(ctx context.Context) ([]StoredResponse, error) {
 		if err = json.Unmarshal(responseBytes, &nextResponse); err == nil {
 			stored = append(stored, nextResponse)
 		} else {
-			logrus.WithError(err).Errorf("could not unmarshal stored response: %s", responseKey)
+			logrus.WithError(err).Errorf("could not unmarshal stored response while getting all responses: %s", responseKey)
 		}
 	}
 	return stored, nil
@@ -235,7 +226,7 @@ func (ms *Storage) GetResponses(ctx context.Context) ([]StoredResponse, error) {
 
 func (ms *Storage) DeleteResponse(ctx context.Context, id string) error {
 	if err := ms.db.Delete(ctx, responseNamespace, id); err != nil {
-		return util.LoggingErrorMsgf(err, "could not delete response: %s", id)
+		return util.LoggingErrorMsgf(err, "deleting response: %s", id)
 	}
 	return nil
 }
@@ -264,18 +255,9 @@ func (ms *Storage) ReviewApplication(ctx context.Context, applicationID string,
 		return nil, nil, errors.Wrap(err, "storing credential response")
 	}
 
-	responseData, operationData, err := ms.db.UpdateValueAndOperation(
-		ctx,
-		responseNamespace,
-		response.ID,
-		storage.NewUpdater(m),
-		namespace.FromID(opID),
-		opID,
-		opsubmission.OperationUpdater{
-			UpdaterWithMap: storage.NewUpdater(map[string]any{
-				"done": true,
-			}),
-		})
+	responseData, operationData, err := ms.db.UpdateValueAndOperation(ctx, responseNamespace, response.ID,
+		storage.NewUpdater(m), namespace.FromID(opID), opID,
+		opsubmission.OperationUpdater{UpdaterWithMap: storage.NewUpdater(map[string]any{"done": true})})
 	if err != nil {
 		return nil, nil, errors.Wrap(err, "updating value and operation")
 	}
diff --git a/pkg/service/presentation/model/model.go b/pkg/service/presentation/model/model.go
index 3a9c064..fbb1482 100644
--- a/pkg/service/presentation/model/model.go
+++ b/pkg/service/presentation/model/model.go
@@ -5,15 +5,17 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	"github.com/TBD54566975/ssi-sdk/util"
 	"github.com/goccy/go-json"
+	"go.einride.tech/aip/filtering"
+
 	"github.com/tbd54566975/ssi-service/internal/credential"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/service/presentation/storage"
-	"go.einride.tech/aip/filtering"
 )
 
 type CreatePresentationDefinitionRequest struct {
 	PresentationDefinition exchange.PresentationDefinition `json:"presentationDefinition" validate:"required"`
 	Author                 string                          `json:"author" validate:"required"`
+	AuthorKID              string                          `json:"authorKid" validate:"required"`
 }
 
 func (cpr CreatePresentationDefinitionRequest) IsValid() error {
diff --git a/pkg/service/presentation/service.go b/pkg/service/presentation/service.go
index c94eb68..0fd97f2 100644
--- a/pkg/service/presentation/service.go
+++ b/pkg/service/presentation/service.go
@@ -8,6 +8,7 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential/signing"
 	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	sdkutil "github.com/TBD54566975/ssi-sdk/util"
+	"github.com/lestrrat-go/jwx/jws"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
@@ -103,12 +104,13 @@ func (s Service) CreatePresentationDefinition(ctx context.Context, request model
 		ID:                     request.PresentationDefinition.ID,
 		PresentationDefinition: request.PresentationDefinition,
 		Author:                 request.Author,
+		AuthorKID:              request.AuthorKID,
 	}
 
 	if err := s.storage.StorePresentation(ctx, storedPresentation); err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not store presentation")
 	}
-	defJWT, err := s.keystore.Sign(context.Background(), storedPresentation.Author, exchange.PresentationDefinitionEnvelope{PresentationDefinition: storedPresentation.PresentationDefinition})
+	defJWT, err := s.keystore.Sign(context.Background(), storedPresentation.AuthorKID, exchange.PresentationDefinitionEnvelope{PresentationDefinition: storedPresentation.PresentationDefinition})
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "signing presentation definition enveloper with author<%s>", storedPresentation.Author)
 	}
@@ -129,7 +131,8 @@ func (s Service) GetPresentationDefinition(ctx context.Context, request model.Ge
 	if storedPresentation == nil {
 		return nil, util.LoggingNewErrorf("presentation definition with id<%s> could not be found", request.ID)
 	}
-	defJWT, err := s.keystore.Sign(ctx, storedPresentation.Author, exchange.PresentationDefinitionEnvelope{PresentationDefinition: storedPresentation.PresentationDefinition})
+	// TODO(gabe) decouple this to a separate endpoint for presentation requests https://github.com/TBD54566975/ssi-service/issues/375
+	defJWT, err := s.keystore.Sign(ctx, storedPresentation.AuthorKID, exchange.PresentationDefinitionEnvelope{PresentationDefinition: storedPresentation.PresentationDefinition})
 	if err != nil {
 		return nil, util.LoggingErrorMsgf(err, "signing presentation definition envelope by issuer<%s>", storedPresentation.Author)
 	}
@@ -161,14 +164,23 @@ func (s Service) CreateSubmission(ctx context.Context, request model.CreateSubmi
 		return nil, errors.Wrap(err, "provided value is not a valid presentation submission")
 	}
 
-	sdkVP, err := signing.ParseVerifiablePresentationFromJWT(request.SubmissionJWT.String())
+	headers, _, vp, err := signing.ParseVerifiablePresentationFromJWT(request.SubmissionJWT.String())
 	if err != nil {
 		return nil, errors.Wrap(err, "parsing vp from jwt")
 	}
 
+	gotKID, ok := headers.Get(jws.KeyIDKey)
+	if !ok {
+		return nil, errors.New("kid not found in token headers")
+	}
+	kid, ok := gotKID.(string)
+	if !ok {
+		return nil, errors.New("kid not a string")
+	}
+
 	// verify the token with the did by first resolving the did and getting the public key and next verifying the token
-	if err = didint.VerifyTokenFromDID(ctx, s.resolver, sdkVP.Holder, request.SubmissionJWT); err != nil {
-		return nil, errors.Wrap(err, "verifying token from did")
+	if err = didint.VerifyTokenFromDID(ctx, s.resolver, vp.Holder, kid, request.SubmissionJWT); err != nil {
+		return nil, errors.Wrapf(err, "verifying token from did<%s> with kid<%s>", vp.Holder, kid)
 	}
 
 	if _, err = s.storage.GetSubmission(ctx, request.Submission.ID); !errors.Is(err, presentationstorage.ErrSubmissionNotFound) {
diff --git a/pkg/service/presentation/storage.go b/pkg/service/presentation/storage.go
index eec68e9..53ff984 100644
--- a/pkg/service/presentation/storage.go
+++ b/pkg/service/presentation/storage.go
@@ -8,13 +8,14 @@ import (
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
+	"go.einride.tech/aip/filtering"
+
 	"github.com/tbd54566975/ssi-service/internal/util"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage/namespace"
 	opsubmission "github.com/tbd54566975/ssi-service/pkg/service/operation/submission"
 	prestorage "github.com/tbd54566975/ssi-service/pkg/service/presentation/storage"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
-	"go.einride.tech/aip/filtering"
 )
 
 const (
@@ -25,6 +26,7 @@ type StoredPresentation struct {
 	ID                     string                          `json:"id"`
 	PresentationDefinition exchange.PresentationDefinition `json:"presentationDefinition"`
 	Author                 string                          `json:"issuerID"`
+	AuthorKID              string                          `json:"issuerKid"`
 }
 
 type Storage struct {
diff --git a/pkg/service/schema/model.go b/pkg/service/schema/model.go
index fc8ffd8..40fd169 100644
--- a/pkg/service/schema/model.go
+++ b/pkg/service/schema/model.go
@@ -15,7 +15,10 @@ type CreateSchemaRequest struct {
 	Author string            `json:"author" validate:"required"`
 	Name   string            `json:"name" validate:"required"`
 	Schema schema.JSONSchema `json:"schema" validate:"required"`
-	Sign   bool              `json:"signed"`
+
+	// If sign == true, the schema will be signed by the author's private key with the specified KID
+	Sign      bool   `json:"signed"`
+	AuthorKID string `json:"authorKid"`
 }
 
 func (csr CreateSchemaRequest) IsValid() bool {
diff --git a/pkg/service/schema/service.go b/pkg/service/schema/service.go
index 7c84745..0dfc080 100644
--- a/pkg/service/schema/service.go
+++ b/pkg/service/schema/service.go
@@ -11,12 +11,12 @@ import (
 	sdkutil "github.com/TBD54566975/ssi-sdk/util"
 	"github.com/goccy/go-json"
 	"github.com/google/uuid"
+	"github.com/lestrrat-go/jwx/jws"
 	"github.com/lestrrat-go/jwx/jwt"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
 	"github.com/tbd54566975/ssi-service/config"
-	"github.com/tbd54566975/ssi-service/internal/did"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
@@ -80,7 +80,7 @@ func NewSchemaService(config config.SchemaServiceConfig, s storage.ServiceStorag
 }
 
 // CreateSchema houses the main service logic for schema creation. It validates the input, and
-// produces a schema value that conforms with the VC JSON JSONSchema specification.
+// produces a schema value that conforms with the VC JSON SchemaID specification.
 // TODO(gabe) support data integrity proof generation on schemas, versioning, and more
 func (s Service) CreateSchema(ctx context.Context, request CreateSchemaRequest) (*CreateSchemaResponse, error) {
 
@@ -114,7 +114,7 @@ func (s Service) CreateSchema(ctx context.Context, request CreateSchemaRequest)
 
 	// sign the schema
 	if request.Sign {
-		signedSchema, err := s.signSchemaJWT(ctx, request.Author, schemaValue)
+		signedSchema, err := s.signSchemaJWT(ctx, request.AuthorKID, schemaValue)
 		if err != nil {
 			return nil, util.LoggingError(err)
 		}
@@ -143,25 +143,25 @@ func prepareJSONSchema(id, name string, s schema.JSONSchema) schema.JSONSchema {
 }
 
 // signSchemaJWT signs a schema after the key associated with the provided author for the schema as a JWT
-func (s Service) signSchemaJWT(ctx context.Context, author string, schema schema.VCJSONSchema) (*keyaccess.JWT, error) {
-	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: author})
+func (s Service) signSchemaJWT(ctx context.Context, authorKID string, schema schema.VCJSONSchema) (*keyaccess.JWT, error) {
+	gotKey, err := s.keyStore.GetKey(ctx, keystore.GetKeyRequest{ID: authorKID})
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not get key for signing schema for author<%s>", author)
+		return nil, util.LoggingErrorMsgf(err, "could not get key for signing schema for authorKID<%s>", authorKID)
 	}
-	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not create key access for signing schema for author<%s>", author)
+		return nil, util.LoggingErrorMsgf(err, "could not create key access for signing schema for authorKID<%s>", authorKID)
 	}
 	schemaJSONBytes, err := sdkutil.ToJSONMap(schema)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not marshal schema for signing for author<%s>", author)
+		return nil, util.LoggingErrorMsgf(err, "could not marshal schema for signing for authorKID<%s>", authorKID)
 	}
 	schemaToken, err := keyAccess.SignWithDefaults(schemaJSONBytes)
 	if err != nil {
-		return nil, util.LoggingErrorMsgf(err, "could not sign schema for author<%s>", author)
+		return nil, util.LoggingErrorMsgf(err, "could not sign schema for authorKID<%s>", authorKID)
 	}
 	if _, err = s.verifySchemaJWT(ctx, keyaccess.JWT(schemaToken)); err != nil {
-		return nil, util.LoggingErrorMsg(err, "could not verify signed schema")
+		return nil, util.LoggingErrorMsg(err, "could not verify schema was signed correctly")
 	}
 	return keyaccess.JWTPtr(string(schemaToken)), nil
 }
@@ -185,11 +185,26 @@ func (s Service) VerifySchema(ctx context.Context, request VerifySchemaRequest)
 }
 
 func (s Service) verifySchemaJWT(ctx context.Context, token keyaccess.JWT) (*schema.VCJSONSchema, error) {
-	parsed, err := jwt.Parse([]byte(token))
+	// parse headers
+	headers, err := keyaccess.GetJWTHeaders([]byte(token))
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not parse JWT headers")
+	}
+	jwtKID, ok := headers.Get(jws.KeyIDKey)
+	if !ok {
+		return nil, util.LoggingNewError("JWT does not contain a kid")
+	}
+	kid, ok := jwtKID.(string)
+	if !ok {
+		return nil, util.LoggingNewError("JWT kid is not a string")
+	}
+
+	// parse token
+	parsedToken, err := jwt.Parse([]byte(token))
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not parse JWT")
 	}
-	claims := parsed.PrivateClaims()
+	claims := parsedToken.PrivateClaims()
 	claimsJSONBytes, err := json.Marshal(claims)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not marshal claims")
@@ -202,11 +217,11 @@ func (s Service) verifySchemaJWT(ctx context.Context, token keyaccess.JWT) (*sch
 	if err != nil {
 		return nil, errors.Wrapf(err, "failed to resolve schema author's did: %s", parsedSchema.Author)
 	}
-	kid, pubKey, err := did.GetVerificationInformation(resolved.Document, "")
+	pubKey, err := didsdk.GetKeyFromVerificationMethod(resolved.Document, kid)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not get verification information from schema")
 	}
-	verifier, err := keyaccess.NewJWKKeyAccessVerifier(kid, pubKey)
+	verifier, err := keyaccess.NewJWKKeyAccessVerifier(parsedSchema.Author, kid, pubKey)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not create schema verifier")
 	}
diff --git a/pkg/service/webhook/model.go b/pkg/service/webhook/model.go
index 46e87d8..d4877c0 100644
--- a/pkg/service/webhook/model.go
+++ b/pkg/service/webhook/model.go
@@ -12,7 +12,7 @@ const (
 	Credential   = Noun("Credential")
 	DID          = Noun("DID")
 	Manifest     = Noun("Manifest")
-	Schema       = Noun("Schema")
+	Schema       = Noun("SchemaID")
 	Presentation = Noun("Presentation")
 )
 


Test patch:
diff --git a/integration/credential_revocation_concurrency_integration_test.go b/integration/credential_revocation_concurrency_integration_test.go
index 20836d8..6181702 100644
--- a/integration/credential_revocation_concurrency_integration_test.go
+++ b/integration/credential_revocation_concurrency_integration_test.go
@@ -19,6 +19,10 @@ func TestCreateRevocationVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Contains(t, issuerDID, "did:key")
 
+	issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaOutput, err := CreateKYCSchema()
 	assert.NoError(t, err)
 
@@ -26,7 +30,7 @@ func TestCreateRevocationVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
-	vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, SchemaID: schemaID, SubjectID: issuerDID}, true)
+	vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, vcOutput)
 
@@ -53,6 +57,10 @@ func TestCreateRevocationVerifiableCredentialShareStatusListIntegration(t *testi
 	assert.NoError(t, err)
 	assert.Contains(t, issuerDID, "did:key")
 
+	issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaOutput, err := CreateKYCSchema()
 	assert.NoError(t, err)
 
@@ -60,7 +68,7 @@ func TestCreateRevocationVerifiableCredentialShareStatusListIntegration(t *testi
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
-	vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, SchemaID: schemaID, SubjectID: issuerDID}, true)
+	vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, vcOutput)
 
@@ -74,7 +82,7 @@ func TestCreateRevocationVerifiableCredentialShareStatusListIntegration(t *testi
 	assert.NotEmpty(t, credStatusListURL)
 	assert.Contains(t, credStatusListURL, "http")
 
-	vcOutputTwo, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, SchemaID: schemaID, SubjectID: issuerDID}, true)
+	vcOutputTwo, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, vcOutputTwo)
 
@@ -103,6 +111,10 @@ func TestConcurrencyRevocationVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.Contains(t, issuerDID, "did:key")
 
+	issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaOutput, err := CreateKYCSchema()
 	assert.NoError(t, err)
 
@@ -123,7 +135,7 @@ func TestConcurrencyRevocationVerifiableCredentialIntegration(t *testing.T) {
 		go func() {
 			defer wg.Done()
 
-			vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, SchemaID: schemaID, SubjectID: issuerDID}, true)
+			vcOutput, err := CreateVerifiableCredential(credInputParams{IssuerID: issuerDID, IssuerKID: issuerKID, SchemaID: schemaID, SubjectID: issuerDID}, true)
 
 			// We're hammering the DB, so some calls might fail due to internal timeouts or similar. Upon failure, we
 			// shouldn't check any assertions, since we know they'll fail.
diff --git a/integration/credential_revocation_integration_test.go b/integration/credential_revocation_integration_test.go
index acb3fab..49461ab 100644
--- a/integration/credential_revocation_integration_test.go
+++ b/integration/credential_revocation_integration_test.go
@@ -20,10 +20,14 @@ func TestRevocationCreateIssuerDIDKeyIntegration(t *testing.T) {
 	assert.NoError(t, err)
 
 	issuerDID, err := getJSONElement(didKeyOutput, "$.did.id")
+	assert.NoError(t, err)
+	assert.Contains(t, issuerDID, "did:key")
 	SetValue(credentialRevocationContext, "issuerDID", issuerDID)
 
+	issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
 	assert.NoError(t, err)
-	assert.Contains(t, issuerDID, "did:key")
+	assert.NotEmpty(t, issuerKID)
+	SetValue(credentialRevocationContext, "issuerKID", issuerKID)
 }
 
 func TestRevocationCreateSchemaIntegration(t *testing.T) {
@@ -35,10 +39,9 @@ func TestRevocationCreateSchemaIntegration(t *testing.T) {
 	assert.NoError(t, err)
 
 	schemaID, err := getJSONElement(output, "$.id")
-	SetValue(credentialRevocationContext, "schemaID", schemaID)
-
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
+	SetValue(credentialRevocationContext, "schemaID", schemaID)
 }
 
 func TestRevocationCreateVerifiableCredentialIntegration(t *testing.T) {
@@ -50,12 +53,17 @@ func TestRevocationCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
+	issuerKID, err := GetValue(credentialRevocationContext, "issuerKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaID, err := GetValue(credentialRevocationContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	vcOutput, err := CreateVerifiableCredential(credInputParams{
 		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
 		SchemaID:  schemaID.(string),
 		SubjectID: issuerDID.(string),
 	}, true)
@@ -63,21 +71,21 @@ func TestRevocationCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NotEmpty(t, vcOutput)
 
 	cred, err := getJSONElement(vcOutput, "$.credential")
-	SetValue(credentialRevocationContext, "cred", cred)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, cred)
+	SetValue(credentialRevocationContext, "cred", cred)
 
 	credStatusURL, err := getJSONElement(vcOutput, "$.credential.credentialStatus.id")
-	SetValue(credentialRevocationContext, "credStatusURL", credStatusURL)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credStatusURL)
 	assert.Contains(t, credStatusURL, "http")
+	SetValue(credentialRevocationContext, "credStatusURL", credStatusURL)
 
 	statusListCredentialURL, err := getJSONElement(vcOutput, "$.credential.credentialStatus.statusListCredential")
-	SetValue(credentialRevocationContext, "statusListCredentialURL", statusListCredentialURL)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, statusListCredentialURL)
 	assert.Contains(t, statusListCredentialURL, "http")
+	SetValue(credentialRevocationContext, "statusListCredentialURL", statusListCredentialURL)
 
 	credStatusListCredentialOutput, err := get(statusListCredentialURL)
 	assert.NoError(t, err)
@@ -87,7 +95,6 @@ func TestRevocationCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, encodedListOriginal)
 	SetValue(credentialRevocationContext, "encodedListOriginal", encodedListOriginal)
-
 }
 
 func TestRevocationCheckStatusIntegration(t *testing.T) {
diff --git a/integration/didion_integration_test.go b/integration/didion_integration_test.go
index 22e0ea1..2caf45e 100644
--- a/integration/didion_integration_test.go
+++ b/integration/didion_integration_test.go
@@ -20,13 +20,13 @@ func TestCreateIssuerDIDIONIntegration(t *testing.T) {
 
 	issuerDID, err := getJSONElement(didIONOutput, "$.did.id")
 	assert.NoError(t, err)
+	assert.Contains(t, issuerDID, "did:ion")
 	SetValue(didIONContext, "issuerDID", issuerDID)
 
-	issuerKeyID, err := getJSONElement(didIONOutput, "$.did.verificationMethod[0].id")
-	SetValue(didIONContext, "issuerKeyID", issuerKeyID)
-
+	issuerKID, err := getJSONElement(didIONOutput, "$.did.verificationMethod[0].id")
 	assert.NoError(t, err)
-	assert.Contains(t, issuerDID, "did:ion")
+	assert.NotEmpty(t, issuerKID)
+	SetValue(didIONContext, "issuerKID", issuerKID)
 }
 
 func TestCreateAliceDIDIONIntegration(t *testing.T) {
@@ -43,13 +43,10 @@ func TestCreateAliceDIDIONIntegration(t *testing.T) {
 	assert.NotEmpty(t, aliceDID)
 	SetValue(didIONContext, "aliceDID", aliceDID)
 
-	aliceKeyID, err := getJSONElement(didIONOutput, "$.did.verificationMethod[0].id")
-	SetValue(didIONContext, "aliceKeyID", aliceKeyID)
+	aliceKID, err := getJSONElement(didIONOutput, "$.did.verificationMethod[0].id")
 	assert.NoError(t, err)
-	assert.NotEmpty(t, aliceKeyID)
-
-	assert.NoError(t, err)
-	assert.Contains(t, aliceDID, "did:ion")
+	assert.NotEmpty(t, aliceKID)
+	SetValue(didIONContext, "aliceKID", aliceKID)
 
 	aliceDIDPrivateKey, err := getJSONElement(didIONOutput, "$.privateKeyBase58")
 	assert.NoError(t, err)
@@ -81,16 +78,17 @@ func TestDIDIONCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
-	issuerKeyID, err := GetValue(didIONContext, "issuerKeyID")
+	issuerKID, err := GetValue(didIONContext, "issuerKID")
 	assert.NoError(t, err)
-	assert.NotEmpty(t, issuerKeyID)
+	assert.NotEmpty(t, issuerKID)
 
 	schemaID, err := GetValue(didIONContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	vcOutput, err := CreateVerifiableCredential(credInputParams{
-		IssuerID:  issuerDID.(string) + "#" + issuerKeyID.(string),
+		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
 		SchemaID:  schemaID.(string),
 		SubjectID: issuerDID.(string),
 	}, false)
@@ -98,9 +96,9 @@ func TestDIDIONCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NotEmpty(t, vcOutput)
 
 	credentialJWT, err := getJSONElement(vcOutput, "$.credentialJwt")
-	SetValue(didIONContext, "credentialJWT", credentialJWT)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credentialJWT)
+	SetValue(didIONContext, "credentialJWT", credentialJWT)
 }
 
 func TestDIDIONCreateCredentialManifestIntegration(t *testing.T) {
@@ -112,29 +110,30 @@ func TestDIDIONCreateCredentialManifestIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
-	issuerKeyID, err := GetValue(didIONContext, "issuerKeyID")
+	issuerKID, err := GetValue(didIONContext, "issuerKID")
 	assert.NoError(t, err)
-	assert.NotEmpty(t, issuerKeyID)
+	assert.NotEmpty(t, issuerKID)
 
 	schemaID, err := GetValue(didIONContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	cmOutput, err := CreateCredentialManifest(credManifestParams{
-		IssuerID: issuerDID.(string) + "#" + issuerKeyID.(string),
-		SchemaID: schemaID.(string),
+		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
+		SchemaID:  schemaID.(string),
 	})
 	assert.NoError(t, err)
 
 	presentationDefinitionID, err := getJSONElement(cmOutput, "$.credential_manifest.presentation_definition.id")
-	SetValue(didIONContext, "presentationDefinitionID", presentationDefinitionID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, presentationDefinitionID)
+	SetValue(didIONContext, "presentationDefinitionID", presentationDefinitionID)
 
 	manifestID, err := getJSONElement(cmOutput, "$.credential_manifest.id")
-	SetValue(didIONContext, "manifestID", manifestID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, manifestID)
+	SetValue(didIONContext, "manifestID", manifestID)
 }
 
 func TestDIDIONSubmitAndReviewApplicationIntegration(t *testing.T) {
@@ -158,9 +157,9 @@ func TestDIDIONSubmitAndReviewApplicationIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, aliceDID)
 
-	aliceKeyID, err := GetValue(didIONContext, "aliceKeyID")
+	aliceKID, err := GetValue(didIONContext, "aliceKID")
 	assert.NoError(t, err)
-	assert.NotEmpty(t, aliceDID)
+	assert.NotEmpty(t, aliceKID)
 
 	aliceDIDPrivateKey, err := GetValue(didIONContext, "aliceDIDPrivateKey")
 	assert.NoError(t, err)
@@ -169,7 +168,7 @@ func TestDIDIONSubmitAndReviewApplicationIntegration(t *testing.T) {
 	credAppJWT, err := CreateCredentialApplicationJWT(credApplicationParams{
 		DefinitionID: presentationDefinitionID.(string),
 		ManifestID:   manifestID.(string),
-	}, credentialJWT.(string), aliceDID.(string)+"#"+aliceKeyID.(string), aliceDIDPrivateKey.(string))
+	}, credentialJWT.(string), aliceDID.(string), aliceKID.(string), aliceDIDPrivateKey.(string))
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credAppJWT)
 
diff --git a/integration/didweb_integration_test.go b/integration/didweb_integration_test.go
index 0d912e0..f37d64b 100644
--- a/integration/didweb_integration_test.go
+++ b/integration/didweb_integration_test.go
@@ -19,10 +19,14 @@ func TestCreateIssuerDIDWebIntegration(t *testing.T) {
 	assert.NoError(t, err)
 
 	issuerDID, err := getJSONElement(didWebOutput, "$.did.id")
+	assert.NoError(t, err)
+	assert.Contains(t, issuerDID, "did:web")
 	SetValue(didWebContext, "issuerDID", issuerDID)
 
+	issuerKID, err := getJSONElement(didWebOutput, "$.did.verificationMethod[0].id")
 	assert.NoError(t, err)
-	assert.Contains(t, issuerDID, "did:web")
+	assert.NotEmpty(t, issuerKID)
+	SetValue(didWebContext, "issuerKID", issuerKID)
 }
 
 func TestCreateAliceDIDWebIntegration(t *testing.T) {
@@ -35,15 +39,19 @@ func TestCreateAliceDIDWebIntegration(t *testing.T) {
 	assert.NotEmpty(t, didWebOutput)
 
 	aliceDID, err := getJSONElement(didWebOutput, "$.did.id")
+	assert.NoError(t, err)
+	assert.Contains(t, aliceDID, "did:web")
 	SetValue(didWebContext, "aliceDID", aliceDID)
 
+	aliceKID, err := getJSONElement(didWebOutput, "$.did.verificationMethod[0].id")
 	assert.NoError(t, err)
-	assert.Contains(t, aliceDID, "did:web")
+	assert.NotEmpty(t, aliceKID)
+	SetValue(didWebContext, "aliceKID", aliceKID)
 
 	aliceDIDPrivateKey, err := getJSONElement(didWebOutput, "$.privateKeyBase58")
-	SetValue(didWebContext, "aliceDIDPrivateKey", aliceDIDPrivateKey)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, aliceDID)
+	SetValue(didWebContext, "aliceDIDPrivateKey", aliceDIDPrivateKey)
 }
 
 func TestDIDWebCreateSchemaIntegration(t *testing.T) {
@@ -55,10 +63,9 @@ func TestDIDWebCreateSchemaIntegration(t *testing.T) {
 	assert.NoError(t, err)
 
 	schemaID, err := getJSONElement(output, "$.id")
-	SetValue(didWebContext, "schemaID", schemaID)
-
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
+	SetValue(didWebContext, "schemaID", schemaID)
 }
 
 func TestDIDWebCreateVerifiableCredentialIntegration(t *testing.T) {
@@ -70,12 +77,17 @@ func TestDIDWebCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
+	issuerKID, err := GetValue(didWebContext, "issuerKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaID, err := GetValue(didWebContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	vcOutput, err := CreateVerifiableCredential(credInputParams{
 		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
 		SchemaID:  schemaID.(string),
 		SubjectID: issuerDID.(string),
 	}, false)
@@ -83,9 +95,9 @@ func TestDIDWebCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NotEmpty(t, vcOutput)
 
 	credentialJWT, err := getJSONElement(vcOutput, "$.credentialJwt")
-	SetValue(didWebContext, "credentialJWT", credentialJWT)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credentialJWT)
+	SetValue(didWebContext, "credentialJWT", credentialJWT)
 }
 
 func TestDIDWebCreateCredentialManifestIntegration(t *testing.T) {
@@ -97,25 +109,30 @@ func TestDIDWebCreateCredentialManifestIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
+	issuerKID, err := GetValue(didWebContext, "issuerKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaID, err := GetValue(didWebContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	cmOutput, err := CreateCredentialManifest(credManifestParams{
-		IssuerID: issuerDID.(string),
-		SchemaID: schemaID.(string),
+		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
+		SchemaID:  schemaID.(string),
 	})
 	assert.NoError(t, err)
 
 	presentationDefinitionID, err := getJSONElement(cmOutput, "$.credential_manifest.presentation_definition.id")
-	SetValue(didWebContext, "presentationDefinitionID", presentationDefinitionID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, presentationDefinitionID)
+	SetValue(didWebContext, "presentationDefinitionID", presentationDefinitionID)
 
 	manifestID, err := getJSONElement(cmOutput, "$.credential_manifest.id")
-	SetValue(didWebContext, "manifestID", manifestID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, manifestID)
+	SetValue(didWebContext, "manifestID", manifestID)
 }
 
 func TestDIDWebSubmitAndReviewApplicationIntegration(t *testing.T) {
@@ -139,6 +156,10 @@ func TestDIDWebSubmitAndReviewApplicationIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, aliceDID)
 
+	aliceKID, err := GetValue(didWebContext, "aliceKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, aliceKID)
+
 	aliceDIDPrivateKey, err := GetValue(didWebContext, "aliceDIDPrivateKey")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, aliceDIDPrivateKey)
@@ -146,7 +167,7 @@ func TestDIDWebSubmitAndReviewApplicationIntegration(t *testing.T) {
 	credAppJWT, err := CreateCredentialApplicationJWT(credApplicationParams{
 		DefinitionID: presentationDefinitionID.(string),
 		ManifestID:   manifestID.(string),
-	}, credentialJWT.(string), aliceDID.(string), aliceDIDPrivateKey.(string))
+	}, credentialJWT.(string), aliceDID.(string), aliceKID.(string), aliceDIDPrivateKey.(string))
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credAppJWT)
 
diff --git a/integration/presentation_exchange_integration_test.go b/integration/presentation_exchange_integration_test.go
index d5ae710..ea5c6fe 100644
--- a/integration/presentation_exchange_integration_test.go
+++ b/integration/presentation_exchange_integration_test.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/google/uuid"
 	"github.com/stretchr/testify/assert"
+
 	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 )
 
@@ -21,6 +22,12 @@ func TestCreateParticipants(t *testing.T) {
 	issuerDID, err := getJSONElement(didKeyOutput, "$.did.id")
 	assert.NoError(t, err)
 	assert.Contains(t, issuerDID, "did:key")
+	SetValue(presentationExchangeContext, "issuerDID", issuerDID)
+
+	issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+	SetValue(presentationExchangeContext, "issuerKID", issuerKID)
 
 	holderOutput, err := CreateDIDKey()
 	assert.NoError(t, err)
@@ -28,9 +35,16 @@ func TestCreateParticipants(t *testing.T) {
 	holderDID, err := getJSONElement(holderOutput, "$.did.id")
 	assert.NoError(t, err)
 	assert.Contains(t, holderDID, "did:key")
+	SetValue(presentationExchangeContext, "holderDID", holderDID)
+
+	holderKID, err := getJSONElement(holderOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, holderKID)
+	SetValue(presentationExchangeContext, "holderKID", holderKID)
 
 	holderPrivateKey, err := getJSONElement(holderOutput, "$.privateKeyBase58")
 	assert.NoError(t, err)
+	SetValue(presentationExchangeContext, "holderPrivateKey", holderPrivateKey)
 
 	verifierOutput, err := CreateDIDKey()
 	assert.NoError(t, err)
@@ -38,11 +52,12 @@ func TestCreateParticipants(t *testing.T) {
 	verifierDID, err := getJSONElement(verifierOutput, "$.did.id")
 	assert.NoError(t, err)
 	assert.Contains(t, holderDID, "did:key")
-
-	SetValue(presentationExchangeContext, "issuerDID", issuerDID)
-	SetValue(presentationExchangeContext, "holderDID", holderDID)
 	SetValue(presentationExchangeContext, "verifierDID", verifierDID)
-	SetValue(presentationExchangeContext, "holderPrivateKey", holderPrivateKey)
+
+	verifierKID, err := getJSONElement(verifierOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, verifierKID)
+	SetValue(presentationExchangeContext, "verifierKID", verifierKID)
 }
 
 func TestCreatePresentationDefinition(t *testing.T) {
@@ -53,7 +68,13 @@ func TestCreatePresentationDefinition(t *testing.T) {
 	verifierDID, err := GetValue(presentationExchangeContext, "verifierDID")
 	assert.NoError(t, err)
 
-	definition, err := CreatePresentationDefinition(definitionParams{Author: verifierDID.(string)})
+	verifierKID, err := GetValue(presentationExchangeContext, "verifierKID")
+	assert.NoError(t, err)
+
+	definition, err := CreatePresentationDefinition(definitionParams{
+		Author:    verifierDID.(string),
+		AuthorKID: verifierKID.(string),
+	})
 	assert.NoError(t, err)
 
 	definitionID, err := getJSONElement(definition, "$.presentation_definition.id")
@@ -72,14 +93,21 @@ func TestSubmissionFlow(t *testing.T) {
 	holderDID, err := GetValue(presentationExchangeContext, "holderDID")
 	assert.NoError(t, err)
 
+	holderKID, err := GetValue(presentationExchangeContext, "holderKID")
+	assert.NoError(t, err)
+
 	holderPrivateKey, err := GetValue(presentationExchangeContext, "holderPrivateKey")
 	assert.NoError(t, err)
 
 	issuerDID, err := GetValue(presentationExchangeContext, "issuerDID")
 	assert.NoError(t, err)
 
+	issuerKID, err := GetValue(presentationExchangeContext, "issuerKID")
+	assert.NoError(t, err)
+
 	credOutput, err := CreateSubmissionCredential(credInputParams{
 		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
 		SubjectID: holderDID.(string),
 	})
 	assert.NoError(t, err)
@@ -89,6 +117,7 @@ func TestSubmissionFlow(t *testing.T) {
 
 	toBeCancelledOp, err := CreateSubmission(submissionParams{
 		HolderID:      holderDID.(string),
+		HolderKID:     holderKID.(string),
 		DefinitionID:  definitionID.(string),
 		CredentialJWT: credentialJWT,
 		SubmissionID:  uuid.NewString(),
@@ -105,6 +134,7 @@ func TestSubmissionFlow(t *testing.T) {
 
 	submissionOpOutput, err := CreateSubmission(submissionParams{
 		HolderID:      holderDID.(string),
+		HolderKID:     holderKID.(string),
 		DefinitionID:  definitionID.(string),
 		CredentialJWT: credentialJWT,
 		SubmissionID:  uuid.NewString(),
diff --git a/integration/steelthread_integration_test.go b/integration/steelthread_integration_test.go
index f0d21d1..ae87d8c 100644
--- a/integration/steelthread_integration_test.go
+++ b/integration/steelthread_integration_test.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential/util"
 	"github.com/stretchr/testify/assert"
+
 	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 )
 
@@ -19,11 +20,14 @@ func TestCreateIssuerDIDKeyIntegration(t *testing.T) {
 	assert.NoError(t, err)
 
 	issuerDID, err := getJSONElement(didKeyOutput, "$.did.id")
-	SetValue(steelThreadContext, "issuerDID", issuerDID)
-
 	assert.NoError(t, err)
 	assert.Contains(t, issuerDID, "did:key")
+	SetValue(steelThreadContext, "issuerDID", issuerDID)
 
+	issuerKID, err := getJSONElement(didKeyOutput, "$.did.verificationMethod[0].id")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+	SetValue(steelThreadContext, "issuerKID", issuerKID)
 }
 
 func TestResolveIONDIDIntegration(t *testing.T) {
@@ -50,16 +54,14 @@ func TestCreateAliceDIDKeyIntegration(t *testing.T) {
 	assert.NotEmpty(t, didKeyOutput)
 
 	aliceDID, err := getJSONElement(didKeyOutput, "$.did.id")
-	SetValue(steelThreadContext, "aliceDID", aliceDID)
-
 	assert.NoError(t, err)
 	assert.Contains(t, aliceDID, "did:key")
+	SetValue(steelThreadContext, "aliceDID", aliceDID)
 
 	aliceDIDPrivateKey, err := getJSONElement(didKeyOutput, "$.privateKeyBase58")
-	SetValue(steelThreadContext, "aliceDIDPrivateKey", aliceDIDPrivateKey)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, aliceDID)
-
+	SetValue(steelThreadContext, "aliceDIDPrivateKey", aliceDIDPrivateKey)
 }
 
 func TestCreateSchemaIntegration(t *testing.T) {
@@ -71,10 +73,9 @@ func TestCreateSchemaIntegration(t *testing.T) {
 	assert.NoError(t, err)
 
 	schemaID, err := getJSONElement(output, "$.id")
-	SetValue(steelThreadContext, "schemaID", schemaID)
-
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
+	SetValue(steelThreadContext, "schemaID", schemaID)
 }
 
 func TestCreateVerifiableCredentialIntegration(t *testing.T) {
@@ -86,12 +87,17 @@ func TestCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
+	issuerKID, err := GetValue(steelThreadContext, "issuerKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaID, err := GetValue(steelThreadContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	vcOutput, err := CreateVerifiableCredential(credInputParams{
 		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
 		SchemaID:  schemaID.(string),
 		SubjectID: issuerDID.(string),
 	}, false)
@@ -99,9 +105,9 @@ func TestCreateVerifiableCredentialIntegration(t *testing.T) {
 	assert.NotEmpty(t, vcOutput)
 
 	credentialJWT, err := getJSONElement(vcOutput, "$.credentialJwt")
-	SetValue(steelThreadContext, "credentialJWT", credentialJWT)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credentialJWT)
+	SetValue(steelThreadContext, "credentialJWT", credentialJWT)
 }
 
 func TestCreateCredentialManifestIntegration(t *testing.T) {
@@ -113,25 +119,30 @@ func TestCreateCredentialManifestIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
+	issuerKID, err := GetValue(steelThreadContext, "issuerKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaID, err := GetValue(steelThreadContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	cmOutput, err := CreateCredentialManifest(credManifestParams{
-		IssuerID: issuerDID.(string),
-		SchemaID: schemaID.(string),
+		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
+		SchemaID:  schemaID.(string),
 	})
 	assert.NoError(t, err)
 
 	presentationDefinitionID, err := getJSONElement(cmOutput, "$.credential_manifest.presentation_definition.id")
-	SetValue(steelThreadContext, "presentationDefinitionID", presentationDefinitionID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, presentationDefinitionID)
+	SetValue(steelThreadContext, "presentationDefinitionID", presentationDefinitionID)
 
 	manifestID, err := getJSONElement(cmOutput, "$.credential_manifest.id")
-	SetValue(steelThreadContext, "manifestID", manifestID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, manifestID)
+	SetValue(steelThreadContext, "manifestID", manifestID)
 }
 
 func TestCreateIssuanceTemplateIntegration(t *testing.T) {
@@ -143,30 +154,36 @@ func TestCreateIssuanceTemplateIntegration(t *testing.T) {
 	assert.NoError(t, err)
 	assert.NotEmpty(t, issuerDID)
 
+	issuerKID, err := GetValue(steelThreadContext, "issuerKID")
+	assert.NoError(t, err)
+	assert.NotEmpty(t, issuerKID)
+
 	schemaID, err := GetValue(steelThreadContext, "schemaID")
 	assert.NoError(t, err)
 	assert.NotEmpty(t, schemaID)
 
 	cmOutput, err := CreateCredentialManifest(credManifestParams{
-		IssuerID: issuerDID.(string),
-		SchemaID: schemaID.(string),
+		IssuerID:  issuerDID.(string),
+		IssuerKID: issuerKID.(string),
+		SchemaID:  schemaID.(string),
 	})
 	assert.NoError(t, err)
 
 	manifestID, err := getJSONElement(cmOutput, "$.credential_manifest.id")
-	SetValue(steelThreadContext, "manifestWithIssuanceTemplateID", manifestID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, manifestID)
+	SetValue(steelThreadContext, "manifestWithIssuanceTemplateID", manifestID)
 
 	presentationDefinitionID, err := getJSONElement(cmOutput, "$.credential_manifest.presentation_definition.id")
-	SetValue(steelThreadContext, "presentationDefinitionWithIssuanceTemplateID", presentationDefinitionID)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, presentationDefinitionID)
+	SetValue(steelThreadContext, "presentationDefinitionWithIssuanceTemplateID", presentationDefinitionID)
 
 	itOutput, err := CreateIssuanceTemplate(issuanceTemplateParams{
 		SchemaID:   schemaID.(string),
 		ManifestID: manifestID,
 		IssuerID:   issuerDID.(string),
+		IssuerKID:  issuerKID.(string),
 	})
 	assert.NoError(t, err)
 
@@ -204,7 +221,7 @@ func TestSubmitApplicationWithIssuanceTemplateIntegration(t *testing.T) {
 	credAppJWT, err := CreateCredentialApplicationJWT(credApplicationParams{
 		DefinitionID: presentationDefinitionID.(string),
 		ManifestID:   manifestID.(string),
-	}, credentialJWT.(string), aliceDID.(string), aliceDIDPrivateKey.(string))
+	}, credentialJWT.(string), aliceDID.(string), aliceDID.(string), aliceDIDPrivateKey.(string))
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credAppJWT)
 
@@ -257,7 +274,7 @@ func TestSubmitAndReviewApplicationIntegration(t *testing.T) {
 	credAppJWT, err := CreateCredentialApplicationJWT(credApplicationParams{
 		DefinitionID: presentationDefinitionID.(string),
 		ManifestID:   manifestID.(string),
-	}, credentialJWT.(string), aliceDID.(string), aliceDIDPrivateKey.(string))
+	}, credentialJWT.(string), aliceDID.(string), aliceDID.(string), aliceDIDPrivateKey.(string))
 	assert.NoError(t, err)
 	assert.NotEmpty(t, credAppJWT)
 
diff --git a/integration/testdata/credential-input.json b/integration/testdata/credential-input.json
index df1da5c..d38469c 100644
--- a/integration/testdata/credential-input.json
+++ b/integration/testdata/credential-input.json
@@ -14,8 +14,9 @@
     "taxID":"123"
   },
   "issuer": "{{.IssuerID}}",
+  "issuerKid": "{{.IssuerKID}}",
   "subject": "{{.SubjectID}}",
   "@context":"https://www.w3.org/2018/credentials/v1",
   "expiry": "2051-10-05T14:48:00.000Z",
-  "schema": "{{.SchemaID}}"
+  "schemaId": "{{.SchemaID}}"
 }
\ No newline at end of file
diff --git a/integration/testdata/credential-revocable-input.json b/integration/testdata/credential-revocable-input.json
index 136f2a3..7560dfa 100644
--- a/integration/testdata/credential-revocable-input.json
+++ b/integration/testdata/credential-revocable-input.json
@@ -14,9 +14,10 @@
     "taxID":"123"
   },
   "issuer": "{{.IssuerID}}",
+  "issuerKid": "{{.IssuerKID}}",
   "subject": "{{.SubjectID}}",
   "@context":"https://www.w3.org/2018/credentials/v1",
   "expiry": "2051-10-05T14:48:00.000Z",
-  "schema": "{{.SchemaID}}",
+  "schemaId": "{{.SchemaID}}",
   "revocable": true
 }
\ No newline at end of file
diff --git a/integration/testdata/did-input.json b/integration/testdata/did-input.json
index 169d9aa..b3cdddd 100644
--- a/integration/testdata/did-input.json
+++ b/integration/testdata/did-input.json
@@ -1,1 +1,3 @@
-{"keyType":"Ed25519"}
\ No newline at end of file
+{
+  "keyType": "Ed25519"
+}
\ No newline at end of file
diff --git a/integration/testdata/issuance-template-input.json b/integration/testdata/issuance-template-input.json
index 209b0b6..da9b857 100644
--- a/integration/testdata/issuance-template-input.json
+++ b/integration/testdata/issuance-template-input.json
@@ -1,6 +1,7 @@
 {
   "credentialManifest": "{{.ManifestID}}",
   "issuer": "{{.IssuerID}}",
+  "issuerKid": "{{.IssuerKID}}",
   "credentials": [
     {
       "id": "kyc_credential",
diff --git a/integration/testdata/manifest-input.json b/integration/testdata/manifest-input.json
index 55cb86b..2ca5f12 100644
--- a/integration/testdata/manifest-input.json
+++ b/integration/testdata/manifest-input.json
@@ -1,5 +1,6 @@
 {
-  "issuerDID":"{{.IssuerID}}",
+  "issuerDid":"{{.IssuerID}}",
+  "issuerKid": "{{.IssuerKID}}",
   "issuerName":"Issuer Name Lol",
   "format":{
     "jwt":{
diff --git a/integration/testdata/presentation-definition-input.json b/integration/testdata/presentation-definition-input.json
index 8ebd29b..aee1709 100644
--- a/integration/testdata/presentation-definition-input.json
+++ b/integration/testdata/presentation-definition-input.json
@@ -21,5 +21,6 @@
       }
     }
   ],
-  "author": "{{.Author}}"
+  "author": "{{.Author}}",
+  "authorKid": "{{.AuthorKID}}"
 }
\ No newline at end of file
diff --git a/integration/testdata/submission-credential-input.json b/integration/testdata/submission-credential-input.json
index 6c4e3e7..c9c5e4a 100644
--- a/integration/testdata/submission-credential-input.json
+++ b/integration/testdata/submission-credential-input.json
@@ -6,6 +6,7 @@
     "givenName": "Uribe"
   },
   "issuer": "{{.IssuerID}}",
+  "issuerKid": "{{.IssuerKID}}",
   "subject": "{{.SubjectID}}",
   "expiry": "2051-10-05T14:48:00.000Z"
 }
\ No newline at end of file
diff --git a/internal/did/access_test.go b/internal/did/access_test.go
deleted file mode 100644
index 6189fd7..0000000
--- a/internal/did/access_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-package did
-
-import (
-	"crypto"
-	"crypto/ed25519"
-	"fmt"
-	"testing"
-
-	"github.com/TBD54566975/ssi-sdk/did"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestGetVerificationInformation(t *testing.T) {
-	publicKey := map[string]struct {
-		base58    string
-		publicKey crypto.PublicKey
-	}{
-		"kid2": {
-			base58:    "4HyjANoMdhpp952YPb4wALydQRQ7BmsXHmBdwq4YSyiR",
-			publicKey: ed25519.PublicKey{0x30, 0xec, 0x7e, 0xbc, 0x71, 0xf, 0x76, 0xd1, 0xad, 0x90, 0x39, 0xb9, 0x94, 0xcd, 0x80, 0x9c, 0x42, 0x72, 0x94, 0x92, 0xf1, 0x46, 0xaf, 0xcc, 0x89, 0x9e, 0x8b, 0xe5, 0xcb, 0xd2, 0x47, 0xfa},
-		},
-		"an awesome kid": {
-			base58:    "z6MkgeW28gvxZGKzGchuPHpNeju7VKcx4ZAJue8N5RNa3qR5",
-			publicKey: ed25519.PublicKey{0x2, 0x3c, 0x2e, 0xdc, 0xec, 0x41, 0xbe, 0xa6, 0x33, 0x91, 0xe8, 0x60, 0xbe, 0x13, 0xda, 0x44, 0xe6, 0x69, 0x61, 0xa3, 0x9a, 0xf3, 0x68, 0x6a, 0xb6, 0xd3, 0xd5, 0xf4, 0xb1, 0x15, 0x4, 0x44, 0x89, 0x4c, 0xf4, 0xb4},
-		},
-	}
-
-	kid2Method := did.VerificationMethod{
-		ID:              "kid2",
-		Type:            "Ed25519",
-		PublicKeyBase58: publicKey["kid2"].base58,
-	}
-	awesomeKidMethod := did.VerificationMethod{
-		ID:              "an awesome kid",
-		Type:            "Ed25519",
-		PublicKeyBase58: publicKey["an awesome kid"].base58,
-	}
-	type args struct {
-		did      did.Document
-		maybeKID string
-	}
-	tests := []struct {
-		name       string
-		args       args
-		wantKid    string
-		wantPubKey crypto.PublicKey
-		wantErr    assert.ErrorAssertionFunc
-	}{
-		{
-			name: "multiple methods return the correct public key",
-			args: args{
-				did: did.Document{
-					ID: "my doc id",
-					VerificationMethod: []did.VerificationMethod{
-						kid2Method,
-						awesomeKidMethod,
-					},
-				},
-				maybeKID: "kid2",
-			},
-			wantKid:    "kid2",
-			wantPubKey: publicKey["kid2"].publicKey,
-			wantErr:    assert.NoError,
-		},
-		{
-			name: "single verification method without maybekid",
-			args: args{
-				did: did.Document{
-					ID: "my doc id",
-					VerificationMethod: []did.VerificationMethod{
-						awesomeKidMethod,
-					},
-				},
-				maybeKID: "",
-			},
-			wantKid:    "my doc id",
-			wantPubKey: publicKey["an awesome kid"].publicKey,
-			wantErr:    assert.NoError,
-		},
-		{
-			name: "single verification method with maybekid",
-			args: args{
-				did: did.Document{
-					ID: "my doc id",
-					VerificationMethod: []did.VerificationMethod{
-						awesomeKidMethod,
-					},
-				},
-				maybeKID: "an awesome kid",
-			},
-			wantKid:    "my doc id",
-			wantPubKey: publicKey["an awesome kid"].publicKey,
-			wantErr:    assert.NoError,
-		},
-		{
-			name: "things not great",
-			args: args{
-				did: did.Document{
-					ID: "my doc id",
-					VerificationMethod: []did.VerificationMethod{
-						kid2Method,
-						awesomeKidMethod,
-					},
-				},
-				maybeKID: "an awesome kid",
-			},
-			wantKid:    "an awesome kid",
-			wantPubKey: publicKey["an awesome kid"].publicKey,
-			wantErr:    assert.NoError,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			gotKid, gotPubKey, err := GetVerificationInformation(tt.args.did, tt.args.maybeKID)
-			if !tt.wantErr(t, err, fmt.Sprintf("GetVerificationInformation(%v, %v)", tt.args.did, tt.args.maybeKID)) {
-				return
-			}
-			assert.Equalf(t, tt.wantKid, gotKid, "GetVerificationInformation(%v, %v)", tt.args.did, tt.args.maybeKID)
-			assert.Equalf(t, tt.wantPubKey, gotPubKey, "GetVerificationInformation(%v, %v)", tt.args.did, tt.args.maybeKID)
-		})
-	}
-}
diff --git a/internal/keyaccess/dataintegrity_test.go b/internal/keyaccess/dataintegrity_test.go
index da42819..24fc538 100644
--- a/internal/keyaccess/dataintegrity_test.go
+++ b/internal/keyaccess/dataintegrity_test.go
@@ -12,16 +12,18 @@ import (
 func TestCreateDataIntegrityKeyAccess(t *testing.T) {
 	t.Run("Create a Key Access object - Happy Path", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		id := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewDataIntegrityKeyAccess(kid, privKey)
+		ka, err := NewDataIntegrityKeyAccess(id, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 	})
 
 	t.Run("Create a Key Access object - Bad Key", func(tt *testing.T) {
+		id := "test-id"
 		kid := "test-kid"
-		ka, err := NewDataIntegrityKeyAccess(kid, nil)
+		ka, err := NewDataIntegrityKeyAccess(id, kid, nil)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "key cannot be nil")
 		assert.Empty(tt, ka)
@@ -30,7 +32,7 @@ func TestCreateDataIntegrityKeyAccess(t *testing.T) {
 	t.Run("Create a Key Access object - No KID", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
 		assert.NoError(tt, err)
-		ka, err := NewDataIntegrityKeyAccess("", privKey)
+		ka, err := NewDataIntegrityKeyAccess("test-id", "", privKey)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "kid cannot be empty")
 		assert.Empty(tt, ka)
@@ -40,9 +42,10 @@ func TestCreateDataIntegrityKeyAccess(t *testing.T) {
 func TestDataIntegrityKeyAccessSignVerify(t *testing.T) {
 	t.Run("Sign and Verify Credential - Happy Path", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		id := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewDataIntegrityKeyAccess(kid, privKey)
+		ka, err := NewDataIntegrityKeyAccess(id, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -63,9 +66,10 @@ func TestDataIntegrityKeyAccessSignVerify(t *testing.T) {
 
 	t.Run("Sign and Verify Credential - Bad Data", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		id := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewDataIntegrityKeyAccess(kid, privKey)
+		ka, err := NewDataIntegrityKeyAccess(id, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -77,9 +81,10 @@ func TestDataIntegrityKeyAccessSignVerify(t *testing.T) {
 
 	t.Run("Sign and Verify Credential - Bad Signature", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		id := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewDataIntegrityKeyAccess(kid, privKey)
+		ka, err := NewDataIntegrityKeyAccess(id, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -91,9 +96,10 @@ func TestDataIntegrityKeyAccessSignVerify(t *testing.T) {
 
 	t.Run("Sign and Verify Presentation", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		id := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewDataIntegrityKeyAccess(kid, privKey)
+		ka, err := NewDataIntegrityKeyAccess(id, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
diff --git a/internal/keyaccess/jwt_test.go b/internal/keyaccess/jwt_test.go
index f3398f1..7c20dae 100644
--- a/internal/keyaccess/jwt_test.go
+++ b/internal/keyaccess/jwt_test.go
@@ -8,9 +8,11 @@ import (
 	"github.com/goccy/go-json"
 	"github.com/google/uuid"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
 )
 
 func TestJWKKeyAccessForEachKeyType(t *testing.T) {
+	testID := "test-id"
 	testKID := "test-kid"
 	testData := map[string]any{
 		"test": "data",
@@ -46,7 +48,7 @@ func TestJWKKeyAccessForEachKeyType(t *testing.T) {
 			assert.NotEmpty(t, privKey)
 
 			// create key access with the key
-			ka, err := NewJWKKeyAccess(testKID, privKey)
+			ka, err := NewJWKKeyAccess(testID, testKID, privKey)
 			assert.NoError(t, err)
 			assert.NotEmpty(t, ka)
 
@@ -65,16 +67,18 @@ func TestJWKKeyAccessForEachKeyType(t *testing.T) {
 func TestCreateJWKKeyAccess(t *testing.T) {
 	t.Run("Create a Key Access object - Happy Path", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 	})
 
 	t.Run("Create a Key Access object - Bad Key", func(tt *testing.T) {
+		testID := "test-id"
 		kid := "test-kid"
-		ka, err := NewJWKKeyAccess(kid, nil)
+		ka, err := NewJWKKeyAccess(testID, kid, nil)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "key cannot be nil")
 		assert.Empty(tt, ka)
@@ -83,7 +87,7 @@ func TestCreateJWKKeyAccess(t *testing.T) {
 	t.Run("Create a Key Access object - No KID", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess("", privKey)
+		ka, err := NewJWKKeyAccess("test-id", "", privKey)
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "kid cannot be empty")
 		assert.Empty(tt, ka)
@@ -93,9 +97,10 @@ func TestCreateJWKKeyAccess(t *testing.T) {
 func TestJWKKeyAccessSignVerify(t *testing.T) {
 	t.Run("Sign and Verify - Happy Path", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -110,7 +115,7 @@ func TestJWKKeyAccessSignVerify(t *testing.T) {
 		assert.NoError(tt, err)
 
 		// Create just a verifier and check that it can verify the token
-		verifier, err := NewJWKKeyAccessVerifier(kid, privKey.Public())
+		verifier, err := NewJWKKeyAccessVerifier(testID, kid, privKey.Public())
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, verifier)
 
@@ -125,9 +130,10 @@ func TestJWKKeyAccessSignVerify(t *testing.T) {
 
 	t.Run("Sign and Verify - Bad Data", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -138,9 +144,10 @@ func TestJWKKeyAccessSignVerify(t *testing.T) {
 
 	t.Run("Sign and Verify - Bad Signature", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -153,15 +160,17 @@ func TestJWKKeyAccessSignVerify(t *testing.T) {
 func TestJWKKeyAccessSignVerifyCredentials(t *testing.T) {
 	t.Run("Sign and Verify Credentials - Happy Path", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
 		// sign
 		testCred := getTestCredential()
-		signedCred, err := ka.SignVerifiableCredential(testCred)
+		testCredCopy := copyCred(t, testCred)
+		signedCred, err := ka.SignVerifiableCredential(testCredCopy)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, signedCred)
 
@@ -180,9 +189,10 @@ func TestJWKKeyAccessSignVerifyCredentials(t *testing.T) {
 
 	t.Run("Sign and Verify Credentials - Bad Data", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -194,9 +204,10 @@ func TestJWKKeyAccessSignVerifyCredentials(t *testing.T) {
 
 	t.Run("Sign and Verify Credentials - Bad Signature", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -212,16 +223,19 @@ func TestJWKKeyAccessSignVerifyPresentations(t *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		testID := "test-id"
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
 		// sign
 		testPres := getTestPresentation()
-		signedPres, err := ka.SignVerifiablePresentation(testPres)
+		signedPres, err := ka.SignVerifiablePresentation("test-audience", testPres)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, signedPres)
 
+		println(string(*signedPres))
+
 		// verify
 		verifiedPres, err := ka.VerifyVerifiablePresentation(*signedPres)
 		assert.NoError(tt, err)
@@ -237,23 +251,25 @@ func TestJWKKeyAccessSignVerifyPresentations(t *testing.T) {
 
 	t.Run("Sign and Verify Presentations - Bad Data", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
 		// sign
-		_, err = ka.SignVerifiablePresentation(credential.VerifiablePresentation{})
+		_, err = ka.SignVerifiablePresentation("test-audience", credential.VerifiablePresentation{})
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "cannot sign invalid presentation")
 	})
 
 	t.Run("Sign and Verify Presentations - Bad Signature", func(tt *testing.T) {
 		_, privKey, err := crypto.GenerateEd25519Key()
+		testID := "test-id"
 		kid := "test-kid"
 		assert.NoError(tt, err)
-		ka, err := NewJWKKeyAccess(kid, privKey)
+		ka, err := NewJWKKeyAccess(testID, kid, privKey)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
@@ -299,3 +315,12 @@ func getTestPresentation() credential.VerifiablePresentation {
 		VerifiableCredential: []any{getTestCredential()},
 	}
 }
+
+func copyCred(t *testing.T, cred credential.VerifiableCredential) credential.VerifiableCredential {
+	credBytes, err := json.Marshal(cred)
+	require.NoError(t, err)
+	var newCred credential.VerifiableCredential
+	err = json.Unmarshal(credBytes, &newCred)
+	require.NoError(t, err)
+	return newCred
+}
diff --git a/pkg/server/router/credential_test.go b/pkg/server/router/credential_test.go
index a8a7ba1..ce0afdf 100644
--- a/pkg/server/router/credential_test.go
+++ b/pkg/server/router/credential_test.go
@@ -15,6 +15,7 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/goccy/go-json"
+
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
@@ -39,7 +40,6 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Credential Service Test", func(tt *testing.T) {
-
 		bolt := setupTestDB(tt)
 		assert.NotNil(tt, bolt)
 
@@ -64,8 +64,9 @@ func TestCredentialRouter(t *testing.T) {
 		issuer := issuerDID.DID.ID
 		subject := "did:test:345"
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:  issuer,
-			Subject: subject,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
 			Data: map[string]any{
 				"firstName": "Satoshi",
 				"lastName":  "Nakamoto",
@@ -92,6 +93,11 @@ func TestCredentialRouter(t *testing.T) {
 		// compare for object equality
 		assert.Equal(tt, createdCred.CredentialJWT, gotCred.CredentialJWT)
 
+		// verify it
+		verified, err := credService.VerifyCredential(context.Background(), credential.VerifyCredentialRequest{CredentialJWT: gotCred.CredentialJWT})
+		assert.NoError(tt, err)
+		assert.True(tt, verified.Verified)
+
 		// get a cred that doesn't exist
 		_, err = credService.GetCredential(context.Background(), credential.GetCredentialRequest{ID: "bad"})
 		assert.Error(tt, err)
@@ -121,9 +127,10 @@ func TestCredentialRouter(t *testing.T) {
 
 		// create another cred with the same issuer, different subject, different schema that doesn't exist
 		_, err = credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    "did:abcd:efghi",
-			JSONSchema: "https://test-schema.com",
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abcd:efghi",
+			SchemaID:  "https://test-schema.com",
 			Data: map[string]any{
 				"email": "satoshi@nakamoto.com",
 			},
@@ -143,15 +150,16 @@ func TestCredentialRouter(t *testing.T) {
 			"required":             []any{"email"},
 			"additionalProperties": false,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// create another cred with the same issuer, different subject, different schema that does exist
 		createdCredWithSchema, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    "did:abcd:efghi",
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abcd:efghi",
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "satoshi@nakamoto.com",
 			},
@@ -227,7 +235,7 @@ func TestCredentialRouter(t *testing.T) {
 			"additionalProperties": false,
 		}
 
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
@@ -235,9 +243,10 @@ func TestCredentialRouter(t *testing.T) {
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -257,9 +266,10 @@ func TestCredentialRouter(t *testing.T) {
 		assert.NotEmpty(tt, credStatusMap["statusListIndex"])
 
 		createdCredTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "Satoshi2@Nakamoto2.btc",
 			},
@@ -281,14 +291,15 @@ func TestCredentialRouter(t *testing.T) {
 		// Cred with same <issuer, schema> pair share the same statusListCredential
 		assert.Equal(tt, credStatusMapTwo["statusListCredential"], credStatusMap["statusListCredential"])
 
-		createdSchemaTwo, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		createdSchemaTwo, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchemaTwo)
 
 		createdCredThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: createdSchemaTwo.ID,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchemaTwo.ID,
 			Data: map[string]any{
 				"email": "Satoshi2@Nakamoto2.btc",
 			},
@@ -337,8 +348,9 @@ func TestCredentialRouter(t *testing.T) {
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:  issuer,
-			Subject: subject,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -358,8 +370,9 @@ func TestCredentialRouter(t *testing.T) {
 		assert.NotEmpty(tt, credStatusMap["statusListIndex"])
 
 		createdCredTwo, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:  issuer,
-			Subject: subject,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
 			Data: map[string]any{
 				"email": "Satoshi2@Nakamoto2.btc",
 			},
@@ -392,14 +405,15 @@ func TestCredentialRouter(t *testing.T) {
 			"additionalProperties": false,
 		}
 
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		createdCredThree, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "Satoshi2@Nakamoto2.btc",
 			},
@@ -454,7 +468,7 @@ func TestCredentialRouter(t *testing.T) {
 			"additionalProperties": false,
 		}
 
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
@@ -462,9 +476,10 @@ func TestCredentialRouter(t *testing.T) {
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuer,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -533,7 +548,7 @@ func TestCredentialRouter(t *testing.T) {
 
 	})
 
-	t.Run("Create Multiple Suspendable Credential Different Issuer Schema StatusPurpose Triples", func(tt *testing.T) {
+	t.Run("Create Multiple Suspendable Credential Different Issuer SchemaID StatusPurpose Triples", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		assert.NotNil(tt, bolt)
 
@@ -565,16 +580,17 @@ func TestCredentialRouter(t *testing.T) {
 			"additionalProperties": false,
 		}
 
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    subject,
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -585,9 +601,10 @@ func TestCredentialRouter(t *testing.T) {
 		assert.NotEmpty(tt, createdCred)
 
 		createdCredSuspendable, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    subject,
-			JSONSchema: createdSchema.ID,
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subject,
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -627,13 +644,14 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Create Suspendable Credential", func(tt *testing.T) {
-		issuer, schema, credService := createCredServicePrereqs(tt)
+		issuer, issuerKID, schemaID, credService := createCredServicePrereqs(tt)
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: schema,
+			Issuer:    issuer,
+			IssuerKID: issuerKID,
+			Subject:   subject,
+			SchemaID:  schemaID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -682,13 +700,14 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Update Suspendable Credential To Suspended", func(tt *testing.T) {
-		issuer, schema, credService := createCredServicePrereqs(tt)
+		issuer, issuerKID, schemaID, credService := createCredServicePrereqs(tt)
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: schema,
+			Issuer:    issuer,
+			IssuerKID: issuerKID,
+			Subject:   subject,
+			SchemaID:  schemaID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -759,13 +778,14 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Update Suspendable Credential To Suspended then Unsuspended", func(tt *testing.T) {
-		issuer, schema, credService := createCredServicePrereqs(tt)
+		issuer, issuerKID, schemaID, credService := createCredServicePrereqs(tt)
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: schema,
+			Issuer:    issuer,
+			IssuerKID: issuerKID,
+			Subject:   subject,
+			SchemaID:  schemaID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -841,13 +861,14 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Create Suspendable and Revocable Credential Should Be Error", func(tt *testing.T) {
-		issuer, schema, credService := createCredServicePrereqs(tt)
+		issuer, issuerKID, schemaID, credService := createCredServicePrereqs(tt)
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: schema,
+			Issuer:    issuer,
+			IssuerKID: issuerKID,
+			Subject:   subject,
+			SchemaID:  schemaID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -862,13 +883,14 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Update Suspendable and Revocable Credential Should Be Error", func(tt *testing.T) {
-		issuer, schema, credService := createCredServicePrereqs(tt)
+		issuer, issuerKID, schemaID, credService := createCredServicePrereqs(tt)
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: schema,
+			Issuer:    issuer,
+			IssuerKID: issuerKID,
+			Subject:   subject,
+			SchemaID:  schemaID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -886,13 +908,14 @@ func TestCredentialRouter(t *testing.T) {
 	})
 
 	t.Run("Update Suspended On Revoked Credential Should Be Error", func(tt *testing.T) {
-		issuer, schema, credService := createCredServicePrereqs(tt)
+		issuer, issuerKID, schemaID, credService := createCredServicePrereqs(tt)
 		subject := "did:test:345"
 
 		createdCred, err := credService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuer,
-			Subject:    subject,
-			JSONSchema: schema,
+			Issuer:    issuer,
+			IssuerKID: issuerKID,
+			Subject:   subject,
+			SchemaID:  schemaID,
 			Data: map[string]any{
 				"email": "Satoshi@Nakamoto.btc",
 			},
@@ -910,7 +933,7 @@ func TestCredentialRouter(t *testing.T) {
 	})
 }
 
-func createCredServicePrereqs(tt *testing.T) (string, string, credential.Service) {
+func createCredServicePrereqs(tt *testing.T) (issuer, issuerKID, schemaID string, credSvc credential.Service) {
 	bolt := setupTestDB(tt)
 	require.NotNil(tt, bolt)
 
@@ -943,9 +966,9 @@ func createCredServicePrereqs(tt *testing.T) (string, string, credential.Service
 		"additionalProperties": false,
 	}
 
-	createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: emailSchema})
+	createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "simple schema", Schema: emailSchema})
 	require.NoError(tt, err)
 	require.NotEmpty(tt, createdSchema)
 
-	return issuerDID.DID.ID, createdSchema.ID, *credService
+	return issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID, *credService
 }
diff --git a/pkg/server/router/manifest_test.go b/pkg/server/router/manifest_test.go
index a2891a0..08d9a3b 100644
--- a/pkg/server/router/manifest_test.go
+++ b/pkg/server/router/manifest_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/google/uuid"
 	"github.com/mr-tron/base58"
 	"github.com/stretchr/testify/assert"
+
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest/model"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
 
@@ -76,22 +77,24 @@ func TestManifestRouter(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// issue a credential against the schema to the subject, from the issuer
 		createdCred, err := credentialService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    applicantDID.DID.ID,
-			JSONSchema: createdSchema.ID,
-			Data:       map[string]any{"licenseType": "WA-DL-CLASS-A"},
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: kid,
+			Subject:   applicantDID.DID.ID,
+			SchemaID:  createdSchema.ID,
+			Data:      map[string]any{"licenseType": "WA-DL-CLASS-A"},
 		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdCred)
 
 		// good manifest request, which asks for a single verifiable credential in the VC-JWT format
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, kid, createdSchema.ID)
 		createdManifest, err := manifestService.CreateManifest(context.Background(), createManifestRequest)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdManifest)
@@ -116,13 +119,13 @@ func TestManifestRouter(t *testing.T) {
 		assert.NoError(tt, err)
 		applicantPrivKey, err := crypto.BytesToPrivKey(applicantPrivKeyBytes, applicantDID.KeyType)
 		assert.NoError(tt, err)
-		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantPrivKey)
+		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantDID.DID.VerificationMethod[0].ID, applicantPrivKey)
 		assert.NoError(tt, err)
 		signed, err := signer.SignJSON(applicationRequest)
 		assert.NoError(tt, err)
 
 		submitApplicationRequest := SubmitApplicationRequest{ApplicationJWT: *signed}
-		sar, err := submitApplicationRequest.ToServiceRequest()
+		sar, err := submitApplicationRequest.toServiceRequest()
 		assert.NoError(tt, err)
 		createdApplicationResponseOp, err := manifestService.ProcessApplicationSubmission(context.Background(), *sar)
 		assert.NoError(tt, err)
@@ -143,9 +146,10 @@ func TestManifestRouter(t *testing.T) {
 }
 
 // getValidManifestRequest returns a valid manifest request, expecting a single JWT-VC EdDSA credential
-func getValidManifestRequest(issuerDID, schemaID string) model.CreateManifestRequest {
+func getValidManifestRequest(issuerDID, issuerKID, schemaID string) model.CreateManifestRequest {
 	createManifestRequest := model.CreateManifestRequest{
 		IssuerDID: issuerDID,
+		IssuerKID: issuerKID,
 		ClaimFormat: &exchange.ClaimFormat{
 			JWTVC: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}},
 		},
diff --git a/pkg/server/router/presentation_test.go b/pkg/server/router/presentation_test.go
index 5266c82..e8f18fa 100644
--- a/pkg/server/router/presentation_test.go
+++ b/pkg/server/router/presentation_test.go
@@ -11,6 +11,7 @@ import (
 	"github.com/mr-tron/base58"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
@@ -55,7 +56,7 @@ func TestPresentationDefinitionService(t *testing.T) {
 	require.NoError(t, err)
 	privKey, err := crypto.BytesToPrivKey(privKeyBytes, authorDID.KeyType)
 	require.NoError(t, err)
-	ka, err := keyaccess.NewJWKKeyAccessVerifier(authorDID.DID.ID, privKey.(Public).Public())
+	ka, err := keyaccess.NewJWKKeyAccessVerifier(authorDID.DID.ID, authorDID.DID.ID, privKey.(Public).Public())
 	require.NoError(t, err)
 
 	service, err := presentation.NewPresentationService(config.PresentationServiceConfig{}, s, didService.GetResolver(), schemaService, keyStoreService)
@@ -63,7 +64,11 @@ func TestPresentationDefinitionService(t *testing.T) {
 
 	t.Run("Create returns the created definition", func(t *testing.T) {
 		pd := createPresentationDefinition(t)
-		created, err := service.CreatePresentationDefinition(context.Background(), model.CreatePresentationDefinitionRequest{PresentationDefinition: *pd, Author: authorDID.DID.ID})
+		created, err := service.CreatePresentationDefinition(context.Background(), model.CreatePresentationDefinitionRequest{
+			PresentationDefinition: *pd,
+			Author:                 authorDID.DID.ID,
+			AuthorKID:              authorDID.DID.VerificationMethod[0].ID,
+		})
 
 		assert.NoError(t, err)
 		assert.Equal(t, pd, &created.PresentationDefinition)
@@ -72,7 +77,11 @@ func TestPresentationDefinitionService(t *testing.T) {
 
 	t.Run("Get returns the created definition", func(t *testing.T) {
 		pd := createPresentationDefinition(t)
-		_, err := service.CreatePresentationDefinition(context.Background(), model.CreatePresentationDefinitionRequest{PresentationDefinition: *pd, Author: authorDID.DID.ID})
+		_, err := service.CreatePresentationDefinition(context.Background(), model.CreatePresentationDefinitionRequest{
+			PresentationDefinition: *pd,
+			Author:                 authorDID.DID.ID,
+			AuthorKID:              authorDID.DID.VerificationMethod[0].ID,
+		})
 		assert.NoError(t, err)
 
 		getPd, err := service.GetPresentationDefinition(context.Background(), model.GetPresentationDefinitionRequest{ID: pd.ID})
@@ -85,7 +94,11 @@ func TestPresentationDefinitionService(t *testing.T) {
 
 	t.Run("Get does not return after deletion", func(t *testing.T) {
 		pd := createPresentationDefinition(t)
-		_, err := service.CreatePresentationDefinition(context.Background(), model.CreatePresentationDefinitionRequest{PresentationDefinition: *pd, Author: authorDID.DID.ID})
+		_, err := service.CreatePresentationDefinition(context.Background(), model.CreatePresentationDefinitionRequest{
+			PresentationDefinition: *pd,
+			Author:                 authorDID.DID.ID,
+			AuthorKID:              authorDID.DID.VerificationMethod[0].ID,
+		})
 		assert.NoError(t, err)
 
 		assert.NoError(t, service.DeletePresentationDefinition(context.Background(), model.DeletePresentationDefinitionRequest{ID: pd.ID}))
diff --git a/pkg/server/router/schema_test.go b/pkg/server/router/schema_test.go
index 2cbc40e..be653a3 100644
--- a/pkg/server/router/schema_test.go
+++ b/pkg/server/router/schema_test.go
@@ -30,7 +30,7 @@ func TestSchemaRouter(t *testing.T) {
 		assert.Contains(tt, err.Error(), "could not create schema router with service type: test")
 	})
 
-	t.Run("Schema Service Test", func(tt *testing.T) {
+	t.Run("SchemaID Service Test", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		assert.NotNil(tt, bolt)
 
@@ -116,7 +116,7 @@ func TestSchemaRouter(t *testing.T) {
 
 func TestSchemaSigning(t *testing.T) {
 
-	t.Run("Unsigned Schema Test", func(tt *testing.T) {
+	t.Run("Unsigned SchemaID Test", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		assert.NotNil(tt, bolt)
 
@@ -150,11 +150,11 @@ func TestSchemaSigning(t *testing.T) {
 		assert.Equal(tt, "me", createdSchema.Schema.Author)
 		assert.Equal(tt, "simple schema", createdSchema.Schema.Name)
 
-		// missing DID
+		// missing kid
 		createdSchema, err = schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: "me", Name: "simple schema", Schema: simpleSchema, Sign: true})
 		assert.Error(tt, err)
 		assert.Empty(tt, createdSchema)
-		assert.Contains(tt, err.Error(), "could not get key for signing schema for author<me>")
+		assert.Contains(tt, err.Error(), "could not get key for signing schema for authorKID<>: getting key with id:")
 
 		// create an author DID
 		authorDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{
@@ -164,7 +164,8 @@ func TestSchemaSigning(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, authorDID)
 
-		createdSchema, err = schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: authorDID.DID.ID, Name: "simple schema", Schema: simpleSchema, Sign: true})
+		kid := authorDID.DID.VerificationMethod[0].ID
+		createdSchema, err = schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: authorDID.DID.ID, AuthorKID: kid, Name: "simple schema", Schema: simpleSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 		assert.NotEmpty(tt, createdSchema.SchemaJWT)
diff --git a/pkg/server/server_credential_test.go b/pkg/server/server_credential_test.go
index 9914030..4ead625 100644
--- a/pkg/server/server_credential_test.go
+++ b/pkg/server/server_credential_test.go
@@ -42,9 +42,10 @@ func TestCredentialAPI(t *testing.T) {
 
 		// missing required field: data
 		badCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
-			Expiry:  time.Now().Add(24 * time.Hour).Format(time.RFC3339),
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
+			Expiry:    time.Now().Add(24 * time.Hour).Format(time.RFC3339),
 		}
 		badRequestValue := newRequestValue(tt, badCredRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", badRequestValue)
@@ -59,8 +60,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// missing known issuer request
 		missingIssuerRequest := router.CreateCredentialRequest{
-			Issuer:  "did:abc:123",
-			Subject: "did:abc:456",
+			Issuer:    "did:abc:123",
+			IssuerKID: "did:abc:123#key-1",
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -71,15 +73,16 @@ func TestCredentialAPI(t *testing.T) {
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/credentials", missingIssuerRequestValue)
 		err = credRouter.CreateCredential(newRequestContext(), w, req)
 		assert.Error(tt, err)
-		assert.Contains(tt, err.Error(), "could not get key for signing credential with key<did:abc:123>")
+		assert.Contains(tt, err.Error(), "getting key for signing credential<did:abc:123#key-1>")
 
 		// reset the http recorder
 		w.Flush()
 
 		// good request
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -100,7 +103,7 @@ func TestCredentialAPI(t *testing.T) {
 		assert.Equal(tt, resp.Credential.Issuer, issuerDID.DID.ID)
 	})
 
-	t.Run("Test Create Credential with Schema", func(tt *testing.T) {
+	t.Run("Test Create Credential with SchemaID", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
 
@@ -137,9 +140,10 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NotEmpty(tt, createdSchema)
 
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
-			Schema:  createdSchema.ID,
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -176,9 +180,10 @@ func TestCredentialAPI(t *testing.T) {
 
 		// create cred with unknown schema
 		missingSchemaCred := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
-			Schema:  "bad",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
+			SchemaID:  "bad",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -229,8 +234,9 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NotEmpty(tt, issuerDID)
 
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -262,7 +268,7 @@ func TestCredentialAPI(t *testing.T) {
 		assert.Equal(tt, resp.Credential.ID, getCredResp.ID)
 	})
 
-	t.Run("Test Get Credential By Schema", func(tt *testing.T) {
+	t.Run("Test Get Credential By SchemaID", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
 
@@ -299,9 +305,10 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NotEmpty(tt, createdSchema)
 
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
-			Schema:  createdSchema.ID,
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
+			SchemaID:  createdSchema.ID,
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -354,8 +361,9 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NotEmpty(tt, issuerDID)
 
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -408,8 +416,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		subjectID := "did:abc:456"
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: subjectID,
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   subjectID,
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -460,8 +469,9 @@ func TestCredentialAPI(t *testing.T) {
 		assert.NotEmpty(tt, issuerDID)
 
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -526,8 +536,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good request
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -602,8 +613,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good request One
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -626,8 +638,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good revocable request One
 		createRevocableCredRequestOne := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -656,8 +669,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good revocable request Two
 		createRevocableCredRequestTwo := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -686,8 +700,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good revocable request Three
 		createRevocableCredRequestThree := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -716,8 +731,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good revocable request Four (different issuer / schema)
 		createRevocableCredRequestFour := router.CreateCredentialRequest{
-			Issuer:  issuerDIDTwo.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDIDTwo.DID.ID,
+			IssuerKID: issuerDIDTwo.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -765,8 +781,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good request number one
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
@@ -837,8 +854,9 @@ func TestCredentialAPI(t *testing.T) {
 
 		// good request number one
 		createCredRequest := router.CreateCredentialRequest{
-			Issuer:  issuerDID.DID.ID,
-			Subject: "did:abc:456",
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: issuerDID.DID.VerificationMethod[0].ID,
+			Subject:   "did:abc:456",
 			Data: map[string]any{
 				"firstName": "Jack",
 				"lastName":  "Dorsey",
diff --git a/pkg/server/server_issuance_test.go b/pkg/server/server_issuance_test.go
index 19f5a5e..14e51af 100644
--- a/pkg/server/server_issuance_test.go
+++ b/pkg/server/server_issuance_test.go
@@ -14,6 +14,8 @@ import (
 	"github.com/google/go-cmp/cmp"
 	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
@@ -38,6 +40,7 @@ func TestIssuanceRouter(t *testing.T) {
 					IssuanceTemplate: issuing.IssuanceTemplate{
 						CredentialManifest: manifest.Manifest.ID,
 						Issuer:             issuerResp.DID.ID,
+						IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 						Credentials: []issuing.CredentialTemplate{
 							{
 								ID:     "output_descriptor_1",
@@ -60,6 +63,7 @@ func TestIssuanceRouter(t *testing.T) {
 					IssuanceTemplate: issuing.IssuanceTemplate{
 						CredentialManifest: manifest.Manifest.ID,
 						Issuer:             issuerResp.DID.ID,
+						IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 						Credentials: []issuing.CredentialTemplate{
 							{
 								ID:     "output_descriptor_1",
@@ -106,6 +110,7 @@ func TestIssuanceRouter(t *testing.T) {
 					IssuanceTemplate: issuing.IssuanceTemplate{
 						CredentialManifest: manifest.Manifest.ID,
 						Issuer:             issuerResp.DID.ID,
+						IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 						Credentials: []issuing.CredentialTemplate{
 							{
 								ID:     "",
@@ -129,6 +134,7 @@ func TestIssuanceRouter(t *testing.T) {
 					IssuanceTemplate: issuing.IssuanceTemplate{
 						CredentialManifest: manifest.Manifest.ID,
 						Issuer:             issuerResp.DID.ID,
+						IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 						Credentials: []issuing.CredentialTemplate{
 							{
 								ID:     "output_descriptor_1",
@@ -153,6 +159,7 @@ func TestIssuanceRouter(t *testing.T) {
 					IssuanceTemplate: issuing.IssuanceTemplate{
 						CredentialManifest: manifest.Manifest.ID,
 						Issuer:             issuerResp.DID.ID,
+						IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 						Credentials: []issuing.CredentialTemplate{
 							{
 								ID:     "output_descriptor_1",
@@ -176,6 +183,7 @@ func TestIssuanceRouter(t *testing.T) {
 					IssuanceTemplate: issuing.IssuanceTemplate{
 						CredentialManifest: "fake manifest id",
 						Issuer:             issuerResp.DID.ID,
+						IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 						Credentials: []issuing.CredentialTemplate{
 							{
 								ID:     "output_descriptor_1",
@@ -237,6 +245,7 @@ func TestIssuanceRouter(t *testing.T) {
 		inputTemplate := issuing.IssuanceTemplate{
 			CredentialManifest: manifest.Manifest.ID,
 			Issuer:             issuerResp.DID.ID,
+			IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 			Credentials: []issuing.CredentialTemplate{
 				{
 					ID:     "output_descriptor_1",
@@ -355,6 +364,7 @@ func createSimpleTemplate(t *testing.T, manifest *model.CreateManifestResponse,
 			IssuanceTemplate: issuing.IssuanceTemplate{
 				CredentialManifest: manifest.Manifest.ID,
 				Issuer:             issuerResp.DID.ID,
+				IssuerKID:          issuerResp.DID.VerificationMethod[0].ID,
 				Credentials: []issuing.CredentialTemplate{
 					{
 						ID:     "output_descriptor_1",
@@ -375,7 +385,7 @@ func createSimpleTemplate(t *testing.T, manifest *model.CreateManifestResponse,
 		w := httptest.NewRecorder()
 
 		err := r.CreateIssuanceTemplate(newRequestContext(), w, req)
-		assert.NoError(t, err)
+		require.NoError(t, err)
 	}
 }
 
@@ -392,7 +402,7 @@ func setupAllThings(t *testing.T) (*did.CreateDIDResponse, *schema.CreateSchemaR
 		Method:  "key",
 		KeyType: crypto.Ed25519,
 	})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	licenseSchema := map[string]any{
 		"type": "object",
@@ -403,12 +413,15 @@ func setupAllThings(t *testing.T) (*did.CreateDIDResponse, *schema.CreateSchemaR
 		},
 		"additionalProperties": true,
 	}
-	createdSchema, err := schemaSvc.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerResp.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
-	assert.NoError(t, err)
+	keyID := issuerResp.DID.VerificationMethod[0].ID
+	createdSchema, err := schemaSvc.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerResp.DID.ID, AuthorKID: keyID, Name: "license schema", Schema: licenseSchema, Sign: true})
+	require.NoError(t, err)
+
 	sillyName := "some silly name"
 	manifest, err := manifestSvc.CreateManifest(context.Background(), model.CreateManifestRequest{
 		Name:      &sillyName,
 		IssuerDID: issuerResp.DID.ID,
+		IssuerKID: issuerResp.DID.VerificationMethod[0].ID,
 		ClaimFormat: &exchange.ClaimFormat{
 			JWT: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}},
 		},
@@ -419,19 +432,18 @@ func setupAllThings(t *testing.T) (*did.CreateDIDResponse, *schema.CreateSchemaR
 			},
 		},
 	})
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
 	r := testIssuanceRouter(t, s)
 	return issuerResp, createdSchema, manifest, r
 }
 
 func testIssuanceRouter(t *testing.T, s storage.ServiceStorage) *router.IssuanceRouter {
-	svc, err := issuing.NewIssuingService(config.IssuingServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{
-		Name: "test-issuing",
-	}}, s)
-	assert.NoError(t, err)
+	serviceConfig := config.IssuingServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "test-issuing"}}
+	svc, err := issuing.NewIssuingService(serviceConfig, s)
+	require.NoError(t, err)
 
 	r, err := router.NewIssuanceRouter(svc)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	return r
 }
diff --git a/pkg/server/server_manifest_test.go b/pkg/server/server_manifest_test.go
index 60fd86d..01eef0b 100644
--- a/pkg/server/server_manifest_test.go
+++ b/pkg/server/server_manifest_test.go
@@ -82,12 +82,13 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -101,6 +102,8 @@ func TestManifestAPI(t *testing.T) {
 		assert.NotEmpty(tt, resp.Manifest)
 		assert.Equal(tt, resp.Manifest.Issuer.ID, issuerDID.DID.ID)
 
+		println(string(resp.ManifestJWT))
+
 		// verify the manifest
 		verificationResponse, err := manifestService.VerifyManifest(context.Background(), manifestsvc.VerifyManifestRequest{ManifestJWT: resp.ManifestJWT})
 		assert.NoError(tt, err)
@@ -156,12 +159,13 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -214,12 +218,13 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -279,12 +284,13 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -335,23 +341,20 @@ func TestManifestAPI(t *testing.T) {
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
 		manifestRouter, manifestSvc := testManifest(tt, bolt, keyStoreService, didService, credentialService)
+
 		// create an issuer
-		issuerDID, err := didService.CreateDIDByMethod(
-			context.Background(),
-			did.CreateDIDRequest{
-				Method:  didsdk.KeyMethod,
-				KeyType: crypto.Ed25519,
-			})
+		issuerDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{
+			Method:  didsdk.KeyMethod,
+			KeyType: crypto.Ed25519,
+		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, issuerDID)
 
 		// create an applicant
-		applicantDID, err := didService.CreateDIDByMethod(
-			context.Background(),
-			did.CreateDIDRequest{
-				Method:  didsdk.KeyMethod,
-				KeyType: crypto.Ed25519,
-			})
+		applicantDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{
+			Method:  didsdk.KeyMethod,
+			KeyType: crypto.Ed25519,
+		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, issuerDID)
 
@@ -365,9 +368,10 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
+		kid := issuerDID.DID.VerificationMethod[0].ID
 		createdSchema, err := schemaService.CreateSchema(
 			context.Background(),
-			schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+			schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
@@ -375,9 +379,10 @@ func TestManifestAPI(t *testing.T) {
 		createdCred, err := credentialService.CreateCredential(
 			context.Background(),
 			credential.CreateCredentialRequest{
-				Issuer:     issuerDID.DID.ID,
-				Subject:    applicantDID.DID.ID,
-				JSONSchema: createdSchema.ID,
+				Issuer:    issuerDID.DID.ID,
+				IssuerKID: kid,
+				Subject:   applicantDID.DID.ID,
+				SchemaID:  createdSchema.ID,
 				Data: map[string]any{
 					"licenseType": "WA-DL-CLASS-A",
 					"firstName":   "Tester",
@@ -388,7 +393,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NotEmpty(tt, createdCred)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -413,19 +418,18 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		applicantPrivKey, err := crypto.BytesToPrivKey(applicantPrivKeyBytes, applicantDID.KeyType)
 		assert.NoError(tt, err)
-		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantPrivKey)
+		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantDID.DID.VerificationMethod[0].ID, applicantPrivKey)
 		assert.NoError(tt, err)
 		signed, err := signer.SignJSON(applicationRequest)
 		assert.NoError(tt, err)
 
-		now := time.Date(2022, 10, 31, 0, 0, 0, 0, time.UTC)
+		expiryDateTime := time.Date(2022, 10, 31, 0, 0, 0, 0, time.UTC)
 		mockClock := clock.NewMock()
 		manifestSvc.Clock = mockClock
-		mockClock.Set(now)
-		duration := 5 * time.Second
-		issuanceTemplate, err := issuanceService.CreateIssuanceTemplate(
-			context.Background(),
-			getValidIssuanceTemplateRequest(m, issuerDID, createdSchema, now, duration))
+		mockClock.Set(expiryDateTime)
+		expiryDuration := 5 * time.Second
+		issuanceTemplate, err := issuanceService.CreateIssuanceTemplate(context.Background(),
+			getValidIssuanceTemplateRequest(m, issuerDID, createdSchema, expiryDateTime, expiryDuration))
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, issuanceTemplate)
 
@@ -444,23 +448,24 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		err = json.Unmarshal(respData, &appResp)
 		assert.NoError(tt, err)
-
 		assert.Len(tt, appResp.Credentials, 2, "each output_descriptor in the definition should result in a credential")
+
 		vc, err := util.CredentialsFromInterface(appResp.Credentials.([]any)[0])
 		assert.NoError(tt, err)
-		assert.Equal(tt, credsdk.CredentialSubject{
+		expectedSubject := credsdk.CredentialSubject{
 			"id":        applicantDID.DID.ID,
 			"state":     "CA",
 			"firstName": "Tester",
 			"lastName":  "McTest",
-		}, vc.CredentialSubject)
+		}
+		assert.Equal(tt, expectedSubject, vc.CredentialSubject)
 		assert.Equal(tt, time.Date(2022, 10, 31, 0, 0, 0, 0, time.UTC).Format(time.RFC3339), vc.ExpirationDate)
 		assert.Equal(tt, createdSchema.ID, vc.CredentialSchema.ID)
 		assert.Empty(tt, vc.CredentialStatus)
 
 		vc2, err := util.CredentialsFromInterface(appResp.Credentials.([]any)[1])
 		assert.NoError(tt, err)
-		assert.Equal(tt, credsdk.CredentialSubject{
+		expectedSubject = credsdk.CredentialSubject{
 			"id": applicantDID.DID.ID,
 			"someCrazyObject": map[string]any{
 				"foo": 123.,
@@ -469,15 +474,16 @@ func TestManifestAPI(t *testing.T) {
 					"yay", 123., nil,
 				},
 			},
-		}, vc2.CredentialSubject)
-		assert.Equal(
-			tt,
+		}
+		assert.Equal(tt, expectedSubject, vc2.CredentialSubject)
+		assert.Equal(tt,
 			time.Date(2022, 10, 31, 0, 0, 5, 0, time.UTC).Format(time.RFC3339),
 			vc2.ExpirationDate,
 		)
 		assert.Equal(tt, createdSchema.ID, vc2.CredentialSchema.ID)
 		assert.NotEmpty(tt, vc2.CredentialStatus)
 	})
+
 	t.Run("Test Submit Application", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
@@ -489,10 +495,7 @@ func TestManifestAPI(t *testing.T) {
 		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		// missing required field: Application
-		badManifestRequest := router.SubmitApplicationRequest{
-			ApplicationJWT: "bad",
-		}
-
+		badManifestRequest := router.SubmitApplicationRequest{ApplicationJWT: "bad"}
 		badRequestValue := newRequestValue(tt, badManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests/applications", badRequestValue)
 		w := httptest.NewRecorder()
@@ -530,22 +533,25 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(),
+			schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// issue a credential against the schema to the subject, from the issuer
 		createdCred, err := credentialService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    applicantDID.DID.ID,
-			JSONSchema: createdSchema.ID,
-			Data:       map[string]any{"licenseType": "WA-DL-CLASS-A"},
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: kid,
+			Subject:   applicantDID.DID.ID,
+			SchemaID:  createdSchema.ID,
+			Data:      map[string]any{"licenseType": "WA-DL-CLASS-A"},
 		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdCred)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		w.Flush()
 
@@ -571,7 +577,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		applicantPrivKey, err := crypto.BytesToPrivKey(applicantPrivKeyBytes, applicantDID.KeyType)
 		assert.NoError(tt, err)
-		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantPrivKey)
+		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantDID.DID.VerificationMethod[0].ID, applicantPrivKey)
 		assert.NoError(tt, err)
 		signed, err := signer.SignJSON(applicationRequest)
 		assert.NoError(tt, err)
@@ -684,16 +690,19 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(),
+			schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// issue a credential against the schema to the subject, from the issuer
 		createdCred, err := credentialService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    applicantDID.DID.ID,
-			JSONSchema: createdSchema.ID,
-			Data:       map[string]any{"licenseType": "WA-DL-CLASS-A"},
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: kid,
+			Subject:   applicantDID.DID.ID,
+			SchemaID:  createdSchema.ID,
+			Data:      map[string]any{"licenseType": "WA-DL-CLASS-A"},
 		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdCred)
@@ -701,7 +710,7 @@ func TestManifestAPI(t *testing.T) {
 		w.Flush()
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -729,7 +738,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		applicantPrivKey, err := crypto.BytesToPrivKey(applicantPrivKeyBytes, applicantDID.KeyType)
 		assert.NoError(tt, err)
-		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantPrivKey)
+		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantDID.DID.VerificationMethod[0].ID, applicantPrivKey)
 		assert.NoError(tt, err)
 		signed, err := signer.SignJSON(applicationRequest)
 		assert.NoError(tt, err)
@@ -834,22 +843,25 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(),
+			schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// issue a credential against the schema to the subject, from the issuer
 		createdCred, err := credentialService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    applicantDID.DID.ID,
-			JSONSchema: createdSchema.ID,
-			Data:       map[string]any{"licenseType": "WA-DL-CLASS-A"},
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: kid,
+			Subject:   applicantDID.DID.ID,
+			SchemaID:  createdSchema.ID,
+			Data:      map[string]any{"licenseType": "WA-DL-CLASS-A"},
 		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdCred)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -873,7 +885,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		applicantPrivKey, err := crypto.BytesToPrivKey(applicantPrivKeyBytes, applicantDID.KeyType)
 		assert.NoError(tt, err)
-		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantPrivKey)
+		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantDID.DID.VerificationMethod[0].ID, applicantPrivKey)
 		assert.NoError(tt, err)
 		signed, err := signer.SignJSON(applicationRequest)
 		assert.NoError(tt, err)
@@ -986,22 +998,25 @@ func TestManifestAPI(t *testing.T) {
 			},
 			"additionalProperties": true,
 		}
-		createdSchema, err := schemaService.CreateSchema(context.Background(), schema.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "license schema", Schema: licenseSchema, Sign: true})
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		createdSchema, err := schemaService.CreateSchema(context.Background(),
+			schema.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "license schema", Schema: licenseSchema, Sign: true})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdSchema)
 
 		// issue a credential against the schema to the subject, from the issuer
 		createdCred, err := credentialService.CreateCredential(context.Background(), credential.CreateCredentialRequest{
-			Issuer:     issuerDID.DID.ID,
-			Subject:    applicantDID.DID.ID,
-			JSONSchema: createdSchema.ID,
-			Data:       map[string]any{"licenseType": "WA-DL-CLASS-A"},
+			Issuer:    issuerDID.DID.ID,
+			IssuerKID: kid,
+			Subject:   applicantDID.DID.ID,
+			SchemaID:  createdSchema.ID,
+			Data:      map[string]any{"licenseType": "WA-DL-CLASS-A"},
 		})
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdCred)
 
 		// good request
-		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, createdSchema.ID)
+		createManifestRequest := getValidManifestRequest(issuerDID.DID.ID, issuerDID.DID.VerificationMethod[0].ID, createdSchema.ID)
 
 		requestValue := newRequestValue(tt, createManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", requestValue)
@@ -1025,7 +1040,7 @@ func TestManifestAPI(t *testing.T) {
 		assert.NoError(tt, err)
 		applicantPrivKey, err := crypto.BytesToPrivKey(applicantPrivKeyBytes, applicantDID.KeyType)
 		assert.NoError(tt, err)
-		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantPrivKey)
+		signer, err := keyaccess.NewJWKKeyAccess(applicantDID.DID.ID, applicantDID.DID.VerificationMethod[0].ID, applicantPrivKey)
 		assert.NoError(tt, err)
 		signed, err := signer.SignJSON(applicationRequest)
 		assert.NoError(tt, err)
@@ -1077,12 +1092,14 @@ func TestManifestAPI(t *testing.T) {
 	})
 }
 
-func getValidIssuanceTemplateRequest(m manifest.CredentialManifest, issuerDID *did.CreateDIDResponse, createdSchema *schema.CreateSchemaResponse, now time.Time, duration time.Duration) *issuing.CreateIssuanceTemplateRequest {
+func getValidIssuanceTemplateRequest(m manifest.CredentialManifest, issuerDID *did.CreateDIDResponse,
+	createdSchema *schema.CreateSchemaResponse, expiry1 time.Time, expiry2 time.Duration) *issuing.CreateIssuanceTemplateRequest {
 	return &issuing.CreateIssuanceTemplateRequest{
 		IssuanceTemplate: issuing.IssuanceTemplate{
 			ID:                 uuid.NewString(),
 			CredentialManifest: m.ID,
 			Issuer:             issuerDID.DID.ID,
+			IssuerKID:          issuerDID.DID.VerificationMethod[0].ID,
 			Credentials: []issuing.CredentialTemplate{
 				{
 					ID:                        "id1",
@@ -1094,7 +1111,7 @@ func getValidIssuanceTemplateRequest(m manifest.CredentialManifest, issuerDID *d
 						"state":     "CA",
 					},
 					Expiry: issuing.TimeLike{
-						Time: &now,
+						Time: &expiry1,
 					},
 				},
 				{
@@ -1110,7 +1127,7 @@ func getValidIssuanceTemplateRequest(m manifest.CredentialManifest, issuerDID *d
 							},
 						},
 					},
-					Expiry:    issuing.TimeLike{Duration: &duration},
+					Expiry:    issuing.TimeLike{Duration: &expiry2},
 					Revocable: true,
 				},
 			},
diff --git a/pkg/server/server_operation_test.go b/pkg/server/server_operation_test.go
index 8706423..7b2eca0 100644
--- a/pkg/server/server_operation_test.go
+++ b/pkg/server/server_operation_test.go
@@ -13,6 +13,7 @@ import (
 	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/operation"
 	opstorage "github.com/tbd54566975/ssi-service/pkg/service/operation/storage"
@@ -27,8 +28,9 @@ func TestOperationsAPI(t *testing.T) {
 		opRouter := setupOperationsRouter(t, s)
 
 		holderSigner, holderDID := getSigner(t)
-		definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
-		submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+		kid := authorDID.DID.VerificationMethod[0].ID
+		definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
+		submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 		sub := reviewSubmission(t, pRouter, opstorage.StatusObjectID(submissionOp.ID))
 
 		createdID := submissionOp.ID
@@ -60,8 +62,9 @@ func TestOperationsAPI(t *testing.T) {
 			opRouter := setupOperationsRouter(t, s)
 
 			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
-			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			createdID := submissionOp.ID
 			req := httptest.NewRequest(
@@ -121,12 +124,13 @@ func TestOperationsAPI(t *testing.T) {
 			authorDID := createDID(t, didService)
 			opRouter := setupOperationsRouter(t, s)
 
-			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
 			holderSigner, holderDID := getSigner(t)
-			submissionOp := createSubmission(t, pRouter, def.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			submissionOp := createSubmission(t, pRouter, def.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			holderSigner2, holderDID2 := getSigner(t)
-			submissionOp2 := createSubmission(t, pRouter, def.PresentationDefinition.ID, VerifiableCredential(), holderDID2, holderSigner2)
+			submissionOp2 := createSubmission(t, pRouter, def.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID2, holderSigner2)
 
 			request := router.GetOperationsRequest{
 				Parent: "presentations/submissions",
@@ -157,9 +161,10 @@ func TestOperationsAPI(t *testing.T) {
 			authorDID := createDID(t, didService)
 			opRouter := setupOperationsRouter(t, s)
 
-			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
 			holderSigner, holderDID := getSigner(t)
-			_ = createSubmission(t, pRouter, def.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			_ = createSubmission(t, pRouter, def.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			request := router.GetOperationsRequest{
 				Parent: "presentations/submissions",
@@ -183,9 +188,10 @@ func TestOperationsAPI(t *testing.T) {
 			authorDID := createDID(t, didService)
 			opRouter := setupOperationsRouter(t, s)
 
-			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
 			holderSigner, holderDID := getSigner(t)
-			_ = createSubmission(t, pRouter, def.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			_ = createSubmission(t, pRouter, def.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			request := router.GetOperationsRequest{
 				Parent: "presentations/submissions",
@@ -208,9 +214,10 @@ func TestOperationsAPI(t *testing.T) {
 			authorDID := createDID(t, didService)
 			opRouter := setupOperationsRouter(t, s)
 
-			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			def := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
 			holderSigner, holderDID := getSigner(t)
-			_ = createSubmission(t, pRouter, def.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			_ = createSubmission(t, pRouter, def.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			request := router.GetOperationsRequest{
 				Parent: "/presentations/other",
@@ -235,8 +242,9 @@ func TestOperationsAPI(t *testing.T) {
 			opRouter := setupOperationsRouter(t, s)
 
 			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
-			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			createdID := submissionOp.ID
 			req := httptest.NewRequest(
@@ -262,8 +270,9 @@ func TestOperationsAPI(t *testing.T) {
 			opRouter := setupOperationsRouter(t, s)
 
 			holderSigner, holderDID := getSigner(t)
-			definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID)
-			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(t, pRouter, authorDID.DID.ID, kid)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 			_ = reviewSubmission(t, pRouter, opstorage.StatusObjectID(submissionOp.ID))
 
 			createdID := submissionOp.ID
diff --git a/pkg/server/server_presentation_test.go b/pkg/server/server_presentation_test.go
index 05de245..1754223 100644
--- a/pkg/server/server_presentation_test.go
+++ b/pkg/server/server_presentation_test.go
@@ -18,6 +18,7 @@ import (
 	"github.com/google/uuid"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+
 	"github.com/tbd54566975/ssi-service/config"
 	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
@@ -54,7 +55,8 @@ func TestPresentationAPI(t *testing.T) {
 
 		var createdID string
 		{
-			resp := createPresentationDefinition(tt, pRouter, authorDID.DID.ID, WithInputDescriptors(inputDescriptors))
+			kid := authorDID.DID.VerificationMethod[0].ID
+			resp := createPresentationDefinition(tt, pRouter, authorDID.DID.ID, kid, WithInputDescriptors(inputDescriptors))
 			if diff := cmp.Diff(*pd, resp.PresentationDefinition, cmpopts.IgnoreFields(exchange.PresentationDefinition{}, "ID")); diff != "" {
 				t.Errorf("PresentationDefinition mismatch (-want +got):\n%s", diff)
 			}
@@ -73,7 +75,6 @@ func TestPresentationAPI(t *testing.T) {
 			if diff := cmp.Diff(*pd, resp.PresentationDefinition, cmpopts.IgnoreFields(exchange.PresentationDefinition{}, "ID")); diff != "" {
 				t.Errorf("PresentationDefinition mismatch (-want +got):\n%s", diff)
 			}
-
 		}
 		{
 			// And it can also be listed
@@ -122,8 +123,9 @@ func TestPresentationAPI(t *testing.T) {
 		s := setupTestDB(tt)
 		pRouter, didService := setupPresentationRouter(tt, s)
 		authorDID := createDID(tt, didService)
-		def1 := createPresentationDefinition(tt, pRouter, authorDID.DID.ID)
-		def2 := createPresentationDefinition(tt, pRouter, authorDID.DID.ID)
+		kid := authorDID.DID.VerificationMethod[0].ID
+		def1 := createPresentationDefinition(tt, pRouter, authorDID.DID.ID, kid)
+		def2 := createPresentationDefinition(tt, pRouter, authorDID.DID.ID, kid)
 
 		req := httptest.NewRequest(http.MethodGet, "https://ssi-service.com/v1/presentations/definitions", nil)
 		w := httptest.NewRecorder()
@@ -188,8 +190,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			op := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			op := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -216,8 +219,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			request := createSubmissionRequest(ttt, definition.PresentationDefinition.ID, VerifiableCredential(
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			request := createSubmissionRequest(ttt, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -246,8 +250,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 
 			request := router.ReviewSubmissionRequest{
 				Approved: true,
@@ -279,8 +284,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(), holderDID, holderSigner)
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			submissionOp := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(), holderDID, holderSigner)
 			createdID := opstorage.StatusObjectID(submissionOp.ID)
 			_ = reviewSubmission(ttt, pRouter, createdID)
 
@@ -326,8 +332,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			op := createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			op := createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -337,7 +344,7 @@ func TestPresentationAPI(t *testing.T) {
 				})), holderDID, holderSigner)
 
 			mrTeeSigner, mrTeeDID := getSigner(ttt)
-			op2 := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			op2 := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mr. T",
 					"dateOfBirth":    "1999-01-02",
@@ -429,8 +436,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			op := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			op := createSubmission(ttt, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -485,8 +493,9 @@ func TestPresentationAPI(t *testing.T) {
 			authorDID := createDID(ttt, didService)
 
 			holderSigner, holderDID := getSigner(ttt)
-			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID)
-			_ = createSubmission(t, pRouter, definition.PresentationDefinition.ID, VerifiableCredential(
+			kid := authorDID.DID.VerificationMethod[0].ID
+			definition := createPresentationDefinition(ttt, pRouter, authorDID.DID.ID, kid)
+			_ = createSubmission(t, pRouter, definition.PresentationDefinition.ID, authorDID.DID.ID, VerifiableCredential(
 				WithCredentialSubject(credential.CredentialSubject{
 					"additionalName": "Mclovin",
 					"dateOfBirth":    "1987-01-02",
@@ -537,8 +546,8 @@ func createDID(t *testing.T, didService *did.Service) *did.CreateDIDResponse {
 	return creatorDID
 }
 
-func createSubmission(t *testing.T, pRouter *router.PresentationRouter, definitionID string, vc credential.VerifiableCredential, holderDID didsdk.DIDKey, holderSigner crypto.JWTSigner) router.Operation {
-	request := createSubmissionRequest(t, definitionID, vc, holderSigner, holderDID)
+func createSubmission(t *testing.T, pRouter *router.PresentationRouter, definitionID string, requesterDID string, vc credential.VerifiableCredential, holderDID didsdk.DIDKey, holderSigner crypto.JWTSigner) router.Operation {
+	request := createSubmissionRequest(t, definitionID, requesterDID, vc, holderSigner, holderDID)
 
 	value := newRequestValue(t, request)
 	req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/presentations/submissions", value)
@@ -548,24 +557,23 @@ func createSubmission(t *testing.T, pRouter *router.PresentationRouter, definiti
 
 	require.NoError(t, err)
 	var resp router.Operation
-	assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
+	require.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
 	return resp
 }
 
-func createSubmissionRequest(t *testing.T, definitionID string, vc credential.VerifiableCredential, holderSigner crypto.JWTSigner, holderDID didsdk.DIDKey) router.CreateSubmissionRequest {
+func createSubmissionRequest(t *testing.T, definitionID, requesterDID string, vc credential.VerifiableCredential, holderSigner crypto.JWTSigner, holderDID didsdk.DIDKey) router.CreateSubmissionRequest {
 	issuerSigner, didKey := getSigner(t)
 	vc.Issuer = didKey.String()
 	vcData, err := signing.SignVerifiableCredentialJWT(issuerSigner, vc)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 	ps := exchange.PresentationSubmission{
 		ID:           uuid.NewString(),
 		DefinitionID: definitionID,
 		DescriptorMap: []exchange.SubmissionDescriptor{
 			{
-				ID:         "wa_driver_license",
-				Format:     string(exchange.JWTVPTarget),
-				Path:       "$.verifiableCredential[0]",
-				PathNested: nil,
+				ID:     "wa_driver_license",
+				Format: string(exchange.JWTVPTarget),
+				Path:   "$.verifiableCredential[0]",
 			},
 		},
 	}
@@ -577,11 +585,10 @@ func createSubmissionRequest(t *testing.T, definitionID string, vc credential.Ve
 		Type:                   []string{credential.VerifiablePresentationType},
 		PresentationSubmission: ps,
 		VerifiableCredential:   []any{keyaccess.JWT(vcData)},
-		Proof:                  nil,
 	}
 
-	signed, err := signing.SignVerifiablePresentationJWT(holderSigner, vp)
-	assert.NoError(t, err)
+	signed, err := signing.SignVerifiablePresentationJWT(holderSigner, signing.JWTVVPParameters{Audience: requesterDID}, vp)
+	require.NoError(t, err)
 
 	request := router.CreateSubmissionRequest{SubmissionJWT: keyaccess.JWT(signed)}
 	return request
@@ -589,13 +596,12 @@ func createSubmissionRequest(t *testing.T, definitionID string, vc credential.Ve
 
 func VerifiableCredential(options ...VCOption) credential.VerifiableCredential {
 	vc := credential.VerifiableCredential{
-		Context:          []string{credential.VerifiableCredentialsLinkedDataContext},
-		ID:               uuid.NewString(),
-		Type:             []string{credential.VerifiableCredentialType},
-		Issuer:           "did:key:z4oJ8bFEFv7E3omhuK5LrAtL29Nmd8heBey9HtJCSvodSb7nrfaMrd6zb7fjYSRxrfSgBSDeM6Bs59KRKFgXSDWJcfcjs",
-		IssuanceDate:     "2022-11-07T21:28:57Z",
-		ExpirationDate:   "2051-10-05T14:48:00.000Z",
-		CredentialStatus: nil,
+		Context:        []string{credential.VerifiableCredentialsLinkedDataContext},
+		ID:             uuid.NewString(),
+		Type:           []string{credential.VerifiableCredentialType},
+		Issuer:         "did:key:z4oJ8bFEFv7E3omhuK5LrAtL29Nmd8heBey9HtJCSvodSb7nrfaMrd6zb7fjYSRxrfSgBSDeM6Bs59KRKFgXSDWJcfcjs",
+		IssuanceDate:   "2022-11-07T21:28:57Z",
+		ExpirationDate: "2051-10-05T14:48:00.000Z",
 		CredentialSubject: credential.CredentialSubject{
 			"additionalName": "Mclovin",
 			"dateOfBirth":    "1987-01-02",
@@ -603,11 +609,6 @@ func VerifiableCredential(options ...VCOption) credential.VerifiableCredential {
 			"givenName":      "Uribe",
 			"id":             "did:web:andresuribe.com",
 		},
-		CredentialSchema: nil,
-		RefreshService:   nil,
-		TermsOfUse:       nil,
-		Evidence:         nil,
-		Proof:            nil,
 	}
 	for _, o := range options {
 		o(&vc)
@@ -630,12 +631,11 @@ func WithInputDescriptors(inputDescriptors []exchange.InputDescriptor) Definitio
 		r.InputDescriptors = inputDescriptors
 	}
 }
-func createPresentationDefinition(t *testing.T, pRouter *router.PresentationRouter, author string, opts ...DefinitionOption) router.CreatePresentationDefinitionResponse {
+
+func createPresentationDefinition(t *testing.T, pRouter *router.PresentationRouter, author, authorKID string, opts ...DefinitionOption) router.CreatePresentationDefinitionResponse {
 	request := router.CreatePresentationDefinitionRequest{
-		Name:                   "name",
-		Purpose:                "purpose",
-		Format:                 nil,
-		SubmissionRequirements: nil,
+		Name:    "name",
+		Purpose: "purpose",
 		InputDescriptors: []exchange.InputDescriptor{
 			{
 				ID:      "wa_driver_license",
@@ -657,7 +657,8 @@ func createPresentationDefinition(t *testing.T, pRouter *router.PresentationRout
 				},
 			},
 		},
-		Author: author,
+		Author:    author,
+		AuthorKID: authorKID,
 	}
 	for _, o := range opts {
 		o(&request)
@@ -666,18 +667,21 @@ func createPresentationDefinition(t *testing.T, pRouter *router.PresentationRout
 	req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/presentations/definitions", value)
 	w := httptest.NewRecorder()
 
-	assert.NoError(t, pRouter.CreateDefinition(newRequestContext(), w, req))
+	require.NoError(t, pRouter.CreateDefinition(newRequestContext(), w, req))
 	var resp router.CreatePresentationDefinitionResponse
-	assert.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
+	require.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
 	return resp
 }
 
 func getSigner(t *testing.T) (crypto.JWTSigner, didsdk.DIDKey) {
 	private, didKey, err := didsdk.GenerateDIDKey(crypto.P256)
-	assert.NoError(t, err)
+	require.NoError(t, err)
 
-	signer, err := crypto.NewJWTSigner(didKey.String(), private)
-	assert.NoError(t, err)
+	expanded, err := didKey.Expand()
+	require.NoError(t, err)
+
+	signer, err := crypto.NewJWTSigner(didKey.String(), expanded.VerificationMethod[0].ID, private)
+	require.NoError(t, err)
 
 	return *signer, *didKey
 }
diff --git a/pkg/server/server_schema_test.go b/pkg/server/server_schema_test.go
index 1e68ed6..9521290 100644
--- a/pkg/server/server_schema_test.go
+++ b/pkg/server/server_schema_test.go
@@ -19,7 +19,7 @@ import (
 )
 
 func TestSchemaAPI(t *testing.T) {
-	t.Run("Test Create Schema", func(tt *testing.T) {
+	t.Run("Test Create SchemaID", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
 
@@ -54,7 +54,7 @@ func TestSchemaAPI(t *testing.T) {
 		assert.EqualValues(tt, schemaRequest.Schema, resp.Schema.Schema)
 	})
 
-	t.Run("Test Sign & Verify Schema", func(tt *testing.T) {
+	t.Run("Test Sign & Verify SchemaID", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
 
@@ -71,7 +71,7 @@ func TestSchemaAPI(t *testing.T) {
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/schemas", schemaRequestValue)
 		err := schemaService.CreateSchema(newRequestContext(), w, req)
 		assert.Error(tt, err)
-		assert.Contains(tt, err.Error(), "could not create schema with authoring DID: did:test")
+		assert.Contains(tt, err.Error(), "cannot sign schema without authorKID")
 
 		// create a DID
 		issuerDID, err := didService.CreateDIDByMethod(context.Background(), did.CreateDIDRequest{
@@ -82,7 +82,8 @@ func TestSchemaAPI(t *testing.T) {
 		assert.NotEmpty(tt, issuerDID)
 
 		// sign with known DID
-		schemaRequest = router.CreateSchemaRequest{Author: issuerDID.DID.ID, Name: "test schema", Schema: simpleSchema, Sign: true}
+		kid := issuerDID.DID.VerificationMethod[0].ID
+		schemaRequest = router.CreateSchemaRequest{Author: issuerDID.DID.ID, AuthorKID: kid, Name: "test schema", Schema: simpleSchema, Sign: true}
 		schemaRequestValue = newRequestValue(tt, schemaRequest)
 		req = httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/schemas", schemaRequestValue)
 		err = schemaService.CreateSchema(newRequestContext(), w, req)
@@ -123,7 +124,7 @@ func TestSchemaAPI(t *testing.T) {
 		assert.Contains(tt, verifyResp.Reason, "could not verify schema")
 	})
 
-	t.Run("Test Get Schema and Get Schemas", func(tt *testing.T) {
+	t.Run("Test Get SchemaID and Get Schemas", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
 
@@ -206,7 +207,7 @@ func TestSchemaAPI(t *testing.T) {
 		assert.Len(tt, getSchemasResp.Schemas, 1)
 	})
 
-	t.Run("Test Delete Schema", func(tt *testing.T) {
+	t.Run("Test Delete SchemaID", func(tt *testing.T) {
 		bolt := setupTestDB(tt)
 		require.NotNil(tt, bolt)
 
diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go
index bdd93af..43c8c8c 100644
--- a/pkg/server/server_test.go
+++ b/pkg/server/server_test.go
@@ -128,9 +128,10 @@ func newRequestContextWithParams(params map[string]string) context.Context {
 	return httptreemux.AddParamsToContext(ctx, params)
 }
 
-func getValidManifestRequest(issuerDID, schemaID string) model.CreateManifestRequest {
-	createManifestRequest := model.CreateManifestRequest{
+func getValidManifestRequest(issuerDID, issuerKID, schemaID string) model.CreateManifestRequest {
+	return model.CreateManifestRequest{
 		IssuerDID: issuerDID,
+		IssuerKID: issuerKID,
 		ClaimFormat: &exchange.ClaimFormat{
 			JWTVC: &exchange.JWTType{Alg: []crypto.SignatureAlgorithm{crypto.EdDSA}},
 		},
@@ -164,8 +165,6 @@ func getValidManifestRequest(issuerDID, schemaID string) model.CreateManifestReq
 			},
 		},
 	}
-
-	return createManifestRequest
 }
 
 func getValidApplicationRequest(manifestID, presDefID, submissionDescriptorID string, credentials []credmodel.Container) manifestsdk.CredentialApplicationWrapper {
diff --git a/pkg/service/keystore/service_test.go b/pkg/service/keystore/service_test.go
index 170ee6c..32c7e16 100644
--- a/pkg/service/keystore/service_test.go
+++ b/pkg/service/keystore/service_test.go
@@ -136,7 +136,7 @@ func TestStoreAndGetKey(t *testing.T) {
 	assert.Equal(t, privKey, keyResponse.Key)
 
 	// make sure can create a signer properly
-	signer, err := crypto.NewJWTSigner("kid", keyResponse.Key)
+	signer, err := crypto.NewJWTSigner("test-id", "kid", keyResponse.Key)
 	assert.NoError(t, err)
 	assert.NotEmpty(t, signer)
 }
diff --git a/pkg/testutil/well_known_generation_test.go b/pkg/testutil/well_known_generation_test.go
index 9a68974..109e7d5 100644
--- a/pkg/testutil/well_known_generation_test.go
+++ b/pkg/testutil/well_known_generation_test.go
@@ -92,7 +92,7 @@ func createWellKnownDIDConfiguration(tt *testing.T, didResponse *did.CreateDIDRe
 	cred, err := builder.Build()
 	assert.NoError(tt, err)
 
-	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.Controller, gotKey.ID, gotKey.Key)
 	assert.NoError(tt, err)
 
 	jwtToken := jwt.New()