Skip to content

Commit

Permalink
feat(prism-agent): add universal-resolver compatible endpoint (#455)
Browse files Browse the repository at this point in the history
* feat(prism-agent): add new endpoint def

* new uni resolver endpoknt

* add buildResolutionResp to DIDApiServiceImpl

* add contentType to ResolutionMetadata

* pr cleanup

* docs: improve OAS doc on the response

* docs: correct the content-type header in OAS

* fix(prism-agent): unify resolution endpoint

* fix e2e tests
  • Loading branch information
patlo-iog authored Mar 22, 2023
1 parent 6808996 commit 1cbb729
Show file tree
Hide file tree
Showing 14 changed files with 295 additions and 115 deletions.
18 changes: 18 additions & 0 deletions prism-agent/service/api/http/castor/parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,21 @@ components:
schema:
type: string
example: did:prism:4a5b5cf0a513e83b598bbea25cd6196746747f361a73ef77068268bc9bd732ff
resolutionAcceptOption:
in: header
name: Accept
require: false
description: |
Represents [accept resolution option](https://www.w3.org/TR/did-core/#did-resolution-options).
For [DID resolution result](https://w3c-ccg.github.io/did-resolution/#did-resolution-result), `application/ld+json;profile="https://w3id.org/did-resolution"` can be used.
For [DID document representation](https://www.w3.org/TR/did-core/#representations), `application/<format>` can be used.
Default to `application/ld+json;profile="https://w3id.org/did-resolution"` if not specified.
schema:
type: string
enum:
- application/did+ld+json
- application/ld+json;profile="https://w3id.org/did-resolution"
example: application/ld+json;profile="https://w3id.org/did-resolution"
91 changes: 48 additions & 43 deletions prism-agent/service/api/http/castor/schemas.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
components:
schemas:
DIDResponse:
type: object
required:
- did
- metadata
properties:
did:
$ref: "#/components/schemas/DID"
metadata:
$ref: "#/components/schemas/DIDDocumentMetadata"

DIDOperationResponse:
type: object
required:
Expand All @@ -19,13 +8,35 @@ components:
scheduledOperation:
$ref: "#/components/schemas/DidOperationSubmission"

DID:
DIDResolutionResult:
type: object
description: |
A Prism DID document data model capable of being transformed into W3C compliant representation.
required:
- "@context"
- didDocumentMetadata
- didResolutionMetadata
properties:
"@context":
type: string
example: "https://w3id.org/did-resolution/v1"
didDocument:
$ref: "#/components/schemas/DIDDocument"
didDocumentMetadata:
$ref: "#/components/schemas/DIDDocumentMetadata"
didResolutionMetadata:
$ref: "#/components/schemas/DIDResolutionMetadata"

DIDDocument:
type: object
description: A W3C compliant Prism DID document representation.
required:
- "@context"
- id
properties:
"@context":
type: array
items:
type: string
example: "https://www.w3.org/ns/did/v1"
id:
type: string
description: |
Expand All @@ -44,23 +55,23 @@ components:
authentication:
type: array
items:
$ref: "#/components/schemas/VerificationMethodOrRef"
$ref: "#/components/schemas/VerificationMethodRef"
assertionMethod:
type: array
items:
$ref: "#/components/schemas/VerificationMethodOrRef"
$ref: "#/components/schemas/VerificationMethodRef"
keyAgreement:
type: array
items:
$ref: "#/components/schemas/VerificationMethodOrRef"
$ref: "#/components/schemas/VerificationMethodRef"
capabilityInvocation:
type: array
items:
$ref: "#/components/schemas/VerificationMethodOrRef"
$ref: "#/components/schemas/VerificationMethodRef"
capabilityDelegation:
type: array
items:
$ref: "#/components/schemas/VerificationMethodOrRef"
$ref: "#/components/schemas/VerificationMethodRef"
service:
type: array
items:
Expand All @@ -70,8 +81,6 @@ components:
type: object
description: |
[DID document metadata](https://www.w3.org/TR/did-core/#did-document-metadata)
required:
- deactivated
properties:
deactivated:
type: boolean
Expand All @@ -85,6 +94,20 @@ components:
If a DID in short form or has not been published, DID document metadata MUST NOT contain a `canonicalId` property.
DIDResolutionMetadata:
type: object
description: |
[DID resolution metadata](https://www.w3.org/TR/did-core/#did-resolution-metadata)
properties:
error:
type: string
description: Resolution error constant according to [DID spec registries](https://www.w3.org/TR/did-spec-registries/#error)
example: invalidDid
contentType:
type: string
description: The media type of the returned DID document
example: application/did+ld+json

VerificationMethod:
type: object
description: |
Expand All @@ -108,28 +131,10 @@ components:
publicKeyJwk:
$ref: "#/components/schemas/PublicKeyJwk"

VerificationMethodOrRef:
type: object
description: |
An embedded verificationMethod as JSON or a referenced key as a URI.
Referenced key and embedded key are mutually exclusive.
If the type is EMBEDDED, `uri` field must be present.
Otherwise `verificationMethod` field must be present.
required:
- type
properties:
type:
type: string
example: EMBEDDED
enum:
- EMBEDDED
- REFERENCED
uri:
type: string
example: did:prism:c7bd808e8e135236d7262ecf5e639b8f9d22bd886f59a4e6c909486846ca8319#key-1
verificationMethod:
$ref: "#/components/schemas/VerificationMethod"
VerificationMethodRef:
type: string
description: A reference to a `verificationMethod`
example: did:prism:c7bd808e8e135236d7262ecf5e639b8f9d22bd886f59a4e6c909486846ca8319#key-1

CreateManagedDidRequest:
type: object
Expand Down
57 changes: 46 additions & 11 deletions prism-agent/service/api/http/prism-agent-openapi-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,26 +43,61 @@ paths:
get:
operationId: getDid
tags: ["DID"]
summary: Resolve Prism DID
summary: Resolve Prism DID to a W3C representation
description: |
Resolve Prism DID to a DID document data model.
The returned DID document is not the W3C DID document representation, but a DID document data model.
However, this data model is capable of being transformed into the W3C compliant representation.
Resolve Prism DID to a W3C DID document representation.
The response can be the [DID resolution result](https://w3c-ccg.github.io/did-resolution/#did-resolution-result)
or [DID document representation](https://www.w3.org/TR/did-core/#representations) depending on the `Accept` request header.
The response is implemented according to [resolver HTTP binding](https://w3c-ccg.github.io/did-resolution/#bindings-https) in the DID resolution spec.
parameters:
- $ref: "./castor/parameters.yaml#/components/parameters/didRefInPath"
- $ref: "./castor/parameters.yaml#/components/parameters/resolutionAcceptOption"
responses:
"200":
description: The DID document data model
description: The resolution result or W3C DID document representation
content:
application/json:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"
application/did+ld+json:
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDDocument"
"400":
description: Invalid input
content:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResponse"
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"
"404":
$ref: "./shared/responses.yaml#/components/responses/NotFound"
"422":
$ref: "./shared/responses.yaml#/components/responses/UnprocessableEntity"
description: Not found
content:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"
"406":
description: Representation not supported
content:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"
"410":
description: DID Deactivated
content:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"
"500":
$ref: "./shared/responses.yaml#/components/responses/InternalServerError"
description: Internal error
content:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"
"501":
description: Method not supported
content:
application/ld+json;profile="https://w3id.org/did-resolution":
schema:
$ref: "./castor/schemas.yaml#/components/schemas/DIDResolutionResult"

/did-registrar/dids:
get:
Expand Down
4 changes: 2 additions & 2 deletions prism-agent/service/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ lazy val server = project
openApiGeneratorSpec := apiBaseDirectory.value / "http/prism-agent-openapi-spec.yaml",
openApiGeneratorConfig := baseDirectory.value / "openapi/generator-config/config.yaml",
openApiGeneratorImportMapping := Seq(
"DidOperationType",
"DidOperationStatus"
"DIDDocument",
"DIDResolutionResult"
)
.map(model =>
(model, s"io.iohk.atala.agent.server.http.model.OASModelPatches.$model")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ package io.iohk.atala.agent.server.http.marshaller
import akka.http.scaladsl.marshalling.ToEntityMarshaller
import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller
import io.iohk.atala.agent.openapi.api.DIDApiMarshaller
import io.iohk.atala.agent.openapi.model.{DIDOperationResponse, DIDResponse, ErrorResponse}
import io.iohk.atala.agent.openapi.model.{DIDOperationResponse, ErrorResponse}
import spray.json.RootJsonFormat
import zio.*
import io.iohk.atala.agent.server.http.model.OASModelPatches

object DIDApiMarshallerImpl extends JsonSupport {

val layer: ULayer[DIDApiMarshaller] = ZLayer.succeed {
new DIDApiMarshaller {
implicit def toEntityMarshallerDIDResponse: ToEntityMarshaller[DIDResponse] = summon[RootJsonFormat[DIDResponse]]

implicit def toEntityMarshallerErrorResponse: ToEntityMarshaller[ErrorResponse] =
summon[RootJsonFormat[ErrorResponse]]
implicit def toEntityMarshallerDIDResolutionResult: ToEntityMarshaller[OASModelPatches.DIDResolutionResult] =
summon[RootJsonFormat[OASModelPatches.DIDResolutionResult]]
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import spray.json.{

import java.util.UUID
import java.time.OffsetDateTime
import io.iohk.atala.agent.server.http.model.OASModelPatches

object JsonSupport extends JsonSupport

trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {

Expand All @@ -24,11 +27,10 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
CreateManagedDidRequestDocumentTemplate.apply
)
given RootJsonFormat[CreateManagedDIDResponse] = jsonFormat1(CreateManagedDIDResponse.apply)
given RootJsonFormat[DID] = jsonFormat9(DID.apply)
given RootJsonFormat[DIDDocumentMetadata] = jsonFormat2(DIDDocumentMetadata.apply)
given RootJsonFormat[DIDOperationResponse] = jsonFormat1(DIDOperationResponse.apply)
given RootJsonFormat[DidOperationSubmission] = jsonFormat2(DidOperationSubmission.apply)
given RootJsonFormat[DIDResponse] = jsonFormat2(DIDResponse.apply)
given RootJsonFormat[DIDResolutionMetadata] = jsonFormat2(DIDResolutionMetadata.apply)
given RootJsonFormat[ErrorResponse] = jsonFormat5(ErrorResponse.apply)
given RootJsonFormat[ManagedDID] = jsonFormat3(ManagedDID.apply)
given RootJsonFormat[ManagedDIDPage] = jsonFormat6(ManagedDIDPage.apply)
Expand All @@ -47,7 +49,6 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
UpdateManagedDIDRequestActionsInnerUpdateService.apply
)
given RootJsonFormat[VerificationMethod] = jsonFormat4(VerificationMethod.apply)
given RootJsonFormat[VerificationMethodOrRef] = jsonFormat3(VerificationMethodOrRef.apply)

// Issue Credential Protocol
implicit object UUIDFormat extends JsonFormat[UUID] {
Expand Down Expand Up @@ -90,4 +91,8 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
given RootJsonFormat[Connection] = jsonFormat11(Connection.apply)
given RootJsonFormat[ConnectionInvitation] = jsonFormat4(ConnectionInvitation.apply)

// Manual model patches
given RootJsonFormat[OASModelPatches.DIDDocument] = jsonFormat10(OASModelPatches.DIDDocument.apply)
given RootJsonFormat[OASModelPatches.DIDResolutionResult] = jsonFormat4(OASModelPatches.DIDResolutionResult.apply)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.iohk.atala.agent.server.http.model

import akka.http.scaladsl.model.MediaType
import akka.http.scaladsl.model.HttpCharsets

object CustomMediaTypes {

val `application/did+ld+json`: MediaType.WithFixedCharset =
MediaType.customWithFixedCharset("application", "did+ld+json", HttpCharsets.`UTF-8`)

val `application/ld+json;did-resolution`: MediaType.WithFixedCharset = MediaType.customWithFixedCharset(
"application",
"ld+json",
HttpCharsets.`UTF-8`,
params = Map("profile" -> "https://w3id.org/did-resolution")
)

}
Loading

0 comments on commit 1cbb729

Please sign in to comment.