Repository: TBD54566975/ssi-service
Pull request #130 (2022-10-14 23:30:49)

Credential Manifest signing and verification
- cred manifest signing and verification
- added json tags for required fields to all svc structs
- fixed the schema validator to do some static validation too
- updated the JWT type to be an alias not a struct, using this everywhere
- cred application signing coming next

codecov-commenter: # [Codecov](https://codecov.io/gh/TBD54566975/ssi-service/pull/130?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) Report
> Merging [#130](https://codecov.io/gh/TBD54566975/ssi-service/pull/130?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (f5dec67) into [main](https://codecov.io/gh/TBD54566975/ssi-service/commit/606dc0f3707591814cc4565f841e5e2de212d6fb?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) (606dc0f) will **decrease** coverage by `0.01%`.
> The diff coverage is `39.53%`.

```diff
@@            Coverage Diff             @@
##             main     #130      +/-   ##
==========================================
- Coverage   27.81%   27.80%   -0.02%     
==========================================
  Files          20       20              
  Lines        1485     1500      +15     
==========================================
+ Hits          413      417       +4     
- Misses       1005     1016      +11     
  Partials       67       67              
```


| [Impacted Files](https://codecov.io/gh/TBD54566975/ssi-service/pull/130?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975) | Coverage Δ | |
|---|---|---|
| [pkg/server/router/credential.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/130/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvY3JlZGVudGlhbC5nbw==) | `5.40% <ø> (ø)` | |
| [pkg/server/router/dwn.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/130/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvZHduLmdv) | `17.77% <0.00%> (ø)` | |
| [pkg/server/router/manifest.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/130/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvbWFuaWZlc3QuZ28=) | `3.75% <0.00%> (-0.19%)` | :arrow_down: |
| [pkg/server/router/schema.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/130/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-cGtnL3NlcnZlci9yb3V0ZXIvc2NoZW1hLmdv) | `9.19% <0.00%> (+0.20%)` | :arrow_up: |
| [internal/keyaccess/jwt.go](https://codecov.io/gh/TBD54566975/ssi-service/pull/130/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TBD54566975#diff-aW50ZXJuYWwva2V5YWNjZXNzL2p3dC5nbw==) | `54.54% <77.27%> (+0.19%)` | :arrow_up: |

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)


Patch:
diff --git a/doc/swagger.yaml b/doc/swagger.yaml
index d8ed8e4..4d08deb 100644
--- a/doc/swagger.yaml
+++ b/doc/swagger.yaml
@@ -524,8 +524,10 @@ definitions:
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.CreateManifestResponse:
     properties:
-      manifest:
+      credential_manifest:
         $ref: '#/definitions/manifest.CredentialManifest'
+      manifestJwt:
+        type: string
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.CreateSchemaRequest:
     properties:
@@ -620,16 +622,18 @@ definitions:
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.GetManifestResponse:
     properties:
+      credential_manifest:
+        $ref: '#/definitions/manifest.CredentialManifest'
       id:
         type: string
-      manifest:
-        $ref: '#/definitions/manifest.CredentialManifest'
+      manifestJwt:
+        type: string
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.GetManifestsResponse:
     properties:
       manifests:
         items:
-          $ref: '#/definitions/manifest.CredentialManifest'
+          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetManifestResponse'
         type: array
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.GetResponseResponse:
@@ -746,6 +750,8 @@ definitions:
     properties:
       schemaJwt:
         type: string
+    required:
+    - schemaJwt
     type: object
   github.com_tbd54566975_ssi-service_pkg_server_router.VerifySchemaResponse:
     properties:
@@ -919,8 +925,10 @@ definitions:
     type: object
   pkg_server_router.CreateManifestResponse:
     properties:
-      manifest:
+      credential_manifest:
         $ref: '#/definitions/manifest.CredentialManifest'
+      manifestJwt:
+        type: string
     type: object
   pkg_server_router.CreateSchemaRequest:
     properties:
@@ -1015,16 +1023,18 @@ definitions:
     type: object
   pkg_server_router.GetManifestResponse:
     properties:
+      credential_manifest:
+        $ref: '#/definitions/manifest.CredentialManifest'
       id:
         type: string
-      manifest:
-        $ref: '#/definitions/manifest.CredentialManifest'
+      manifestJwt:
+        type: string
     type: object
   pkg_server_router.GetManifestsResponse:
     properties:
       manifests:
         items:
-          $ref: '#/definitions/manifest.CredentialManifest'
+          $ref: '#/definitions/pkg_server_router.GetManifestResponse'
         type: array
     type: object
   pkg_server_router.GetResponseResponse:
@@ -1141,6 +1151,8 @@ definitions:
     properties:
       schemaJwt:
         type: string
+    required:
+    - schemaJwt
     type: object
   pkg_server_router.VerifySchemaResponse:
     properties:
@@ -1330,7 +1342,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.GetCredentialsResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetCredentialsResponse'
         "400":
           description: Bad request
           schema:
@@ -1352,14 +1364,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/pkg_server_router.CreateCredentialRequest'
+          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateCredentialRequest'
       produces:
       - application/json
       responses:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/pkg_server_router.CreateCredentialResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateCredentialResponse'
         "400":
           description: Bad request
           schema:
@@ -1416,7 +1428,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.GetCredentialResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetCredentialResponse'
         "400":
           description: Bad request
           schema:
@@ -1435,14 +1447,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/pkg_server_router.VerifyCredentialRequest'
+          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.VerifyCredentialRequest'
       produces:
       - application/json
       responses:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.VerifyCredentialResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.VerifyCredentialResponse'
         "400":
           description: Bad request
           schema:
@@ -1461,7 +1473,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.GetDIDMethodsResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetDIDMethodsResponse'
       summary: Get DID Methods
       tags:
       - DecentralizedIdentityAPI
@@ -1482,7 +1494,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.GetDIDsByMethodResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetDIDsByMethodResponse'
         "400":
           description: Bad request
           schema:
@@ -1500,7 +1512,7 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/pkg_server_router.CreateDIDByMethodRequest'
+          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateDIDByMethodRequest'
       - description: Method
         in: path
         name: method
@@ -1512,7 +1524,7 @@ paths:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/pkg_server_router.CreateDIDByMethodResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateDIDByMethodResponse'
         "400":
           description: Bad request
           schema:
@@ -1535,7 +1547,7 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/pkg_server_router.CreateDIDByMethodRequest'
+          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateDIDByMethodRequest'
       - description: Method
         in: path
         name: method
@@ -1552,7 +1564,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.GetDIDByMethodResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetDIDByMethodResponse'
         "400":
           description: Bad request
           schema:
@@ -1577,7 +1589,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/pkg_server_router.ResolveDIDResponse'
+            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.ResolveDIDResponse'
         "400":
           description: Bad request
           schema:
@@ -1596,14 +1608,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.PublishManifestRequest'
+          $ref: '#/definitions/pkg_server_router.PublishManifestRequest'
       produces:
       - application/json
       responses:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.PublishManifestResponse'
+            $ref: '#/definitions/pkg_server_router.PublishManifestResponse'
         "400":
           description: Bad request
           schema:
@@ -1693,7 +1705,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetManifestsResponse'
+            $ref: '#/definitions/pkg_server_router.GetManifestsResponse'
         "400":
           description: Bad request
           schema:
@@ -1715,14 +1727,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateManifestRequest'
+          $ref: '#/definitions/pkg_server_router.CreateManifestRequest'
       produces:
       - application/json
       responses:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateManifestResponse'
+            $ref: '#/definitions/pkg_server_router.CreateManifestResponse'
         "400":
           description: Bad request
           schema:
@@ -1779,7 +1791,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetManifestResponse'
+            $ref: '#/definitions/pkg_server_router.GetManifestResponse'
         "400":
           description: Bad request
           schema:
@@ -1799,7 +1811,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetApplicationsResponse'
+            $ref: '#/definitions/pkg_server_router.GetApplicationsResponse'
         "400":
           description: Bad request
           schema:
@@ -1821,14 +1833,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.SubmitApplicationRequest'
+          $ref: '#/definitions/pkg_server_router.SubmitApplicationRequest'
       produces:
       - application/json
       responses:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.SubmitApplicationResponse'
+            $ref: '#/definitions/pkg_server_router.SubmitApplicationResponse'
         "400":
           description: Bad request
           schema:
@@ -1885,7 +1897,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetApplicationResponse'
+            $ref: '#/definitions/pkg_server_router.GetApplicationResponse'
         "400":
           description: Bad request
           schema:
@@ -1905,7 +1917,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetResponsesResponse'
+            $ref: '#/definitions/pkg_server_router.GetResponsesResponse'
         "400":
           description: Bad request
           schema:
@@ -1962,7 +1974,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetResponseResponse'
+            $ref: '#/definitions/pkg_server_router.GetResponseResponse'
         "400":
           description: Bad request
           schema:
@@ -1981,7 +1993,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetSchemasResponse'
+            $ref: '#/definitions/pkg_server_router.GetSchemasResponse'
         "500":
           description: Internal server error
           schema:
@@ -1999,14 +2011,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateSchemaRequest'
+          $ref: '#/definitions/pkg_server_router.CreateSchemaRequest'
       produces:
       - application/json
       responses:
         "201":
           description: Created
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.CreateSchemaResponse'
+            $ref: '#/definitions/pkg_server_router.CreateSchemaResponse'
         "400":
           description: Bad request
           schema:
@@ -2063,7 +2075,7 @@ paths:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.GetSchemaResponse'
+            $ref: '#/definitions/pkg_server_router.GetSchemaResponse'
         "400":
           description: Bad request
           schema:
@@ -2082,14 +2094,14 @@ paths:
         name: request
         required: true
         schema:
-          $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.VerifySchemaRequest'
+          $ref: '#/definitions/pkg_server_router.VerifySchemaRequest'
       produces:
       - application/json
       responses:
         "200":
           description: OK
           schema:
-            $ref: '#/definitions/github.com_tbd54566975_ssi-service_pkg_server_router.VerifySchemaResponse'
+            $ref: '#/definitions/pkg_server_router.VerifySchemaResponse'
         "400":
           description: Bad request
           schema:
diff --git a/gui/streamlit.py b/gui/streamlit.py
index 19453e1..0bcbbf7 100644
--- a/gui/streamlit.py
+++ b/gui/streamlit.py
@@ -5,9 +5,8 @@ import json
 
 st.title('DID and Verifiable Credentials')
 
-
 #
-# Show health and readitness in the sidebar
+# Show health and readiness in the sidebar
 #
 
 health = requests.get('http://web:3000/health').json()
@@ -15,7 +14,6 @@ readiness = requests.get('http://web:3000/readiness').json()
 ready = readiness['status']['status']
 
 with st.sidebar:
-
     with st.expander("Service detail"):
         st.write(health)
         st.write(readiness)
@@ -26,80 +24,70 @@ with st.sidebar:
         st.error("service: " + str(health.json()['status']))
         st.write(readiness)
 
-
     for state in readiness['serviceStatuses']:
         if readiness['serviceStatuses'][state]['status'] == "ready":
             st.success(state + ": " + readiness['serviceStatuses'][state]['status'])
-        else:            
+        else:
             st.error(readiness['serviceStatuses'][state]['status'])
 
-
-
 if 'did' not in st.session_state:
     st.subheader("Create a DID:")
 
     if st.radio("Make or load a DID", ["Create new DID", "Use existing DID"]) == "Create new DID":
         if st.button("Create new DID"):
-            did = requests.put('http://web:3000/v1/dids/key', data=json.dumps({"keyType":"Ed25519"})).json()            
+            did = requests.put('http://web:3000/v1/dids/key', data=json.dumps({"keyType": "Ed25519"})).json()
             st.session_state.did = did
             st.experimental_rerun()
-        else: 
-            st.stop()        
+        else:
+            st.stop()
 
-    else:    
+    else:
         key = st.text_input("", "did:example:1234")
         if st.button("Lookup DID"):
             did = requests.get('http://web:3000/v1/dids/key/' + key).json()
             st.session_state.did = did
             st.experimental_rerun()
         else:
-            st.stop()    
+            st.stop()
 
 did = st.session_state.did
 
-
 st.text("DID chosen: " + did['did']['id'])
 
 with st.expander("(optional) Show DID detail"):
     st.write(did)
 
-
-
-
-
 st.subheader("Choose a schema to issue a  Verifiable Credential against:")
 
+
 @st.cache
-def load_schemas(): 
+def load_schemas():
     schemas = requests.get('https://schema.org/version/latest/schemaorg-current-https.jsonld').json()
-    
+
     listing = []
     for schema in schemas["@graph"]:
         listing.append(schema["@id"])
 
-    return listing    
+    return listing
+
 
 schemas = load_schemas()
 default_schema = "schema:PostalAddress"
 schema = st.selectbox(options=schemas, label='Select a schema', index=schemas.index(default_schema))
 
-
-
-
-
 st.subheader("Issue a Verifiable Credential:")
 
 expiry = st.date_input("Expiry date:", value=None, min_value=None, max_value=None, key=None, help=None)
 # convert to ISO 8601
 expiry = expiry.isoformat()
 
-
-data =  {
-       "addressLocality": "Paris, France",
-        "postalCode": "75002",
-        "streetAddress": "38 avenue de l'\''Opera"
+data = {
+    "addressLocality": "Paris, France",
+    "postalCode": "75002",
+    "streetAddress": "38 avenue de l'\''Opera"
 }
-data = st.text_area("Data for credential (depends on schema):", value=json.dumps(data), height=None, max_chars=None, key=None, help=None)
+data = st.text_area("Data for credential (depends on schema):", value=json.dumps(data), height=None, max_chars=None,
+                    key=None, help=None)
 
 if st.button("Issue Verifiable Credential"):
     payload = {
@@ -109,5 +97,5 @@ if st.button("Issue Verifiable Credential"):
         "Data": json.loads(data),
         "Expiry": str(expiry) + "T00:00:00+00:00"
     }
-    vc  = requests.put('http://web:3000/v1/credentials', data=json.dumps(payload)).json()
-    st.write(vc)
\ No newline at end of file
+    vc = requests.put('http://web:3000/v1/credentials', data=json.dumps(payload)).json()
+    st.write(vc)
diff --git a/internal/credential/model.go b/internal/credential/model.go
index ab24b0e..e3322aa 100644
--- a/internal/credential/model.go
+++ b/internal/credential/model.go
@@ -8,6 +8,8 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential/signing"
 	"github.com/goccy/go-json"
 	"github.com/pkg/errors"
+
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 )
 
 // Container acts as an abstraction over both possible credential representations
@@ -16,23 +18,13 @@ type Container struct {
 	// Credential ID
 	ID            string
 	Credential    *credential.VerifiableCredential
-	CredentialJWT *CredentialJWT
+	CredentialJWT *keyaccess.JWT
 }
 
 func (c Container) JWTString() string {
 	return string(*c.CredentialJWT)
 }
 
-type CredentialJWT string
-
-func (c *CredentialJWT) String() string {
-	return string(*c)
-}
-
-func CredentialJWTPtr(s string) *CredentialJWT {
-	return (*CredentialJWT)(&s)
-}
-
 // 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)
@@ -41,7 +33,7 @@ func NewCredentialContainerFromJWT(credentialJWT string) (*Container, error) {
 	}
 	return &Container{
 		ID:            cred.ID,
-		CredentialJWT: CredentialJWTPtr(credentialJWT),
+		CredentialJWT: keyaccess.JWTPtr(credentialJWT),
 	}, nil
 }
 
diff --git a/internal/credential/verification.go b/internal/credential/verification.go
index a0ee1fa..ca3d29b 100644
--- a/internal/credential/verification.go
+++ b/internal/credential/verification.go
@@ -47,7 +47,7 @@ func NewCredentialVerifier(didResolver *didsdk.Resolver, schemaResolver schema.R
 
 // VerifyJWTCredential first parses and checks the signature on the given JWT credential. Next, it runs
 // a set of static verification checks on the credential as per the credential service's configuration.
-func (v Verifier) VerifyJWTCredential(token CredentialJWT) error {
+func (v Verifier) VerifyJWTCredential(token keyaccess.JWT) error {
 	// first, parse the token to see if it contains a valid verifiable credential
 	cred, err := signing.ParseVerifiableCredentialFromJWT(token.String())
 	if err != nil {
@@ -67,7 +67,7 @@ func (v Verifier) VerifyJWTCredential(token CredentialJWT) error {
 	}
 
 	// verify the signature on the credential
-	if err := verifier.Verify(keyaccess.JWKToken{Token: token.String()}); err != nil {
+	if err = verifier.Verify(token); err != nil {
 		return util.LoggingErrorMsg(err, "could not verify credential's signature")
 	}
 
@@ -90,7 +90,7 @@ func (v Verifier) VerifyDataIntegrityCredential(credential credsdk.VerifiableCre
 	}
 
 	// verify the signature on the credential
-	if err := verifier.Verify(&credential); err != nil {
+	if err = verifier.Verify(&credential); err != nil {
 		return util.LoggingErrorMsg(err, "could not verify the credential's signature")
 	}
 
diff --git a/internal/keyaccess/jwt.go b/internal/keyaccess/jwt.go
index c5a4fa4..4089b8d 100644
--- a/internal/keyaccess/jwt.go
+++ b/internal/keyaccess/jwt.go
@@ -63,12 +63,22 @@ func NewJWKKeyAccessVerifier(kid string, key gocrypto.PublicKey) (*JWKKeyAccess,
 	}, nil
 }
 
-// A JWKToken is a utility that wraps a string representation of a JSON Web Token.
-type JWKToken struct {
-	Token string `json:"token" validate:"required"`
+type JWT string
+
+func (j JWT) String() string {
+	return string(j)
+}
+
+func (j JWT) Ptr() *JWT {
+	return &j
+}
+
+func JWTPtr(j string) *JWT {
+	jwt := JWT(j)
+	return &jwt
 }
 
-func (ka JWKKeyAccess) Sign(payload map[string]interface{}) (*JWKToken, error) {
+func (ka JWKKeyAccess) Sign(payload map[string]interface{}) (*JWT, error) {
 	if ka.JWTSigner == nil {
 		return nil, errors.New("cannot sign with nil signer")
 	}
@@ -79,17 +89,17 @@ func (ka JWKKeyAccess) Sign(payload map[string]interface{}) (*JWKToken, error) {
 	if err != nil {
 		return nil, errors.Wrap(err, "could not sign payload")
 	}
-	return &JWKToken{Token: string(tokenBytes)}, nil
+	return JWT(tokenBytes).Ptr(), nil
 }
 
-func (ka JWKKeyAccess) Verify(token JWKToken) error {
-	if token.Token == "" {
+func (ka JWKKeyAccess) Verify(token JWT) error {
+	if token == "" {
 		return errors.New("token cannot be empty")
 	}
-	return ka.VerifyJWT(token.Token)
+	return ka.VerifyJWT(string(token))
 }
 
-func (ka JWKKeyAccess) SignVerifiableCredential(credential credential.VerifiableCredential) (*JWKToken, error) {
+func (ka JWKKeyAccess) SignVerifiableCredential(credential credential.VerifiableCredential) (*JWT, error) {
 	if ka.JWTSigner == nil {
 		return nil, errors.New("cannot sign with nil signer")
 	}
@@ -100,17 +110,17 @@ func (ka JWKKeyAccess) SignVerifiableCredential(credential credential.Verifiable
 	if err != nil {
 		return nil, errors.Wrap(err, "could not sign credential")
 	}
-	return &JWKToken{Token: string(tokenBytes)}, nil
+	return JWT(tokenBytes).Ptr(), nil
 }
 
-func (ka JWKKeyAccess) VerifyVerifiableCredential(token JWKToken) (*credential.VerifiableCredential, error) {
-	if token.Token == "" {
+func (ka JWKKeyAccess) VerifyVerifiableCredential(token JWT) (*credential.VerifiableCredential, error) {
+	if token == "" {
 		return nil, errors.New("token cannot be empty")
 	}
-	return signing.VerifyVerifiableCredentialJWT(*ka.JWTVerifier, token.Token)
+	return signing.VerifyVerifiableCredentialJWT(*ka.JWTVerifier, token.String())
 }
 
-func (ka JWKKeyAccess) SignVerifiablePresentation(presentation credential.VerifiablePresentation) (*JWKToken, error) {
+func (ka JWKKeyAccess) SignVerifiablePresentation(presentation credential.VerifiablePresentation) (*JWT, error) {
 	if ka.JWTSigner == nil {
 		return nil, errors.New("cannot sign with nil signer")
 	}
@@ -121,12 +131,12 @@ func (ka JWKKeyAccess) SignVerifiablePresentation(presentation credential.Verifi
 	if err != nil {
 		return nil, errors.Wrap(err, "could not sign presentation")
 	}
-	return &JWKToken{Token: string(tokenBytes)}, nil
+	return JWT(tokenBytes).Ptr(), nil
 }
 
-func (ka JWKKeyAccess) VerifyVerifiablePresentation(token JWKToken) (*credential.VerifiablePresentation, error) {
-	if token.Token == "" {
+func (ka JWKKeyAccess) VerifyVerifiablePresentation(token JWT) (*credential.VerifiablePresentation, error) {
+	if token == "" {
 		return nil, errors.New("token cannot be empty")
 	}
-	return signing.VerifyVerifiablePresentationJWT(*ka.JWTVerifier, token.Token)
+	return signing.VerifyVerifiablePresentationJWT(*ka.JWTVerifier, token.String())
 }
diff --git a/pkg/server/router/credential.go b/pkg/server/router/credential.go
index 55d99c8..51705f1 100644
--- a/pkg/server/router/credential.go
+++ b/pkg/server/router/credential.go
@@ -10,6 +10,7 @@ import (
 	"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"
 	"github.com/tbd54566975/ssi-service/pkg/server/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
@@ -64,7 +65,7 @@ func (c CreateCredentialRequest) ToServiceRequest() credential.CreateCredentialR
 
 type CreateCredentialResponse struct {
 	Credential    *credsdk.VerifiableCredential `json:"credential,omitempty"`
-	CredentialJWT *credmodel.CredentialJWT      `json:"credentialJwt,omitempty"`
+	CredentialJWT *keyaccess.JWT                `json:"credentialJwt,omitempty"`
 }
 
 // CreateCredential godoc
@@ -108,7 +109,7 @@ func (cr CredentialRouter) CreateCredential(ctx context.Context, w http.Response
 type GetCredentialResponse struct {
 	ID            string                        `json:"id"`
 	Credential    *credsdk.VerifiableCredential `json:"credential,omitempty"`
-	CredentialJWT *credmodel.CredentialJWT      `json:"credentialJwt,omitempty"`
+	CredentialJWT *keyaccess.JWT                `json:"credentialJwt,omitempty"`
 }
 
 // GetCredential godoc
@@ -146,7 +147,7 @@ func (cr CredentialRouter) GetCredential(ctx context.Context, w http.ResponseWri
 
 type VerifyCredentialRequest struct {
 	DataIntegrityCredential *credsdk.VerifiableCredential `json:"credential,omitempty"`
-	CredentialJWT           *credmodel.CredentialJWT      `json:"credentialJwt,omitempty"`
+	CredentialJWT           *keyaccess.JWT                `json:"credentialJwt,omitempty"`
 }
 
 func (vcr VerifyCredentialRequest) IsValid() bool {
diff --git a/pkg/server/router/dwn.go b/pkg/server/router/dwn.go
index 69f4b16..665bdb6 100644
--- a/pkg/server/router/dwn.go
+++ b/pkg/server/router/dwn.go
@@ -3,9 +3,11 @@ package router
 import (
 	"context"
 	"fmt"
+	"net/http"
+
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
+
 	"github.com/tbd54566975/ssi-service/pkg/service/dwn"
-	"net/http"
 
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -37,8 +39,8 @@ type PublishManifestRequest struct {
 	ManifestID string `json:"manifestId" validate:"required"`
 }
 
-func (req PublishManifestRequest) ToServiceRequest() dwn.DWNPublishManifestRequest {
-	return dwn.DWNPublishManifestRequest{
+func (req PublishManifestRequest) ToServiceRequest() dwn.PublishManifestRequest {
+	return dwn.PublishManifestRequest{
 		ManifestID: req.ManifestID,
 	}
 }
diff --git a/pkg/server/router/manifest.go b/pkg/server/router/manifest.go
index a0a5285..24d63fe 100644
--- a/pkg/server/router/manifest.go
+++ b/pkg/server/router/manifest.go
@@ -8,6 +8,7 @@ import (
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
 
 	"github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/service/manifest"
 
 	"github.com/pkg/errors"
@@ -34,6 +35,8 @@ func NewManifestRouter(s svcframework.Service) (*ManifestRouter, error) {
 	}, nil
 }
 
+// CreateManifestRequest
+// TODO(gabe) consider simplifying this to accept just output descriptors, format, presentation definition
 type CreateManifestRequest struct {
 	Manifest manifestsdk.CredentialManifest `json:"manifest" validate:"required"`
 }
@@ -45,7 +48,8 @@ func (c CreateManifestRequest) ToServiceRequest() manifest.CreateManifestRequest
 }
 
 type CreateManifestResponse struct {
-	Manifest manifestsdk.CredentialManifest `json:"manifest"`
+	Manifest    manifestsdk.CredentialManifest `json:"credential_manifest"`
+	ManifestJWT keyaccess.JWT                  `json:"manifestJwt"`
 }
 
 // CreateManifest godoc
@@ -67,6 +71,12 @@ func (mr ManifestRouter) CreateManifest(ctx context.Context, w http.ResponseWrit
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
 
+	if err := framework.ValidateRequest(request); err != nil {
+		errMsg := "invalid create manifest request"
+		logrus.WithError(err).Error(errMsg)
+		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
+	}
+
 	req := request.ToServiceRequest()
 	createManifestResponse, err := mr.service.CreateManifest(req)
 	if err != nil {
@@ -75,14 +85,14 @@ func (mr ManifestRouter) CreateManifest(ctx context.Context, w http.ResponseWrit
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusInternalServerError)
 	}
 
-	resp := CreateManifestResponse{Manifest: createManifestResponse.Manifest}
-
+	resp := CreateManifestResponse{Manifest: createManifestResponse.Manifest, ManifestJWT: createManifestResponse.ManifestJWT}
 	return framework.Respond(ctx, w, resp, http.StatusCreated)
 }
 
 type GetManifestResponse struct {
-	ID       string                         `json:"id"`
-	Manifest manifestsdk.CredentialManifest `json:"manifest"`
+	ID          string                         `json:"id"`
+	Manifest    manifestsdk.CredentialManifest `json:"credential_manifest"`
+	ManifestJWT keyaccess.JWT                  `json:"manifestJwt"`
 }
 
 // GetManifest godoc
@@ -111,14 +121,15 @@ func (mr ManifestRouter) GetManifest(ctx context.Context, w http.ResponseWriter,
 	}
 
 	resp := GetManifestResponse{
-		ID:       gotManifest.Manifest.ID,
-		Manifest: gotManifest.Manifest,
+		ID:          gotManifest.Manifest.ID,
+		Manifest:    gotManifest.Manifest,
+		ManifestJWT: gotManifest.ManifestJWT,
 	}
 	return framework.Respond(ctx, w, resp, http.StatusOK)
 }
 
 type GetManifestsResponse struct {
-	Manifests []manifestsdk.CredentialManifest `json:"manifests"`
+	Manifests []GetManifestResponse `json:"manifests,omitempty"`
 }
 
 // GetManifests godoc
@@ -143,10 +154,16 @@ func (mr ManifestRouter) GetManifests(ctx context.Context, w http.ResponseWriter
 		return framework.NewRequestError(errors.Wrap(err, errMsg), http.StatusBadRequest)
 	}
 
-	resp := GetManifestsResponse{
-		Manifests: gotManifests.Manifests,
+	var manifests []GetManifestResponse
+	for _, m := range gotManifests.Manifests {
+		manifests = append(manifests, GetManifestResponse{
+			ID:          m.Manifest.ID,
+			Manifest:    m.Manifest,
+			ManifestJWT: m.ManifestJWT,
+		})
 	}
 
+	resp := GetManifestsResponse{Manifests: manifests}
 	return framework.Respond(ctx, w, resp, http.StatusOK)
 }
 
@@ -237,7 +254,7 @@ func (mr ManifestRouter) SubmitApplication(ctx context.Context, w http.ResponseW
 	}
 
 	var credentials []interface{}
-	for _, container := range submitApplicationResponse.Credential {
+	for _, container := range submitApplicationResponse.Credentials {
 		if container.HasDataIntegrityCredential() {
 			credentials = append(credentials, *container.Credential)
 		} else if container.HasJWTCredential() {
diff --git a/pkg/server/router/schema.go b/pkg/server/router/schema.go
index 0f84acc..532c2af 100644
--- a/pkg/server/router/schema.go
+++ b/pkg/server/router/schema.go
@@ -9,6 +9,7 @@ import (
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/server/framework"
 	svcframework "github.com/tbd54566975/ssi-service/pkg/service/framework"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
@@ -26,9 +27,7 @@ func NewSchemaRouter(s svcframework.Service) (*SchemaRouter, error) {
 	if !ok {
 		return nil, fmt.Errorf("could not create schema router with service type: %s", s.Type())
 	}
-	return &SchemaRouter{
-		service: schemaService,
-	}, nil
+	return &SchemaRouter{service: schemaService}, nil
 }
 
 type CreateSchemaRequest struct {
@@ -42,7 +41,7 @@ type CreateSchemaRequest struct {
 type CreateSchemaResponse struct {
 	ID        string                 `json:"id"`
 	Schema    schemalib.VCJSONSchema `json:"schema"`
-	SchemaJWT *string                `json:"schemaJwt,omitempty"`
+	SchemaJWT *keyaccess.JWT         `json:"schemaJwt,omitempty"`
 }
 
 // CreateSchema godoc
@@ -145,16 +144,16 @@ func (sr SchemaRouter) GetSchemas(ctx context.Context, w http.ResponseWriter, r
 
 type GetSchemaResponse struct {
 	Schema    schemalib.VCJSONSchema `json:"schema,omitempty"`
-	SchemaJWT *string                `json:"schemaJwt,omitempty"`
+	SchemaJWT *keyaccess.JWT         `json:"schemaJwt,omitempty"`
 }
 
 type VerifySchemaRequest struct {
-	SchemaJWT string `json:"schemaJwt"`
+	SchemaJWT keyaccess.JWT `json:"schemaJwt" validate:"required"`
 }
 
 type VerifySchemaResponse struct {
-	Verified bool   `json:"verified" json:"verified"`
-	Reason   string `json:"reason,omitempty" json:"reason,omitempty"`
+	Verified bool   `json:"verified"`
+	Reason   string `json:"reason,omitempty"`
 }
 
 // VerifySchema godoc
diff --git a/pkg/service/credential/credential.go b/pkg/service/credential/credential.go
index fd446cc..dc88acb 100644
--- a/pkg/service/credential/credential.go
+++ b/pkg/service/credential/credential.go
@@ -6,7 +6,7 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential"
 	schemalib "github.com/TBD54566975/ssi-sdk/credential/schema"
-	didint "github.com/TBD54566975/ssi-sdk/did"
+	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	sdkutil "github.com/TBD54566975/ssi-sdk/util"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
@@ -63,7 +63,7 @@ func (s Service) Config() config.CredentialServiceConfig {
 	return s.config
 }
 
-func NewCredentialService(config config.CredentialServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, didResolver *didint.Resolver, schema *schema.Service) (*Service, error) {
+func NewCredentialService(config config.CredentialServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, didResolver *didsdk.Resolver, schema *schema.Service) (*Service, error) {
 	credentialStorage, err := credstorage.NewCredentialStorage(s)
 	if err != nil {
 		errMsg := "could not instantiate storage for the credential service"
@@ -133,7 +133,7 @@ func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCrede
 
 		credSchema := credential.CredentialSchema{
 			ID:   request.JSONSchema,
-			Type: SchemaType,
+			Type: SchemaLDType,
 		}
 		if err = builder.SetCredentialSchema(credSchema); err != nil {
 			errMsg := fmt.Sprintf("could not set JSON Schema for credential: %s", request.JSONSchema)
@@ -179,7 +179,7 @@ func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCrede
 	container := credint.Container{
 		ID:            cred.ID,
 		Credential:    cred,
-		CredentialJWT: credint.CredentialJWTPtr(*credJWT),
+		CredentialJWT: credJWT,
 	}
 	storageRequest := credstorage.StoreCredentialRequest{
 		Container: container,
@@ -195,7 +195,7 @@ func (s Service) CreateCredential(request CreateCredentialRequest) (*CreateCrede
 }
 
 // signCredentialJWT signs a credential and returns it as a vc-jwt
-func (s Service) signCredentialJWT(issuer string, cred credential.VerifiableCredential) (*string, error) {
+func (s Service) signCredentialJWT(issuer string, cred credential.VerifiableCredential) (*keyaccess.JWT, error) {
 	gotKey, err := s.keyStore.GetKey(keystore.GetKeyRequest{ID: issuer})
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get key for signing credential with key<%s>", issuer)
@@ -203,20 +203,20 @@ func (s Service) signCredentialJWT(issuer string, cred credential.VerifiableCred
 	}
 	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
 	if err != nil {
-		errMsg := fmt.Sprintf("could not create key access for signing credential with key<%s>", issuer)
+		errMsg := fmt.Sprintf("could not create key access for signing credential with key<%s>", gotKey.ID)
 		return nil, errors.Wrap(err, errMsg)
 	}
 	credToken, err := keyAccess.SignVerifiableCredential(cred)
 	if err != nil {
-		errMsg := fmt.Sprintf("could not sign credential with key<%s>", issuer)
+		errMsg := fmt.Sprintf("could not sign credential with key<%s>", gotKey.ID)
 		return nil, errors.Wrap(err, errMsg)
 	}
-	return &credToken.Token, nil
+	return credToken, nil
 }
 
 type VerifyCredentialRequest struct {
 	DataIntegrityCredential *credential.VerifiableCredential `json:"credential,omitempty"`
-	CredentialJWT           *credint.CredentialJWT           `json:"credentialJwt,omitempty"`
+	CredentialJWT           *keyaccess.JWT                   `json:"credentialJwt,omitempty"`
 }
 
 // IsValid checks if the request is valid, meaning there is at least one data integrity OR jwt credential, but not both
@@ -301,7 +301,7 @@ func (s Service) GetCredentialsByIssuer(request GetCredentialByIssuerRequest) (*
 		container := credint.Container{
 			ID:            cred.CredentialID,
 			Credential:    cred.Credential,
-			CredentialJWT: (*credint.CredentialJWT)(cred.CredentialJWT),
+			CredentialJWT: cred.CredentialJWT,
 		}
 		creds = append(creds, container)
 	}
diff --git a/pkg/service/credential/model.go b/pkg/service/credential/model.go
index 690cd0a..68f9c10 100644
--- a/pkg/service/credential/model.go
+++ b/pkg/service/credential/model.go
@@ -5,51 +5,51 @@ import (
 )
 
 const (
-	SchemaType string = "JsonSchemaValidator2018"
+	SchemaLDType string = "JsonSchemaValidator2018"
 )
 
 type CreateCredentialRequest struct {
-	Issuer  string
-	Subject string
+	Issuer  string `json:"issuer" validate:"required"`
+	Subject string `json:"subject" validate:"required"`
 	// A context is optional. If not present, we'll apply default, required context values.
-	Context string
+	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
-	Data       map[string]interface{}
-	Expiry     string
+	JSONSchema string                 `json:"jsonSchema,omitempty"`
+	Data       map[string]interface{} `json:"data,omitempty"`
+	Expiry     string                 `json:"expiry,omitempty"`
 	// TODO(gabe) support more capabilities like signature type, format, status, and more.
 }
 
 // CreateCredentialResponse holds a resulting credential from credential creation, which is an XOR type:
 // containing either a Data Integrity Proofed credential or a VC-JWT representation.
 type CreateCredentialResponse struct {
-	credential.Container
+	credential.Container `json:"credential,omitempty"`
 }
 
 type GetCredentialRequest struct {
-	ID string
+	ID string `json:"id" validate:"required"`
 }
 
 type GetCredentialResponse struct {
-	credential.Container
+	credential.Container `json:"credential,omitempty"`
 }
 
 type GetCredentialByIssuerRequest struct {
-	Issuer string
+	Issuer string `json:"issuer" validate:"required"`
 }
 
 type GetCredentialBySubjectRequest struct {
-	Subject string
+	Subject string `json:"subject" validate:"required"`
 }
 
 type GetCredentialBySchemaRequest struct {
-	Schema string
+	Schema string `json:"schema" validate:"required"`
 }
 
 type GetCredentialsResponse struct {
-	Credentials []credential.Container
+	Credentials []credential.Container `json:"credentials,omitempty"`
 }
 
 type DeleteCredentialRequest struct {
-	ID string
+	ID string `json:"id" validate:"required"`
 }
diff --git a/pkg/service/credential/storage/storage.go b/pkg/service/credential/storage/storage.go
index 445da66..5707ad9 100644
--- a/pkg/service/credential/storage/storage.go
+++ b/pkg/service/credential/storage/storage.go
@@ -6,6 +6,7 @@ import (
 	"github.com/TBD54566975/ssi-sdk/credential"
 
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
@@ -22,7 +23,7 @@ type StoredCredential struct {
 
 	// only one of these fields should be present
 	Credential    *credential.VerifiableCredential `json:"credential,omitempty"`
-	CredentialJWT *cred.CredentialJWT              `json:"token,omitempty"`
+	CredentialJWT *keyaccess.JWT                   `json:"token,omitempty"`
 
 	Issuer       string `json:"issuer"`
 	Subject      string `json:"subject"`
diff --git a/pkg/service/dwn/dwn.go b/pkg/service/dwn/dwn.go
index c136968..6fb91ea 100644
--- a/pkg/service/dwn/dwn.go
+++ b/pkg/service/dwn/dwn.go
@@ -60,7 +60,7 @@ func NewDWNService(config config.DWNServiceConfig, s storage.ServiceStorage, key
 	return &service, nil
 }
 
-func (s Service) GetManifest(request DWNPublishManifestRequest) (*DWNPublishManifestResponse, error) {
+func (s Service) GetManifest(request PublishManifestRequest) (*PublishManifestResponse, error) {
 
 	logrus.Debugf("getting manifest: %s", request.ManifestID)
 
@@ -70,6 +70,6 @@ func (s Service) GetManifest(request DWNPublishManifestRequest) (*DWNPublishMani
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 
-	response := DWNPublishManifestResponse{Manifest: gotManifest.Manifest}
+	response := PublishManifestResponse{Manifest: gotManifest.Manifest}
 	return &response, nil
 }
diff --git a/pkg/service/dwn/model.go b/pkg/service/dwn/model.go
index 44ff98b..946d93b 100644
--- a/pkg/service/dwn/model.go
+++ b/pkg/service/dwn/model.go
@@ -2,10 +2,10 @@ package dwn
 
 import manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
 
-type DWNPublishManifestRequest struct {
-	ManifestID string
+type PublishManifestRequest struct {
+	ManifestID string `json:"manifestId" validate:"required"`
 }
 
-type DWNPublishManifestResponse struct {
-	Manifest manifestsdk.CredentialManifest
+type PublishManifestResponse struct {
+	Manifest manifestsdk.CredentialManifest `json:"manifest"`
 }
diff --git a/pkg/service/manifest/manifest.go b/pkg/service/manifest/manifest.go
index 6b9ccc8..8db0233 100644
--- a/pkg/service/manifest/manifest.go
+++ b/pkg/service/manifest/manifest.go
@@ -5,11 +5,16 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential/exchange"
 	"github.com/TBD54566975/ssi-sdk/credential/manifest"
+	didsdk "github.com/TBD54566975/ssi-sdk/did"
 	sdkutil "github.com/TBD54566975/ssi-sdk/util"
+	"github.com/goccy/go-json"
+	"github.com/lestrrat-go/jwx/jwt"
+	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 
 	"github.com/tbd54566975/ssi-service/config"
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/framework"
@@ -23,8 +28,9 @@ type Service struct {
 	config  config.ManifestServiceConfig
 
 	// external dependencies
-	credential *credential.Service
 	keyStore   *keystore.Service
+	resolver   *didsdk.Resolver
+	credential *credential.Service
 }
 
 func (s Service) Type() framework.Type {
@@ -36,12 +42,15 @@ func (s Service) Status() framework.Status {
 	if s.storage == nil {
 		ae.AppendString("no storage configured")
 	}
-	if s.credential == nil {
-		ae.AppendString("no credential service configured")
-	}
 	if s.keyStore == nil {
 		ae.AppendString("no keystore service configured")
 	}
+	if s.resolver == nil {
+		ae.AppendString("no did resolver configured")
+	}
+	if s.credential == nil {
+		ae.AppendString("no credential service configured")
+	}
 	if !ae.IsEmpty() {
 		return framework.Status{
 			Status:  framework.StatusNotReady,
@@ -55,7 +64,7 @@ func (s Service) Config() config.ManifestServiceConfig {
 	return s.config
 }
 
-func NewManifestService(config config.ManifestServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, credential *credential.Service) (*Service, error) {
+func NewManifestService(config config.ManifestServiceConfig, s storage.ServiceStorage, keyStore *keystore.Service, didResolver *didsdk.Resolver, credential *credential.Service) (*Service, error) {
 	manifestStorage, err := manifeststorage.NewManifestStorage(s)
 	if err != nil {
 		errMsg := "could not instantiate storage for the manifest service"
@@ -65,34 +74,129 @@ func NewManifestService(config config.ManifestServiceConfig, s storage.ServiceSt
 		storage:    manifestStorage,
 		config:     config,
 		keyStore:   keyStore,
+		resolver:   didResolver,
 		credential: credential,
 	}, nil
 }
 
 func (s Service) CreateManifest(request CreateManifestRequest) (*CreateManifestResponse, error) {
+
 	logrus.Debugf("creating manifest: %+v", request)
 
+	// validate the request
 	m := request.Manifest
 	if err := m.IsValid(); err != nil {
 		return nil, util.LoggingErrorMsg(err, "manifest is not valid")
 	}
 
+	// sign the manifest
+	manifestJWT, err := s.signManifestJWT(m)
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not sign manifest")
+	}
+
 	// store the manifest
 	storageRequest := manifeststorage.StoredManifest{
-		ID:       m.ID,
-		Manifest: m,
-		Issuer:   m.Issuer.ID,
+		ID:          m.ID,
+		Issuer:      m.Issuer.ID,
+		Manifest:    m,
+		ManifestJWT: *manifestJWT,
 	}
 
-	if err := s.storage.StoreManifest(storageRequest); err != nil {
+	if err = s.storage.StoreManifest(storageRequest); err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not store manifest")
 	}
 
 	// return the result
-	response := CreateManifestResponse{Manifest: m}
+	response := CreateManifestResponse{Manifest: m, ManifestJWT: *manifestJWT}
 	return &response, nil
 }
 
+func (s Service) signManifestJWT(m manifest.CredentialManifest) (*keyaccess.JWT, error) {
+	issuerID := m.Issuer.ID
+	gotKey, err := s.keyStore.GetKey(keystore.GetKeyRequest{ID: issuerID})
+	if err != nil {
+		errMsg := fmt.Sprintf("could not get key for signing manifest with key<%s>", issuerID)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+	keyAccess, err := keyaccess.NewJWKKeyAccess(gotKey.ID, gotKey.Key)
+	if err != nil {
+		errMsg := fmt.Sprintf("could not create key access for signing manifest with key<%s>", gotKey.ID)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+
+	// marshal the manifest before signing it as a JWT
+	manifestBytes, err := json.Marshal(m)
+	if err != nil {
+		errMsg := fmt.Sprintf("could not marshal manifest<%s>", m.ID)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+	var manifestJSON map[string]interface{}
+	if err := json.Unmarshal(manifestBytes, &manifestJSON); err != nil {
+		errMsg := fmt.Sprintf("could not unmarshal manifest<%s>", m.ID)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+
+	manifestToken, err := keyAccess.Sign(manifestJSON)
+	if err != nil {
+		errMsg := fmt.Sprintf("could not sign manifest with key<%s>", gotKey.ID)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+	return manifestToken, nil
+}
+
+// VerifyManifest verifies a manifest's signature and makes sure the manifest is compliant with the specification
+func (s Service) VerifyManifest(request VerifyManifestRequest) (*VerifyManifestResponse, error) {
+	m, err := s.verifyManifestJWT(request.ManifestJWT)
+	if err != nil {
+		return &VerifyManifestResponse{Verified: false, Reason: "could not verify manifest's signature: " + err.Error()}, nil
+	}
+
+	// check the manifest is valid against its specification
+	if err := m.IsValid(); err != nil {
+		return &VerifyManifestResponse{Verified: false, Reason: "manifest is not valid: " + err.Error()}, nil
+	}
+	return &VerifyManifestResponse{Verified: true}, nil
+}
+
+func (s Service) verifyManifestJWT(token keyaccess.JWT) (*manifest.CredentialManifest, error) {
+	parsed, err := jwt.Parse([]byte(token))
+	if err != nil {
+		errMsg := "could not parse JWT"
+		logrus.WithError(err).Error(errMsg)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+	claims := parsed.PrivateClaims()
+	claimsJSONBytes, err := json.Marshal(claims)
+	if err != nil {
+		errMsg := "could not marshal claims"
+		logrus.WithError(err).Error(errMsg)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+	var parsedManifest manifest.CredentialManifest
+	if err := json.Unmarshal(claimsJSONBytes, &parsedManifest); err != nil {
+		errMsg := "could not unmarshal claims into manifest"
+		logrus.WithError(err).Error(errMsg)
+		return nil, util.LoggingErrorMsg(err, errMsg)
+	}
+	resolved, err := s.resolver.Resolve(parsedManifest.Issuer.ID)
+	if err != nil {
+		return nil, errors.Wrapf(err, "failed to resolve manifest issuer's did: %s", parsedManifest.Issuer.ID)
+	}
+	kid, pubKey, err := keyaccess.GetVerificationInformation(resolved.DIDDocument, "")
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not get verification information from manifest")
+	}
+	verifier, err := keyaccess.NewJWKKeyAccessVerifier(kid, pubKey)
+	if err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not create manifest verifier")
+	}
+	if err := verifier.Verify(token); err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not verify the manifest's signature")
+	}
+	return &parsedManifest, nil
+}
+
 func (s Service) GetManifest(request GetManifestRequest) (*GetManifestResponse, error) {
 
 	logrus.Debugf("getting manifest: %s", request.ID)
@@ -103,7 +207,7 @@ func (s Service) GetManifest(request GetManifestRequest) (*GetManifestResponse,
 		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 
-	response := GetManifestResponse{Manifest: gotManifest.Manifest}
+	response := GetManifestResponse{Manifest: gotManifest.Manifest, ManifestJWT: gotManifest.ManifestJWT}
 	return &response, nil
 }
 
@@ -114,9 +218,10 @@ func (s Service) GetManifests() (*GetManifestsResponse, error) {
 		return nil, util.LoggingErrorMsg(err, "could not get manifests(s)")
 	}
 
-	var manifests []manifest.CredentialManifest
+	var manifests []GetManifestResponse
 	for _, m := range gotManifests {
-		manifests = append(manifests, m.Manifest)
+		response := GetManifestResponse{Manifest: m.Manifest, ManifestJWT: m.ManifestJWT}
+		manifests = append(manifests, response)
 	}
 	response := GetManifestsResponse{Manifests: manifests}
 	return &response, nil
@@ -257,7 +362,7 @@ func (s Service) ProcessApplicationSubmission(request SubmitApplicationRequest)
 		return nil, util.LoggingErrorMsg(err, "could not store manifest response")
 	}
 
-	response := SubmitApplicationResponse{Response: *credRes, Credential: creds}
+	response := SubmitApplicationResponse{Response: *credRes, Credentials: creds}
 	return &response, nil
 }
 
diff --git a/pkg/service/manifest/model.go b/pkg/service/manifest/model.go
index deab998..cce7aec 100644
--- a/pkg/service/manifest/model.go
+++ b/pkg/service/manifest/model.go
@@ -4,78 +4,90 @@ import (
 	manifestsdk "github.com/TBD54566975/ssi-sdk/credential/manifest"
 
 	cred "github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 )
 
 // Manifest
 
 type CreateManifestRequest struct {
-	Manifest manifestsdk.CredentialManifest
+	Manifest manifestsdk.CredentialManifest `json:"manifest" validate:"required"`
 }
 
 type CreateManifestResponse struct {
-	Manifest manifestsdk.CredentialManifest
+	Manifest    manifestsdk.CredentialManifest `json:"manifest"`
+	ManifestJWT keyaccess.JWT                  `json:"manifestJwt,omitempty"`
+}
+
+type VerifyManifestRequest struct {
+	ManifestJWT keyaccess.JWT `json:"manifestJwt"`
+}
+
+type VerifyManifestResponse struct {
+	Verified bool   `json:"verified" json:"verified"`
+	Reason   string `json:"reason,omitempty" json:"reason,omitempty"`
 }
 
 type GetManifestRequest struct {
-	ID string
+	ID string `json:"id" validate:"required"`
 }
 
 type GetManifestResponse struct {
-	Manifest manifestsdk.CredentialManifest
+	Manifest    manifestsdk.CredentialManifest `json:"manifest"`
+	ManifestJWT keyaccess.JWT                  `json:"manifestJwt,omitempty"`
 }
 
 type GetManifestsResponse struct {
-	Manifests []manifestsdk.CredentialManifest
+	Manifests []GetManifestResponse `json:"manifests,omitempty"`
 }
 
 type DeleteManifestRequest struct {
-	ID string
+	ID string `json:"id" validate:"required"`
 }
 
 // Application
 
 type SubmitApplicationRequest struct {
-	ApplicantDID   string
-	Application    manifestsdk.CredentialApplication
-	Credentials    []cred.Container
-	ApplicationJWT string
+	ApplicantDID   string                            `json:"applicantDid" validate:"required"`
+	Application    manifestsdk.CredentialApplication `json:"application" validate:"required"`
+	Credentials    []cred.Container                  `json:"credentials,omitempty"`
+	ApplicationJWT keyaccess.JWT                     `json:"applicationJWT,omitempty" validate:"required"`
 }
 
 type SubmitApplicationResponse struct {
-	Response   manifestsdk.CredentialResponse
-	Credential []cred.Container
+	Response    manifestsdk.CredentialResponse `json:"response"`
+	Credentials []cred.Container               `json:"credentials,omitempty"`
 }
 
 type GetApplicationRequest struct {
-	ID string
+	ID string `json:"id" validate:"required"`
 }
 
 type GetApplicationResponse struct {
-	Application manifestsdk.CredentialApplication
+	Application manifestsdk.CredentialApplication `json:"application"`
 }
 
 type GetApplicationsResponse struct {
-	Applications []manifestsdk.CredentialApplication
+	Applications []manifestsdk.CredentialApplication `json:"applications,omitempty"`
 }
 
 type DeleteApplicationRequest struct {
-	ID string
+	ID string `json:"id,omitempty" validate:"required"`
 }
 
 // Response
 
 type GetResponseRequest struct {
-	ID string
+	ID string `json:"id,omitempty" validate:"required"`
 }
 
 type GetResponseResponse struct {
-	Response manifestsdk.CredentialResponse
+	Response manifestsdk.CredentialResponse `json:"response"`
 }
 
 type GetResponsesResponse struct {
-	Responses []manifestsdk.CredentialResponse
+	Responses []manifestsdk.CredentialResponse `json:"responses,omitempty"`
 }
 
 type DeleteResponseRequest struct {
-	ID string
+	ID string `json:"id" validate:"required"`
 }
diff --git a/pkg/service/manifest/storage/storage.go b/pkg/service/manifest/storage/storage.go
index 0642703..d36e1a2 100644
--- a/pkg/service/manifest/storage/storage.go
+++ b/pkg/service/manifest/storage/storage.go
@@ -6,14 +6,16 @@ import (
 	"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/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
 
 type StoredManifest struct {
-	ID       string                      `json:"id"`
-	Manifest manifest.CredentialManifest `json:"manifest"`
-	Issuer   string                      `json:"issuer"`
+	ID          string                      `json:"id"`
+	Issuer      string                      `json:"issuer"`
+	Manifest    manifest.CredentialManifest `json:"manifest"`
+	ManifestJWT keyaccess.JWT               `json:"manifestJwt"`
 }
 
 type StoredApplication struct {
diff --git a/pkg/service/schema/model.go b/pkg/service/schema/model.go
index 4a3c115..adfb0a1 100644
--- a/pkg/service/schema/model.go
+++ b/pkg/service/schema/model.go
@@ -3,6 +3,8 @@ package schema
 import (
 	"github.com/TBD54566975/ssi-sdk/credential/schema"
 	"github.com/TBD54566975/ssi-sdk/util"
+
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 )
 
 const (
@@ -23,7 +25,16 @@ func (csr CreateSchemaRequest) IsValid() bool {
 type CreateSchemaResponse struct {
 	ID        string              `json:"id"`
 	Schema    schema.VCJSONSchema `json:"schema"`
-	SchemaJWT *string             `json:"schemaJwt,omitempty"`
+	SchemaJWT *keyaccess.JWT      `json:"schemaJwt,omitempty"`
+}
+
+type VerifySchemaRequest struct {
+	SchemaJWT keyaccess.JWT `json:"schemaJwt"`
+}
+
+type VerifySchemaResponse struct {
+	Verified bool   `json:"verified" json:"verified"`
+	Reason   string `json:"reason,omitempty" json:"reason,omitempty"`
 }
 
 type GetSchemasResponse struct {
@@ -37,7 +48,7 @@ type GetSchemaRequest struct {
 type GetSchemaResponse struct {
 	ID        string              `json:"id"`
 	Schema    schema.VCJSONSchema `json:"schema"`
-	SchemaJWT *string             `json:"schemaJwt,omitempty"`
+	SchemaJWT *keyaccess.JWT      `json:"schemaJwt,omitempty"`
 }
 
 type DeleteSchemaRequest struct {
diff --git a/pkg/service/schema/schema.go b/pkg/service/schema/schema.go
index bfb7fe1..2d59a18 100644
--- a/pkg/service/schema/schema.go
+++ b/pkg/service/schema/schema.go
@@ -146,7 +146,7 @@ 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(author string, schema schema.VCJSONSchema) (*string, error) {
+func (s Service) signSchemaJWT(author string, schema schema.VCJSONSchema) (*keyaccess.JWT, error) {
 	gotKey, err := s.keyStore.GetKey(keystore.GetKeyRequest{ID: author})
 	if err != nil {
 		errMsg := fmt.Sprintf("could not get key for signing schema for author<%s>", author)
@@ -167,64 +167,66 @@ func (s Service) signSchemaJWT(author string, schema schema.VCJSONSchema) (*stri
 		errMsg := fmt.Sprintf("could not sign schema for author<%s>", author)
 		return nil, errors.Wrap(err, errMsg)
 	}
-	if err = s.verifySchemaJWT(string(schemaToken)); err != nil {
+	if _, err = s.verifySchemaJWT(keyaccess.JWT(schemaToken)); err != nil {
 		return nil, errors.Wrap(err, "could not verify signed schema")
 	}
-	return sdkutil.StringPtr(string(schemaToken)), nil
-}
-
-type VerifySchemaRequest struct {
-	SchemaJWT string `json:"credentialJwt"`
-}
-
-type VerifySchemaResponse struct {
-	Verified bool   `json:"verified" json:"verified"`
-	Reason   string `json:"reason,omitempty" json:"reason,omitempty"`
+	return keyaccess.JWTPtr(string(schemaToken)), nil
 }
 
+// VerifySchema verifies a schema's signature and makes sure the schema is compliant with the specification
 func (s Service) VerifySchema(request VerifySchemaRequest) (*VerifySchemaResponse, error) {
-	if err := s.verifySchemaJWT(request.SchemaJWT); err != nil {
-		return &VerifySchemaResponse{Verified: false, Reason: "could not verify schema: " + err.Error()}, nil
+	credSchema, err := s.verifySchemaJWT(request.SchemaJWT)
+	if err != nil {
+		return &VerifySchemaResponse{Verified: false, Reason: "could not verify schema's signature: " + err.Error()}, nil
+	}
+
+	// check the schema is valid against its specification
+	schemaBytes, err := json.Marshal(credSchema)
+	if err != nil {
+		return nil, errors.Wrap(err, "could not marshal schema into json")
+	}
+	if err := schema.IsValidCredentialSchema(string(schemaBytes)); err != nil {
+		return &VerifySchemaResponse{Verified: false, Reason: "schema is not a valid credential schema: " + err.Error()}, nil
 	}
 	return &VerifySchemaResponse{Verified: true}, nil
 }
 
-func (s Service) verifySchemaJWT(token string) error {
+func (s Service) verifySchemaJWT(token keyaccess.JWT) (*schema.VCJSONSchema, error) {
 	parsed, err := jwt.Parse([]byte(token))
 	if err != nil {
 		errMsg := "could not parse JWT"
 		logrus.WithError(err).Error(errMsg)
-		return util.LoggingErrorMsg(err, errMsg)
+		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 	claims := parsed.PrivateClaims()
 	claimsJSONBytes, err := json.Marshal(claims)
 	if err != nil {
 		errMsg := "could not marshal claims"
 		logrus.WithError(err).Error(errMsg)
-		return util.LoggingErrorMsg(err, errMsg)
+		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 	var parsedSchema schema.VCJSONSchema
 	if err := json.Unmarshal(claimsJSONBytes, &parsedSchema); err != nil {
 		errMsg := "could not unmarshal claims into schema"
 		logrus.WithError(err).Error(errMsg)
-		return util.LoggingErrorMsg(err, errMsg)
+		return nil, util.LoggingErrorMsg(err, errMsg)
 	}
 	resolved, err := s.resolver.Resolve(parsedSchema.Author)
 	if err != nil {
-		return errors.Wrapf(err, "failed to resolve schema author's did: %s", parsedSchema.Author)
+		return nil, errors.Wrapf(err, "failed to resolve schema author's did: %s", parsedSchema.Author)
 	}
 	kid, pubKey, err := keyaccess.GetVerificationInformation(resolved.DIDDocument, "")
 	if err != nil {
-		return util.LoggingErrorMsg(err, "could not get verification information from schema")
+		return nil, util.LoggingErrorMsg(err, "could not get verification information from schema")
 	}
 	verifier, err := keyaccess.NewJWKKeyAccessVerifier(kid, pubKey)
 	if err != nil {
-		return util.LoggingErrorMsg(err, "could not create verifier")
+		return nil, util.LoggingErrorMsg(err, "could not create schema verifier")
 	}
-	if err := verifier.Verify(keyaccess.JWKToken{Token: token}); err != nil {
-		return util.LoggingErrorMsg(err, "could not verify the schema's signature")
+	if err := verifier.Verify(token); err != nil {
+		return nil, util.LoggingErrorMsg(err, "could not verify the schema's signature")
 	}
-	return nil
+	return &parsedSchema, nil
 }
 
 func (s Service) GetSchemas() (*GetSchemasResponse, error) {
@@ -243,9 +245,8 @@ func (s Service) GetSchemas() (*GetSchemasResponse, error) {
 			SchemaJWT: stored.SchemaJWT,
 		})
 	}
-	return &GetSchemasResponse{
-		Schemas: schemas,
-	}, nil
+
+	return &GetSchemasResponse{Schemas: schemas}, nil
 }
 
 func (s Service) GetSchema(request GetSchemaRequest) (*GetSchemaResponse, error) {
diff --git a/pkg/service/schema/storage/storage.go b/pkg/service/schema/storage/storage.go
index 8797cb4..143e234 100644
--- a/pkg/service/schema/storage/storage.go
+++ b/pkg/service/schema/storage/storage.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/TBD54566975/ssi-sdk/credential/schema"
 
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/internal/util"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
@@ -12,7 +13,7 @@ import (
 type StoredSchema struct {
 	ID        string              `json:"id"`
 	Schema    schema.VCJSONSchema `json:"schema"`
-	SchemaJWT *string             `json:"token,omitempty"`
+	SchemaJWT *keyaccess.JWT      `json:"token,omitempty"`
 }
 
 type Storage interface {
diff --git a/pkg/service/service.go b/pkg/service/service.go
index 11890e2..c7e426f 100644
--- a/pkg/service/service.go
+++ b/pkg/service/service.go
@@ -95,7 +95,7 @@ func instantiateServices(config config.ServicesConfig) ([]framework.Service, err
 		return nil, util.LoggingErrorMsg(err, "could not instantiate the credential service")
 	}
 
-	manifestService, err := manifest.NewManifestService(config.ManifestConfig, storageProvider, keyStoreService, credentialService)
+	manifestService, err := manifest.NewManifestService(config.ManifestConfig, storageProvider, keyStoreService, didResolver, credentialService)
 	if err != nil {
 		return nil, util.LoggingErrorMsg(err, "could not instantiate the manifest service")
 	}


Test patch:
diff --git a/internal/keyaccess/jwt_test.go b/internal/keyaccess/jwt_test.go
index ef5e67e..73433b4 100644
--- a/internal/keyaccess/jwt_test.go
+++ b/internal/keyaccess/jwt_test.go
@@ -92,7 +92,7 @@ func TestJWKKeyAccessSignVerify(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, ka)
 
-		err = ka.Verify(JWKToken{})
+		err = ka.Verify(JWT(""))
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "token cannot be empty")
 	})
@@ -149,7 +149,7 @@ func TestJWKKeyAccessSignVerifyCredentials(t *testing.T) {
 		assert.NotEmpty(tt, ka)
 
 		// verify
-		_, err = ka.VerifyVerifiableCredential(JWKToken{"bad"})
+		_, err = ka.VerifyVerifiableCredential(JWT("bad"))
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not verify JWT and its signature")
 	})
@@ -206,7 +206,7 @@ func TestJWKKeyAccessSignVerifyPresentations(t *testing.T) {
 		assert.NotEmpty(tt, ka)
 
 		// verify
-		_, err = ka.VerifyVerifiablePresentation(JWKToken{"bad"})
+		_, err = ka.VerifyVerifiablePresentation(JWT("bad"))
 		assert.Error(tt, err)
 		assert.Contains(tt, err.Error(), "could not verify JWT and its signature")
 	})
diff --git a/pkg/server/router/dwn_test.go b/pkg/server/router/dwn_test.go
index 75644e4..6545897 100644
--- a/pkg/server/router/dwn_test.go
+++ b/pkg/server/router/dwn_test.go
@@ -42,7 +42,7 @@ func TestDWNRouter(t *testing.T) {
 		didService := testDIDService(t, bolt, keyStore)
 		schemaService := testSchemaService(t, bolt, keyStore, didService)
 		credentialService := testCredentialService(t, bolt, keyStore, didService, schemaService)
-		manifestService := testManifestService(t, bolt, keyStore, credentialService)
+		manifestService := testManifestService(t, bolt, keyStore, didService, credentialService)
 		dwnService, err := dwn.NewDWNService(serviceConfig, bolt, keyStore, manifestService)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, dwnService)
diff --git a/pkg/server/router/manifest_test.go b/pkg/server/router/manifest_test.go
index eaac273..ed85567 100644
--- a/pkg/server/router/manifest_test.go
+++ b/pkg/server/router/manifest_test.go
@@ -51,7 +51,7 @@ func TestManifestRouter(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestService, err := manifest.NewManifestService(serviceConfig, bolt, keyStoreService, credentialService)
+		manifestService, err := manifest.NewManifestService(serviceConfig, bolt, keyStoreService, didService.GetResolver(), credentialService)
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, manifestService)
 
@@ -103,6 +103,11 @@ func TestManifestRouter(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdManifest)
 
+		verificationResponse, err := manifestService.VerifyManifest(manifest.VerifyManifestRequest{ManifestJWT: createdManifest.ManifestJWT})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, verificationResponse)
+		assert.True(tt, verificationResponse.Verified)
+
 		m := createdManifest.Manifest
 		assert.NotEmpty(tt, m)
 
@@ -118,7 +123,7 @@ func TestManifestRouter(t *testing.T) {
 		assert.NoError(tt, err)
 		assert.NotEmpty(tt, createdManifest)
 		assert.NotEmpty(tt, createdApplicationResponse.Response.ID)
-		assert.Equal(tt, len(createManifestRequest.Manifest.OutputDescriptors), len(createdApplicationResponse.Credential))
+		assert.Equal(tt, len(createManifestRequest.Manifest.OutputDescriptors), len(createdApplicationResponse.Credentials))
 	})
 }
 
diff --git a/pkg/server/router/testutils_test.go b/pkg/server/router/testutils_test.go
index 408c67d..90bcd54 100644
--- a/pkg/server/router/testutils_test.go
+++ b/pkg/server/router/testutils_test.go
@@ -56,10 +56,10 @@ func testCredentialService(t *testing.T, db *storage.BoltDB, keyStore *keystore.
 	return credentialService
 }
 
-func testManifestService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, credential *credential.Service) *manifest.Service {
+func testManifestService(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, credential *credential.Service) *manifest.Service {
 	serviceConfig := config.ManifestServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "manifest"}}
 	// create a manifest service
-	manifestService, err := manifest.NewManifestService(serviceConfig, db, keyStore, credential)
+	manifestService, err := manifest.NewManifestService(serviceConfig, db, keyStore, did.GetResolver(), credential)
 	require.NoError(t, err)
 	require.NotEmpty(t, manifestService)
 	return manifestService
diff --git a/pkg/server/server_credential_test.go b/pkg/server/server_credential_test.go
index 0c7def2..49ce37d 100644
--- a/pkg/server/server_credential_test.go
+++ b/pkg/server/server_credential_test.go
@@ -15,7 +15,7 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 
-	"github.com/tbd54566975/ssi-service/internal/credential"
+	"github.com/tbd54566975/ssi-service/internal/keyaccess"
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
@@ -610,7 +610,7 @@ func TestCredentialAPI(t *testing.T) {
 		assert.True(tt, verifyResp.Verified)
 
 		// bad credential
-		requestValue = newRequestValue(tt, router.VerifyCredentialRequest{CredentialJWT: credential.CredentialJWTPtr("bad")})
+		requestValue = newRequestValue(tt, router.VerifyCredentialRequest{CredentialJWT: keyaccess.JWTPtr("bad")})
 		req = httptest.NewRequest(http.MethodPost, "https://ssi-service.com/v1/credentials/verification", requestValue)
 		err = credRouter.VerifyCredential(newRequestContext(), w, req)
 		assert.NoError(tt, err)
diff --git a/pkg/server/server_dwn_test.go b/pkg/server/server_dwn_test.go
index e625eda..5ce22ba 100644
--- a/pkg/server/server_dwn_test.go
+++ b/pkg/server/server_dwn_test.go
@@ -33,7 +33,7 @@ func TestDWNAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, manifestService := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, manifestService := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 		dwnService := testDWNRouter(tt, bolt, keyStoreService, manifestService)
 
 		w := httptest.NewRecorder()
diff --git a/pkg/server/server_manifest_test.go b/pkg/server/server_manifest_test.go
index f4809a5..4d8f8d4 100644
--- a/pkg/server/server_manifest_test.go
+++ b/pkg/server/server_manifest_test.go
@@ -16,6 +16,7 @@ import (
 	"github.com/tbd54566975/ssi-service/pkg/server/router"
 	"github.com/tbd54566975/ssi-service/pkg/service/credential"
 	"github.com/tbd54566975/ssi-service/pkg/service/did"
+	manifestsvc "github.com/tbd54566975/ssi-service/pkg/service/manifest"
 	"github.com/tbd54566975/ssi-service/pkg/service/schema"
 	"github.com/tbd54566975/ssi-service/pkg/storage"
 )
@@ -35,11 +36,10 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, manifestService := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		// missing required field: Manifest
-		badManifestRequest := router.CreateManifestRequest{}
-
+		var badManifestRequest router.CreateManifestRequest
 		badRequestValue := newRequestValue(tt, badManifestRequest)
 		req := httptest.NewRequest(http.MethodPut, "https://ssi-service.com/v1/manifests", badRequestValue)
 		w := httptest.NewRecorder()
@@ -87,6 +87,12 @@ func TestManifestAPI(t *testing.T) {
 
 		assert.NotEmpty(tt, resp.Manifest)
 		assert.Equal(tt, resp.Manifest.Issuer.ID, issuerDID.DID.ID)
+
+		// verify the manifest
+		verificationResponse, err := manifestService.VerifyManifest(manifestsvc.VerifyManifestRequest{ManifestJWT: resp.ManifestJWT})
+		assert.NoError(tt, err)
+		assert.NotEmpty(tt, verificationResponse)
+		assert.True(tt, verificationResponse.Verified)
 	})
 
 	t.Run("Test Get Manifest By ID", func(tt *testing.T) {
@@ -103,7 +109,7 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		w := httptest.NewRecorder()
 
@@ -185,7 +191,7 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, manifestService := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		w := httptest.NewRecorder()
 
@@ -234,6 +240,14 @@ func TestManifestAPI(t *testing.T) {
 		assert.NotEmpty(tt, getManifestsResp)
 		assert.Len(tt, getManifestsResp.Manifests, 1)
 		assert.Equal(tt, resp.Manifest.ID, getManifestsResp.Manifests[0].ID)
+
+		// verify each manifest
+		for _, m := range getManifestsResp.Manifests {
+			verificationResponse, err := manifestService.VerifyManifest(manifestsvc.VerifyManifestRequest{ManifestJWT: m.ManifestJWT})
+			assert.NoError(tt, err)
+			assert.NotEmpty(tt, verificationResponse)
+			assert.True(tt, verificationResponse.Verified)
+		}
 	})
 
 	t.Run("Test Delete Manifest", func(tt *testing.T) {
@@ -250,7 +264,7 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		// create an issuer
 		issuerDID, err := didService.CreateDIDByMethod(did.CreateDIDRequest{
@@ -330,7 +344,7 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		// missing required field: Application
 		badManifestRequest := router.SubmitApplicationRequest{
@@ -434,7 +448,7 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 		w := httptest.NewRecorder()
 
 		// get a application that doesn't exit
@@ -573,7 +587,7 @@ func TestManifestAPI(t *testing.T) {
 		didService := testDIDService(tt, bolt, keyStoreService)
 		schemaService := testSchemaService(tt, bolt, keyStoreService, didService)
 		credentialService := testCredentialService(tt, bolt, keyStoreService, didService, schemaService)
-		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, credentialService)
+		manifestRouter, _ := testManifest(tt, bolt, keyStoreService, didService, credentialService)
 
 		w := httptest.NewRecorder()
 
diff --git a/pkg/server/server_test.go b/pkg/server/server_test.go
index 9c71604..1bbb9f2 100644
--- a/pkg/server/server_test.go
+++ b/pkg/server/server_test.go
@@ -275,10 +275,10 @@ func testCredentialRouter(t *testing.T, bolt *storage.BoltDB, keyStore *keystore
 	return credentialRouter
 }
 
-func testManifest(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, credential *credential.Service) (*router.ManifestRouter, *manifest.Service) {
+func testManifest(t *testing.T, db *storage.BoltDB, keyStore *keystore.Service, did *did.Service, credential *credential.Service) (*router.ManifestRouter, *manifest.Service) {
 	serviceConfig := config.ManifestServiceConfig{BaseServiceConfig: &config.BaseServiceConfig{Name: "manifest"}}
 	// create a manifest service
-	manifestService, err := manifest.NewManifestService(serviceConfig, db, keyStore, credential)
+	manifestService, err := manifest.NewManifestService(serviceConfig, db, keyStore, did.GetResolver(), credential)
 	require.NoError(t, err)
 	require.NotEmpty(t, manifestService)