Skip to content

Commit

Permalink
Add canonical ID when applying patch changes to a did doc
Browse files Browse the repository at this point in the history
  • Loading branch information
andresuribe87 committed Jul 28, 2023
1 parent 992b1fb commit d50c25c
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 12 deletions.
15 changes: 13 additions & 2 deletions credential/integrity/signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package integrity

import (
"context"
"net/http"
"testing"
"time"

"github.com/TBD54566975/ssi-sdk/credential"
"github.com/TBD54566975/ssi-sdk/did/ion"
"github.com/goccy/go-json"

"github.com/TBD54566975/ssi-sdk/crypto"
Expand Down Expand Up @@ -79,8 +81,8 @@ func TestVerifyCredentialSignature(t *testing.T) {
resolver, err := resolution.NewResolver([]resolution.Resolver{key.Resolver{}}...)
assert.NoError(tt, err)

credential := getTestCredential()
credBytes, err := json.Marshal(credential)
testCred := getTestCredential()
credBytes, err := json.Marshal(testCred)
assert.NoError(tt, err)
_, err = VerifyCredentialSignature(context.Background(), credBytes, resolver)
assert.Error(tt, err)
Expand Down Expand Up @@ -224,6 +226,15 @@ func TestVerifyJWTCredential(t *testing.T) {
assert.NoError(tt, err)
assert.True(tt, verified)
})

t.Run("valid credential with long form ion did", func(t *testing.T) {
resolver, err := ion.NewIONResolver(http.DefaultClient, "https://ion.example.com")
assert.NoError(t, err)
const jwtCred = `eyJhbGciOiJFUzI1NksiLCJraWQiOiJkaWQ6aW9uOkVpQmp6ZUtpVzdXU3lqRUdtai1Jc3NlZDVoTWVmbU0yX0h3eWJLN2RTckRfWEE6ZXlKa1pXeDBZU0k2ZXlKd1lYUmphR1Z6SWpwYmV5SmhZM1JwYjI0aU9pSnlaWEJzWVdObElpd2laRzlqZFcxbGJuUWlPbnNpY0hWaWJHbGpTMlY1Y3lJNlczc2lhV1FpT2lKemFXZGZNalF6T0dOaU1tUWlMQ0p3ZFdKc2FXTkxaWGxLZDJzaU9uc2lZM0oySWpvaWMyVmpjREkxTm1zeElpd2lhM1I1SWpvaVJVTWlMQ0o0SWpvaVZFUkdVbWxPVTNkR2NHMTBjVFZYWDNrNVJIaG9NRGgwWlVKNlNGWkxWemxEYW5kMVJIUjVObGxKVlNJc0lua2lPaUpmVjNjMWNEUldjRVJvYkRGMmFVNUplVXRmTTFkVmJqVmlkSEowT0dWcmVqWm5OMHBIV1VaVVVVWTRJbjBzSW5CMWNuQnZjMlZ6SWpwYkltRjFkR2hsYm5ScFkyRjBhVzl1SWl3aVlYTnpaWEowYVc5dVRXVjBhRzlrSWwwc0luUjVjR1VpT2lKRlkyUnpZVk5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGtpZlYwc0luTmxjblpwWTJWeklqcGJleUpwWkNJNklteHBibXRsWkdSdmJXRnBibk1pTENKelpYSjJhV05sUlc1a2NHOXBiblFpT25zaWIzSnBaMmx1Y3lJNld5Sm9kSFJ3Y3pvdkwyeHBibXRsWkdsdUxtTnZiUzhpWFgwc0luUjVjR1VpT2lKTWFXNXJaV1JFYjIxaGFXNXpJbjBzZXlKcFpDSTZJbWgxWWlJc0luTmxjblpwWTJWRmJtUndiMmx1ZENJNmV5SnBibk4wWVc1alpYTWlPbHNpYUhSMGNITTZMeTlpWlhSaExtaDFZaTV0YzJsa1pXNTBhWFI1TG1OdmJTOTJNUzR3THpVNE9XUTFNMkkxTFdSbFpqVXROREl6TlMxaU5qUXlMVGhsTVdNME1XVTRZbU5oTVNKZGZTd2lkSGx3WlNJNklrbGtaVzUwYVhSNVNIVmlJbjFkZlgxZExDSjFjR1JoZEdWRGIyMXRhWFJ0Wlc1MElqb2lSV2xCYlRVdGFFNXRWbmhTVVZkT1ptMTNRelpXTVRaaE4wYzNTbTVyVHpNNGFVZFVVRlkyTjNGNFEzTkRkeUo5TENKemRXWm1hWGhFWVhSaElqcDdJbVJsYkhSaFNHRnphQ0k2SWtWcFFqRlBRa2huYWt0amFrcGtMVkZRZWkxUllXWlFibGRCZW1SdWNtaDVXVkIyVUVsZlZuSnpUbTVYZDBFaUxDSnlaV052ZG1WeWVVTnZiVzFwZEcxbGJuUWlPaUpGYVVNMk5uTllTR1ZHTWtseWRuaElTM3BDY1dWRVRHd3pWRU5TUzJwVlpFSnNkbVJmYmtaS01GcDNZVFJuSW4xOSNzaWdfMjQzOGNiMmQifQ.eyJzdWIiOiJkaWQ6aW9uOkVpQmp6ZUtpVzdXU3lqRUdtai1Jc3NlZDVoTWVmbU0yX0h3eWJLN2RTckRfWEE6ZXlKa1pXeDBZU0k2ZXlKd1lYUmphR1Z6SWpwYmV5SmhZM1JwYjI0aU9pSnlaWEJzWVdObElpd2laRzlqZFcxbGJuUWlPbnNpY0hWaWJHbGpTMlY1Y3lJNlczc2lhV1FpT2lKemFXZGZNalF6T0dOaU1tUWlMQ0p3ZFdKc2FXTkxaWGxLZDJzaU9uc2lZM0oySWpvaWMyVmpjREkxTm1zeElpd2lhM1I1SWpvaVJVTWlMQ0o0SWpvaVZFUkdVbWxPVTNkR2NHMTBjVFZYWDNrNVJIaG9NRGgwWlVKNlNGWkxWemxEYW5kMVJIUjVObGxKVlNJc0lua2lPaUpmVjNjMWNEUldjRVJvYkRGMmFVNUplVXRmTTFkVmJqVmlkSEowT0dWcmVqWm5OMHBIV1VaVVVVWTRJbjBzSW5CMWNuQnZjMlZ6SWpwYkltRjFkR2hsYm5ScFkyRjBhVzl1SWl3aVlYTnpaWEowYVc5dVRXVjBhRzlrSWwwc0luUjVjR1VpT2lKRlkyUnpZVk5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGtpZlYwc0luTmxjblpwWTJWeklqcGJleUpwWkNJNklteHBibXRsWkdSdmJXRnBibk1pTENKelpYSjJhV05sUlc1a2NHOXBiblFpT25zaWIzSnBaMmx1Y3lJNld5Sm9kSFJ3Y3pvdkwyeHBibXRsWkdsdUxtTnZiUzhpWFgwc0luUjVjR1VpT2lKTWFXNXJaV1JFYjIxaGFXNXpJbjBzZXlKcFpDSTZJbWgxWWlJc0luTmxjblpwWTJWRmJtUndiMmx1ZENJNmV5SnBibk4wWVc1alpYTWlPbHNpYUhSMGNITTZMeTlpWlhSaExtaDFZaTV0YzJsa1pXNTBhWFI1TG1OdmJTOTJNUzR3THpVNE9XUTFNMkkxTFdSbFpqVXROREl6TlMxaU5qUXlMVGhsTVdNME1XVTRZbU5oTVNKZGZTd2lkSGx3WlNJNklrbGtaVzUwYVhSNVNIVmlJbjFkZlgxZExDSjFjR1JoZEdWRGIyMXRhWFJ0Wlc1MElqb2lSV2xCYlRVdGFFNXRWbmhTVVZkT1ptMTNRelpXTVRaaE4wYzNTbTVyVHpNNGFVZFVVRlkyTjNGNFEzTkRkeUo5TENKemRXWm1hWGhFWVhSaElqcDdJbVJsYkhSaFNHRnphQ0k2SWtWcFFqRlBRa2huYWt0amFrcGtMVkZRZWkxUllXWlFibGRCZW1SdWNtaDVXVkIyVUVsZlZuSnpUbTVYZDBFaUxDSnlaV052ZG1WeWVVTnZiVzFwZEcxbGJuUWlPaUpGYVVNMk5uTllTR1ZHTWtseWRuaElTM3BDY1dWRVRHd3pWRU5TUzJwVlpFSnNkbVJmYmtaS01GcDNZVFJuSW4xOSIsImlzcyI6ImRpZDppb246RWlCanplS2lXN1dTeWpFR21qLUlzc2VkNWhNZWZtTTJfSHd5Yks3ZFNyRF9YQTpleUprWld4MFlTSTZleUp3WVhSamFHVnpJanBiZXlKaFkzUnBiMjRpT2lKeVpYQnNZV05sSWl3aVpHOWpkVzFsYm5RaU9uc2ljSFZpYkdsalMyVjVjeUk2VzNzaWFXUWlPaUp6YVdkZk1qUXpPR05pTW1RaUxDSndkV0pzYVdOTFpYbEtkMnNpT25zaVkzSjJJam9pYzJWamNESTFObXN4SWl3aWEzUjVJam9pUlVNaUxDSjRJam9pVkVSR1VtbE9VM2RHY0cxMGNUVlhYM2s1Ukhob01EaDBaVUo2U0ZaTFZ6bERhbmQxUkhSNU5sbEpWU0lzSW5raU9pSmZWM2MxY0RSV2NFUm9iREYyYVU1SmVVdGZNMWRWYmpWaWRISjBPR1ZyZWpabk4wcEhXVVpVVVVZNEluMHNJbkIxY25CdmMyVnpJanBiSW1GMWRHaGxiblJwWTJGMGFXOXVJaXdpWVhOelpYSjBhVzl1VFdWMGFHOWtJbDBzSW5SNWNHVWlPaUpGWTJSellWTmxZM0F5TlRack1WWmxjbWxtYVdOaGRHbHZia3RsZVRJd01Ua2lmVjBzSW5ObGNuWnBZMlZ6SWpwYmV5SnBaQ0k2SW14cGJtdGxaR1J2YldGcGJuTWlMQ0p6WlhKMmFXTmxSVzVrY0c5cGJuUWlPbnNpYjNKcFoybHVjeUk2V3lKb2RIUndjem92TDJ4cGJtdGxaR2x1TG1OdmJTOGlYWDBzSW5SNWNHVWlPaUpNYVc1clpXUkViMjFoYVc1ekluMHNleUpwWkNJNkltaDFZaUlzSW5ObGNuWnBZMlZGYm1Sd2IybHVkQ0k2ZXlKcGJuTjBZVzVqWlhNaU9sc2lhSFIwY0hNNkx5OWlaWFJoTG1oMVlpNXRjMmxrWlc1MGFYUjVMbU52YlM5Mk1TNHdMelU0T1dRMU0ySTFMV1JsWmpVdE5ESXpOUzFpTmpReUxUaGxNV00wTVdVNFltTmhNU0pkZlN3aWRIbHdaU0k2SWtsa1pXNTBhWFI1U0hWaUluMWRmWDFkTENKMWNHUmhkR1ZEYjIxdGFYUnRaVzUwSWpvaVJXbEJiVFV0YUU1dFZuaFNVVmRPWm0xM1F6WldNVFpoTjBjM1NtNXJUek00YVVkVVVGWTJOM0Y0UTNORGR5SjlMQ0p6ZFdabWFYaEVZWFJoSWpwN0ltUmxiSFJoU0dGemFDSTZJa1ZwUWpGUFFraG5ha3RqYWtwa0xWRlFlaTFSWVdaUWJsZEJlbVJ1Y21oNVdWQjJVRWxmVm5KelRtNVhkMEVpTENKeVpXTnZkbVZ5ZVVOdmJXMXBkRzFsYm5RaU9pSkZhVU0yTm5OWVNHVkdNa2x5ZG5oSVMzcENjV1ZFVEd3elZFTlNTMnBWWkVKc2RtUmZia1pLTUZwM1lUUm5JbjE5IiwibmJmIjoxNjQ5Mjg2NzM3LCJleHAiOjI0MzgyMDUxMzcsInZjIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIiwiaHR0cHM6Ly9pZGVudGl0eS5mb3VuZGF0aW9uLy53ZWxsLWtub3duL2NvbnRleHRzL2RpZC1jb25maWd1cmF0aW9uLXYwLjAuanNvbmxkIl0sImlzc3VlciI6ImRpZDppb246RWlCanplS2lXN1dTeWpFR21qLUlzc2VkNWhNZWZtTTJfSHd5Yks3ZFNyRF9YQTpleUprWld4MFlTSTZleUp3WVhSamFHVnpJanBiZXlKaFkzUnBiMjRpT2lKeVpYQnNZV05sSWl3aVpHOWpkVzFsYm5RaU9uc2ljSFZpYkdsalMyVjVjeUk2VzNzaWFXUWlPaUp6YVdkZk1qUXpPR05pTW1RaUxDSndkV0pzYVdOTFpYbEtkMnNpT25zaVkzSjJJam9pYzJWamNESTFObXN4SWl3aWEzUjVJam9pUlVNaUxDSjRJam9pVkVSR1VtbE9VM2RHY0cxMGNUVlhYM2s1Ukhob01EaDBaVUo2U0ZaTFZ6bERhbmQxUkhSNU5sbEpWU0lzSW5raU9pSmZWM2MxY0RSV2NFUm9iREYyYVU1SmVVdGZNMWRWYmpWaWRISjBPR1ZyZWpabk4wcEhXVVpVVVVZNEluMHNJbkIxY25CdmMyVnpJanBiSW1GMWRHaGxiblJwWTJGMGFXOXVJaXdpWVhOelpYSjBhVzl1VFdWMGFHOWtJbDBzSW5SNWNHVWlPaUpGWTJSellWTmxZM0F5TlRack1WWmxjbWxtYVdOaGRHbHZia3RsZVRJd01Ua2lmVjBzSW5ObGNuWnBZMlZ6SWpwYmV5SnBaQ0k2SW14cGJtdGxaR1J2YldGcGJuTWlMQ0p6WlhKMmFXTmxSVzVrY0c5cGJuUWlPbnNpYjNKcFoybHVjeUk2V3lKb2RIUndjem92TDJ4cGJtdGxaR2x1TG1OdmJTOGlYWDBzSW5SNWNHVWlPaUpNYVc1clpXUkViMjFoYVc1ekluMHNleUpwWkNJNkltaDFZaUlzSW5ObGNuWnBZMlZGYm1Sd2IybHVkQ0k2ZXlKcGJuTjBZVzVqWlhNaU9sc2lhSFIwY0hNNkx5OWlaWFJoTG1oMVlpNXRjMmxrWlc1MGFYUjVMbU52YlM5Mk1TNHdMelU0T1dRMU0ySTFMV1JsWmpVdE5ESXpOUzFpTmpReUxUaGxNV00wTVdVNFltTmhNU0pkZlN3aWRIbHdaU0k2SWtsa1pXNTBhWFI1U0hWaUluMWRmWDFkTENKMWNHUmhkR1ZEYjIxdGFYUnRaVzUwSWpvaVJXbEJiVFV0YUU1dFZuaFNVVmRPWm0xM1F6WldNVFpoTjBjM1NtNXJUek00YVVkVVVGWTJOM0Y0UTNORGR5SjlMQ0p6ZFdabWFYaEVZWFJoSWpwN0ltUmxiSFJoU0dGemFDSTZJa1ZwUWpGUFFraG5ha3RqYWtwa0xWRlFlaTFSWVdaUWJsZEJlbVJ1Y21oNVdWQjJVRWxmVm5KelRtNVhkMEVpTENKeVpXTnZkbVZ5ZVVOdmJXMXBkRzFsYm5RaU9pSkZhVU0yTm5OWVNHVkdNa2x5ZG5oSVMzcENjV1ZFVEd3elZFTlNTMnBWWkVKc2RtUmZia1pLTUZwM1lUUm5JbjE5IiwiaXNzdWFuY2VEYXRlIjoiMjAyMi0wNC0wNlQyMzoxMjoxNy44MzVaIiwiZXhwaXJhdGlvbkRhdGUiOiIyMDQ3LTA0LTA2VDIzOjEyOjE3LjgzNVoiLCJ0eXBlIjpbIlZlcmlmaWFibGVDcmVkZW50aWFsIiwiRG9tYWluTGlua2FnZUNyZWRlbnRpYWwiXSwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6aW9uOkVpQmp6ZUtpVzdXU3lqRUdtai1Jc3NlZDVoTWVmbU0yX0h3eWJLN2RTckRfWEE6ZXlKa1pXeDBZU0k2ZXlKd1lYUmphR1Z6SWpwYmV5SmhZM1JwYjI0aU9pSnlaWEJzWVdObElpd2laRzlqZFcxbGJuUWlPbnNpY0hWaWJHbGpTMlY1Y3lJNlczc2lhV1FpT2lKemFXZGZNalF6T0dOaU1tUWlMQ0p3ZFdKc2FXTkxaWGxLZDJzaU9uc2lZM0oySWpvaWMyVmpjREkxTm1zeElpd2lhM1I1SWpvaVJVTWlMQ0o0SWpvaVZFUkdVbWxPVTNkR2NHMTBjVFZYWDNrNVJIaG9NRGgwWlVKNlNGWkxWemxEYW5kMVJIUjVObGxKVlNJc0lua2lPaUpmVjNjMWNEUldjRVJvYkRGMmFVNUplVXRmTTFkVmJqVmlkSEowT0dWcmVqWm5OMHBIV1VaVVVVWTRJbjBzSW5CMWNuQnZjMlZ6SWpwYkltRjFkR2hsYm5ScFkyRjBhVzl1SWl3aVlYTnpaWEowYVc5dVRXVjBhRzlrSWwwc0luUjVjR1VpT2lKRlkyUnpZVk5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGtpZlYwc0luTmxjblpwWTJWeklqcGJleUpwWkNJNklteHBibXRsWkdSdmJXRnBibk1pTENKelpYSjJhV05sUlc1a2NHOXBiblFpT25zaWIzSnBaMmx1Y3lJNld5Sm9kSFJ3Y3pvdkwyeHBibXRsWkdsdUxtTnZiUzhpWFgwc0luUjVjR1VpT2lKTWFXNXJaV1JFYjIxaGFXNXpJbjBzZXlKcFpDSTZJbWgxWWlJc0luTmxjblpwWTJWRmJtUndiMmx1ZENJNmV5SnBibk4wWVc1alpYTWlPbHNpYUhSMGNITTZMeTlpWlhSaExtaDFZaTV0YzJsa1pXNTBhWFI1TG1OdmJTOTJNUzR3THpVNE9XUTFNMkkxTFdSbFpqVXROREl6TlMxaU5qUXlMVGhsTVdNME1XVTRZbU5oTVNKZGZTd2lkSGx3WlNJNklrbGtaVzUwYVhSNVNIVmlJbjFkZlgxZExDSjFjR1JoZEdWRGIyMXRhWFJ0Wlc1MElqb2lSV2xCYlRVdGFFNXRWbmhTVVZkT1ptMTNRelpXTVRaaE4wYzNTbTVyVHpNNGFVZFVVRlkyTjNGNFEzTkRkeUo5TENKemRXWm1hWGhFWVhSaElqcDdJbVJsYkhSaFNHRnphQ0k2SWtWcFFqRlBRa2huYWt0amFrcGtMVkZRZWkxUllXWlFibGRCZW1SdWNtaDVXVkIyVUVsZlZuSnpUbTVYZDBFaUxDSnlaV052ZG1WeWVVTnZiVzFwZEcxbGJuUWlPaUpGYVVNMk5uTllTR1ZHTWtseWRuaElTM3BDY1dWRVRHd3pWRU5TUzJwVlpFSnNkbVJmYmtaS01GcDNZVFJuSW4xOSIsIm9yaWdpbiI6Imh0dHBzOi8vd3d3LmxpbmtlZGluLmNvbS8ifX19.oTFcVvKmYU1Mxh9Q4V5UNikddYANLjw-m3530PNDhFYmR1Dm8DOcjdU-p2rJ6vSZnUKatXV5VJLJxj1aJyuhlw`
verified, err := VerifyJWTCredential(context.Background(), jwtCred, resolver)
assert.NoError(t, err)
assert.True(t, verified)
})
}

func getTestJWTCredential(t *testing.T, signer jwx.Signer) string {
Expand Down
27 changes: 22 additions & 5 deletions did/ion/did.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,24 @@ func PatchesToDIDDocument(shortFormDID, longFormDID string, patches []Patch) (*d
return nil, errors.New("short form DID is required")
}
doc := did.Document{
Context: []string{"https://www.w3.org/ns/did/v1"},
ID: shortFormDID,
AlsoKnownAs: longFormDID,
Context: []any{"https://www.w3.org/ns/did/v1", map[string]any{
"@base": longFormDID,
}},
ID: longFormDID,
}
for _, patch := range patches {
switch patch.GetAction() {
case AddServices:
addServicePatch := patch.(AddServicesAction)
doc.Services = append(doc.Services, addServicePatch.Services...)
for _, s := range addServicePatch.Services {
s := s
s.ID = canonicalID(s.ID)
doc.Services = append(doc.Services, s)
}
case RemoveServices:
removeServicePatch := patch.(RemoveServicesAction)
for _, id := range removeServicePatch.IDs {
id := canonicalID(id)
for i, service := range doc.Services {
if service.ID == id {
doc.Services = append(doc.Services[:i], doc.Services[i+1:]...)
Expand Down Expand Up @@ -180,14 +186,17 @@ func replaceActionPatch(doc did.Document, patch ReplaceAction) (*did.Document, e
}
doc = *gotDoc
for _, service := range patch.Document.Services {
doc.Services = append(doc.Services, service)
s := service
s.ID = canonicalID(s.ID)
doc.Services = append(doc.Services, s)
}
return &doc, nil
}

func addPublicKeysPatch(doc did.Document, patch AddPublicKeysAction) (*did.Document, error) {
for _, key := range patch.PublicKeys {
currKey := key
currKey.ID = canonicalID(currKey.ID)
doc.VerificationMethod = append(doc.VerificationMethod, did.VerificationMethod{
ID: currKey.ID,
Type: cryptosuite.LDKeyType(currKey.Type),
Expand All @@ -214,8 +223,16 @@ func addPublicKeysPatch(doc did.Document, patch AddPublicKeysAction) (*did.Docum
return &doc, nil
}

func canonicalID(id string) string {
if strings.Contains(id, "#") {
return id
}
return "#" + id
}

func removePublicKeysPatch(doc did.Document, patch RemovePublicKeysAction) (*did.Document, error) {
for _, id := range patch.IDs {
id := canonicalID(id)
removed := false
for i, key := range doc.VerificationMethod {
if key.ID != id {
Expand Down
64 changes: 64 additions & 0 deletions did/ion/did_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,77 @@
package ion

import (
"context"
"net/http"
"testing"

"github.com/TBD54566975/ssi-sdk/crypto/jwx"
"github.com/TBD54566975/ssi-sdk/did"
"github.com/goccy/go-json"
"github.com/stretchr/testify/assert"
)

// Test vector from https://identity.foundation/sidetree/spec/#long-form-response, adjusted by replacing s/sidetree/ion/
func TestResolveLongFormDID(t *testing.T) {
longFormDID := `did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJwdWJsaWNLZXlNb2RlbDFJZCIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJ0WFNLQl9ydWJYUzdzQ2pYcXVwVkpFelRjVzNNc2ptRXZxMVlwWG45NlpnIiwieSI6ImRPaWNYcWJqRnhvR0otSzAtR0oxa0hZSnFpY19EX09NdVV3a1E3T2w2bmsifSwicHVycG9zZXMiOlsiYXV0aGVudGljYXRpb24iLCJrZXlBZ3JlZW1lbnQiXSwidHlwZSI6IkVjZHNhU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOSJ9XSwic2VydmljZXMiOlt7ImlkIjoic2VydmljZTFJZCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly93d3cuc2VydmljZTEuY29tIiwidHlwZSI6InNlcnZpY2UxVHlwZSJ9XX19XSwidXBkYXRlQ29tbWl0bWVudCI6IkVpREtJa3dxTzY5SVBHM3BPbEhrZGI4Nm5ZdDBhTnhTSFp1MnItYmhFem5qZEEifSwic3VmZml4RGF0YSI6eyJkZWx0YUhhc2giOiJFaUNmRFdSbllsY0Q5RUdBM2RfNVoxQUh1LWlZcU1iSjluZmlxZHo1UzhWRGJnIiwicmVjb3ZlcnlDb21taXRtZW50IjoiRWlCZk9aZE10VTZPQnc4UGs4NzlRdFotMkotOUZiYmpTWnlvYUFfYnFENHpoQSJ9fQ`
resolver, err := NewIONResolver(http.DefaultClient, "https://example.com")
assert.NoError(t, err)

resolutionResult, err := resolver.Resolve(context.Background(), longFormDID)
assert.NoError(t, err)

jsonResolutionResult, err := json.Marshal(resolutionResult)
assert.NoError(t, err)

expectedResolutionResultJSON := `{
"@context": "https://w3id.org/did-resolution/v1",
"didDocument": {
"id": "did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJwdWJsaWNLZXlNb2RlbDFJZCIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJ0WFNLQl9ydWJYUzdzQ2pYcXVwVkpFelRjVzNNc2ptRXZxMVlwWG45NlpnIiwieSI6ImRPaWNYcWJqRnhvR0otSzAtR0oxa0hZSnFpY19EX09NdVV3a1E3T2w2bmsifSwicHVycG9zZXMiOlsiYXV0aGVudGljYXRpb24iLCJrZXlBZ3JlZW1lbnQiXSwidHlwZSI6IkVjZHNhU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOSJ9XSwic2VydmljZXMiOlt7ImlkIjoic2VydmljZTFJZCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly93d3cuc2VydmljZTEuY29tIiwidHlwZSI6InNlcnZpY2UxVHlwZSJ9XX19XSwidXBkYXRlQ29tbWl0bWVudCI6IkVpREtJa3dxTzY5SVBHM3BPbEhrZGI4Nm5ZdDBhTnhTSFp1MnItYmhFem5qZEEifSwic3VmZml4RGF0YSI6eyJkZWx0YUhhc2giOiJFaUNmRFdSbllsY0Q5RUdBM2RfNVoxQUh1LWlZcU1iSjluZmlxZHo1UzhWRGJnIiwicmVjb3ZlcnlDb21taXRtZW50IjoiRWlCZk9aZE10VTZPQnc4UGs4NzlRdFotMkotOUZiYmpTWnlvYUFfYnFENHpoQSJ9fQ",
"@context": [
"https://www.w3.org/ns/did/v1",
{
"@base": "did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJwdWJsaWNLZXlNb2RlbDFJZCIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJ0WFNLQl9ydWJYUzdzQ2pYcXVwVkpFelRjVzNNc2ptRXZxMVlwWG45NlpnIiwieSI6ImRPaWNYcWJqRnhvR0otSzAtR0oxa0hZSnFpY19EX09NdVV3a1E3T2w2bmsifSwicHVycG9zZXMiOlsiYXV0aGVudGljYXRpb24iLCJrZXlBZ3JlZW1lbnQiXSwidHlwZSI6IkVjZHNhU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOSJ9XSwic2VydmljZXMiOlt7ImlkIjoic2VydmljZTFJZCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly93d3cuc2VydmljZTEuY29tIiwidHlwZSI6InNlcnZpY2UxVHlwZSJ9XX19XSwidXBkYXRlQ29tbWl0bWVudCI6IkVpREtJa3dxTzY5SVBHM3BPbEhrZGI4Nm5ZdDBhTnhTSFp1MnItYmhFem5qZEEifSwic3VmZml4RGF0YSI6eyJkZWx0YUhhc2giOiJFaUNmRFdSbllsY0Q5RUdBM2RfNVoxQUh1LWlZcU1iSjluZmlxZHo1UzhWRGJnIiwicmVjb3ZlcnlDb21taXRtZW50IjoiRWlCZk9aZE10VTZPQnc4UGs4NzlRdFotMkotOUZiYmpTWnlvYUFfYnFENHpoQSJ9fQ"
}
],
"service": [
{
"id": "#service1Id",
"type": "service1Type",
"serviceEndpoint": "http://www.service1.com"
}
],
"verificationMethod": [
{
"id": "#publicKeyModel1Id",
"controller": "did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJwdWJsaWNLZXlNb2RlbDFJZCIsInB1YmxpY0tleUp3ayI6eyJjcnYiOiJzZWNwMjU2azEiLCJrdHkiOiJFQyIsIngiOiJ0WFNLQl9ydWJYUzdzQ2pYcXVwVkpFelRjVzNNc2ptRXZxMVlwWG45NlpnIiwieSI6ImRPaWNYcWJqRnhvR0otSzAtR0oxa0hZSnFpY19EX09NdVV3a1E3T2w2bmsifSwicHVycG9zZXMiOlsiYXV0aGVudGljYXRpb24iLCJrZXlBZ3JlZW1lbnQiXSwidHlwZSI6IkVjZHNhU2VjcDI1NmsxVmVyaWZpY2F0aW9uS2V5MjAxOSJ9XSwic2VydmljZXMiOlt7ImlkIjoic2VydmljZTFJZCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly93d3cuc2VydmljZTEuY29tIiwidHlwZSI6InNlcnZpY2UxVHlwZSJ9XX19XSwidXBkYXRlQ29tbWl0bWVudCI6IkVpREtJa3dxTzY5SVBHM3BPbEhrZGI4Nm5ZdDBhTnhTSFp1MnItYmhFem5qZEEifSwic3VmZml4RGF0YSI6eyJkZWx0YUhhc2giOiJFaUNmRFdSbllsY0Q5RUdBM2RfNVoxQUh1LWlZcU1iSjluZmlxZHo1UzhWRGJnIiwicmVjb3ZlcnlDb21taXRtZW50IjoiRWlCZk9aZE10VTZPQnc4UGs4NzlRdFotMkotOUZiYmpTWnlvYUFfYnFENHpoQSJ9fQ",
"type": "EcdsaSecp256k1VerificationKey2019",
"publicKeyJwk": {
"crv": "secp256k1",
"kty": "EC",
"x": "tXSKB_rubXS7sCjXqupVJEzTcW3MsjmEvq1YpXn96Zg",
"y": "dOicXqbjFxoGJ-K0-GJ1kHYJqic_D_OMuUwkQ7Ol6nk"
}
}
],
"authentication": [
"#publicKeyModel1Id"
],
"keyAgreement": [
"#publicKeyModel1Id"
]
},
"didDocumentMetadata": {
"equivalentId": ["did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg"],
"method": {
"published": false,
"recoveryCommitment": "EiBfOZdMtU6OBw8Pk879QtZ-2J-9FbbjSZyoaA_bqD4zhA",
"updateCommitment": "EiDKIkwqO69IPG3pOlHkdb86nYt0aNxSHZu2r-bhEznjdA"
}
}
}`
assert.JSONEq(t, expectedResolutionResultJSON, string(jsonResolutionResult))
}

// https://github.com/decentralized-identity/ion-sdk/blob/main/tests/IonDid.spec.ts#L18
func TestCreateLongFormDID(t *testing.T) {
var recoveryKey jwx.PublicKeyJWK
Expand Down
3 changes: 1 addition & 2 deletions did/ion/operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,7 @@ func TestResolver(t *testing.T) {
result, err := resolver.Resolve(context.Background(), longFormDID, nil)
assert.NoError(ttt, err)
assert.NotEmpty(ttt, result)
assert.Equal(ttt, "did:ion:EiDyOQbbZAa3aiRzeCkV7LOx3SERjjH93EXoIM3UoN4oWg", result.Document.ID)
assert.Equal(ttt, longFormDID, result.Document.AlsoKnownAs)
assert.Equal(ttt, longFormDID, result.Document.ID)
})
})

Expand Down
19 changes: 16 additions & 3 deletions did/ion/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@ func (i Resolver) Resolve(ctx context.Context, id string, _ ...resolution.Option
if err != nil {
return nil, errors.Wrap(err, "reconstructing document from long form DID")
}
return &resolution.Result{Document: *didDoc}, nil
return &resolution.Result{
Context: "https://w3id.org/did-resolution/v1",
Document: *didDoc,
DocumentMetadata: resolution.DocumentMetadata{
EquivalentID: []string{shortFormDID},
Method: resolution.Method{
Published: false,
RecoveryCommitment: initialState.SuffixData.RecoveryCommitment,
UpdateCommitment: initialState.Delta.UpdateCommitment},
}}, nil
}

if i.baseURL.String() == "" {
Expand All @@ -79,7 +88,9 @@ func (i Resolver) Resolve(ctx context.Context, id string, _ ...resolution.Option
return nil, errors.Wrapf(err, "resolving, with URL: %s", i.baseURL.String())
}

defer resp.Body.Close()
defer func() {
_ = resp.Body.Close()
}()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrapf(err, "resolving, with response %+v", resp)
Expand Down Expand Up @@ -114,7 +125,9 @@ func (i Resolver) Anchor(ctx context.Context, op AnchorOperation) (*resolution.R
return nil, errors.Wrapf(err, "posting anchor operation %+v", op)
}

defer resp.Body.Close()
defer func() {
_ = resp.Body.Close()
}()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrapf(err, "could not resolve with response %+v", resp)
Expand Down

0 comments on commit d50c25c

Please sign in to comment.