github.com/hyperledger/aries-framework-go@v0.3.2/pkg/client/didconfig/didconfig.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package didconfig 8 9 import ( 10 "context" 11 "fmt" 12 "io" 13 "io/ioutil" 14 "net/http" 15 "time" 16 17 jsonld "github.com/piprate/json-gold/ld" 18 19 "github.com/hyperledger/aries-framework-go/pkg/common/log" 20 "github.com/hyperledger/aries-framework-go/pkg/doc/did" 21 "github.com/hyperledger/aries-framework-go/pkg/doc/didconfig" 22 vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 23 ) 24 25 var logger = log.New("aries-framework/client/did-config") 26 27 const defaultTimeout = time.Minute 28 29 // Client is a JSON-LD SDK client. 30 type Client struct { 31 httpClient HTTPClient 32 didConfigOpts []didconfig.DIDConfigurationOpt 33 } 34 35 // New creates new did configuration client. 36 func New(opts ...Option) *Client { 37 client := &Client{ 38 httpClient: &http.Client{Timeout: defaultTimeout}, 39 } 40 41 for _, opt := range opts { 42 opt(client) 43 } 44 45 return client 46 } 47 48 // HTTPClient represents an HTTP client. 49 type HTTPClient interface { 50 Do(req *http.Request) (*http.Response, error) 51 } 52 53 // Option configures the did configuration client. 54 type Option func(opts *Client) 55 56 // WithHTTPClient option is for custom http client. 57 func WithHTTPClient(httpClient HTTPClient) Option { 58 return func(opts *Client) { 59 opts.httpClient = httpClient 60 } 61 } 62 63 // WithJSONLDDocumentLoader defines a JSON-LD document loader. 64 func WithJSONLDDocumentLoader(documentLoader jsonld.DocumentLoader) Option { 65 return func(opts *Client) { 66 opts.didConfigOpts = append(opts.didConfigOpts, didconfig.WithJSONLDDocumentLoader(documentLoader)) 67 } 68 } 69 70 type didResolver interface { 71 Resolve(did string, opts ...vdrapi.DIDMethodOption) (*did.DocResolution, error) 72 } 73 74 // WithVDRegistry defines a vdr service. 75 func WithVDRegistry(didResolver didResolver) Option { 76 return func(opts *Client) { 77 opts.didConfigOpts = append(opts.didConfigOpts, didconfig.WithVDRegistry(didResolver)) 78 } 79 } 80 81 // VerifyDIDAndDomain will verify that there is valid domain linkage credential in did configuration 82 // for specified did and domain. 83 func (c *Client) VerifyDIDAndDomain(did, domain string) error { 84 endpoint := domain + "/.well-known/did-configuration.json" 85 86 req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, endpoint, nil) 87 if err != nil { 88 return fmt.Errorf("new HTTP request: %w", err) 89 } 90 91 resp, err := c.httpClient.Do(req) 92 if err != nil { 93 return fmt.Errorf("httpClient.Do: %w", err) 94 } 95 96 defer closeResponseBody(resp.Body) 97 98 responseBytes, err := ioutil.ReadAll(resp.Body) 99 if err != nil { 100 return fmt.Errorf("failed to read response: %w", err) 101 } 102 103 if resp.StatusCode != http.StatusOK { 104 return fmt.Errorf("endpoint %s returned status '%d' and message '%s'", 105 endpoint, resp.StatusCode, responseBytes) 106 } 107 108 return didconfig.VerifyDIDAndDomain(responseBytes, did, domain, c.didConfigOpts...) 109 } 110 111 func closeResponseBody(respBody io.Closer) { 112 e := respBody.Close() 113 if e != nil { 114 logger.Warnf("failed to close response body: %v", e) 115 } 116 }