diff --git a/codegen/configs/policy_client_v1.yaml b/codegen/configs/policy_client_v1.yaml
new file mode 100644
index 0000000000..5bd811ccf1
--- /dev/null
+++ b/codegen/configs/policy_client_v1.yaml
@@ -0,0 +1,11 @@
+package: client
+generate:
+ echo-server: false
+ client: true
+ models: true
+ strict-server: true
+output-options:
+ skip-prune: true
+ exclude-schemas:
+ - PresentationDefinition
+ - PresentationSubmission
diff --git a/docs/_static/policy/v1.yaml b/docs/_static/policy/v1.yaml
index 3c8bd90878..e221b36cef 100644
--- a/docs/_static/policy/v1.yaml
+++ b/docs/_static/policy/v1.yaml
@@ -5,10 +5,10 @@ info:
servers:
- url: "http://localhost:1323"
paths:
- /{did}/presentation_definition:
+ /presentation_definition:
parameters:
- - name: did
- in: path
+ - name: authorizer
+ in: query
description: URLEncoded DID.
required: true
example: did:web:example.com:1
@@ -52,7 +52,7 @@ paths:
When an access token is used to request a resource, the resource server needs to know if the access token grants access to the requested resource.
The resource server will send a request to the policy backend to check if the access token grants access to the requested resource.
All cryptographic and presentation exchange validations have already been done by the caller.
- operationId: "authorized"
+ operationId: "checkAuthorized"
tags:
- policy
requestBody:
@@ -104,7 +104,7 @@ components:
type: string
presentation_submission:
description: The presentation submission that was used to request the access token.
- type: object
+ $ref: '#/components/schemas/PresentationSubmission'
vps:
description: |
The verifiable presentations that were used to request the access token.
@@ -127,3 +127,8 @@ components:
A presentation definition is a JSON object that describes the desired verifiable credentials and presentation formats.
Specified at https://identity.foundation/presentation-exchange/spec/v2.0.0/
A JSON schema is available at https://identity.foundation/presentation-exchange/#json-schema
+ PresentationSubmission:
+ description: |
+ A presentation submission is a JSON object that maps requirements from the Presentation Definition to the verifiable presentations that were used to request an access token.
+ Specified at https://identity.foundation/presentation-exchange/spec/v2.0.0/
+ A JSON schema is available at https://identity.foundation/presentation-exchange/#json-schema
diff --git a/makefile b/makefile
index 6f6efae5be..31b5d65065 100644
--- a/makefile
+++ b/makefile
@@ -68,6 +68,7 @@ gen-api:
oapi-codegen --config codegen/configs/auth_iam.yaml docs/_static/auth/iam.yaml | gofmt > auth/api/iam/generated.go
oapi-codegen --config codegen/configs/didman_v1.yaml docs/_static/didman/v1.yaml | gofmt > didman/api/v1/generated.go
oapi-codegen --config codegen/configs/crypto_store_client.yaml https://raw.githubusercontent.com/nuts-foundation/secret-store-api/main/nuts-storage-api-v1.yaml | gofmt > crypto/storage/external/generated.go
+ oapi-codegen --config codegen/configs/policy_client_v1.yaml docs/_static/policy/v1.yaml | gofmt > policy/api/v1/client/generated.go
gen-protobuf:
protoc --go_out=paths=source_relative:network -I network network/transport/v2/protocol.proto
diff --git a/policy/api/v1/client/client.go b/policy/api/v1/client/client.go
new file mode 100644
index 0000000000..1e8b21b1d8
--- /dev/null
+++ b/policy/api/v1/client/client.go
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package client
+
+import (
+ "context"
+ "crypto/tls"
+ "encoding/json"
+ "fmt"
+ "github.com/nuts-foundation/go-did/did"
+ "io"
+ "net/http"
+ "net/url"
+ "time"
+
+ "github.com/nuts-foundation/nuts-node/core"
+ "github.com/nuts-foundation/nuts-node/vcr/pe"
+)
+
+// HTTPClient holds the server address and other basic settings for the http client
+type HTTPClient struct {
+ strictMode bool
+ httpClient core.HTTPRequestDoer
+}
+
+// NewHTTPClient creates a new api client.
+func NewHTTPClient(strictMode bool, timeout time.Duration, tlsConfig *tls.Config) HTTPClient {
+ return HTTPClient{
+ strictMode: strictMode,
+ httpClient: core.NewStrictHTTPClient(strictMode, timeout, tlsConfig),
+ }
+}
+
+// PresentationDefinition retrieves the presentation definition from the presentation definition endpoint for the given scope and .
+func (hb HTTPClient) PresentationDefinition(ctx context.Context, policyEndpoint string, authorizer did.DID, scopes string) (*pe.PresentationDefinition, error) {
+ presentationDefinitionURL, err := core.ParsePublicURL(policyEndpoint, hb.strictMode)
+ if err != nil {
+ return nil, err
+ }
+ presentationDefinitionURL.Path = fmt.Sprintf("%s/presentation_definition", presentationDefinitionURL.Path)
+ presentationDefinitionURL.RawQuery = url.Values{"scope": []string{scopes}, "authorizer": []string{authorizer.String()}}.Encode()
+
+ // create a GET request with query params
+ request, err := http.NewRequestWithContext(ctx, http.MethodGet, presentationDefinitionURL.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+ response, err := hb.httpClient.Do(request.WithContext(ctx))
+ if err != nil {
+ return nil, fmt.Errorf("failed to call endpoint: %w", err)
+ }
+ if httpErr := core.TestResponseCode(http.StatusOK, response); httpErr != nil {
+ return nil, httpErr
+ }
+
+ var presentationDefinition pe.PresentationDefinition
+ var data []byte
+
+ if data, err = io.ReadAll(response.Body); err != nil {
+ return nil, fmt.Errorf("unable to read response: %w", err)
+ }
+ if err = json.Unmarshal(data, &presentationDefinition); err != nil {
+ return nil, fmt.Errorf("unable to unmarshal response: %w", err)
+ }
+
+ return &presentationDefinition, nil
+}
diff --git a/policy/api/v1/client/client_test.go b/policy/api/v1/client/client_test.go
new file mode 100644
index 0000000000..94749da224
--- /dev/null
+++ b/policy/api/v1/client/client_test.go
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2023 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package client
+
+import (
+ "context"
+ "encoding/json"
+ "github.com/nuts-foundation/go-did/did"
+ http2 "github.com/nuts-foundation/nuts-node/test/http"
+ "github.com/nuts-foundation/nuts-node/vcr/pe"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+)
+
+func TestHTTPClient_PresentationDefinition(t *testing.T) {
+ ctx := context.Background()
+ authorizer := did.MustParseDID("did:web:example.com")
+ definition := pe.PresentationDefinition{
+ Id: "123",
+ }
+
+ t.Run("ok", func(t *testing.T) {
+ var capturedRequest *http.Request
+ handler := func(writer http.ResponseWriter, request *http.Request) {
+ switch request.URL.Path {
+ case "/presentation_definition":
+ capturedRequest = request
+ writer.WriteHeader(http.StatusOK)
+ bytes, _ := json.Marshal(definition)
+ writer.Write(bytes)
+ }
+ writer.WriteHeader(http.StatusNotFound)
+ }
+ tlsServer, client := testServerAndClient(t, http.HandlerFunc(handler))
+
+ response, err := client.PresentationDefinition(ctx, tlsServer.URL, authorizer, "test")
+
+ require.NoError(t, err)
+ require.NotNil(t, definition)
+ assert.Equal(t, definition, *response)
+ require.NotNil(t, capturedRequest)
+ assert.Equal(t, "GET", capturedRequest.Method)
+ assert.Equal(t, "/presentation_definition", capturedRequest.URL.Path)
+ // check query params
+ require.NotNil(t, capturedRequest.URL.Query().Get("scope"))
+ assert.Equal(t, "test", capturedRequest.URL.Query().Get("scope"))
+ require.NotNil(t, capturedRequest.URL.Query().Get("authorizer"))
+ assert.Equal(t, authorizer.String(), capturedRequest.URL.Query().Get("authorizer"))
+ })
+ t.Run("error - not found", func(t *testing.T) {
+ handler := http2.Handler{StatusCode: http.StatusNotFound}
+ tlsServer, client := testServerAndClient(t, &handler)
+
+ response, err := client.PresentationDefinition(ctx, tlsServer.URL, authorizer, "test")
+
+ require.Error(t, err)
+ assert.EqualError(t, err, "server returned HTTP 404 (expected: 200)")
+ assert.Nil(t, response)
+ })
+ t.Run("error - invalid URL", func(t *testing.T) {
+ handler := http2.Handler{StatusCode: http.StatusNotFound}
+ _, client := testServerAndClient(t, &handler)
+
+ response, err := client.PresentationDefinition(ctx, ":", authorizer, "test")
+
+ require.Error(t, err)
+ assert.EqualError(t, err, "parse \":\": missing protocol scheme")
+ assert.Nil(t, response)
+ })
+ t.Run("error - invalid response", func(t *testing.T) {
+ handler := http2.Handler{StatusCode: http.StatusOK, ResponseData: "}"}
+ tlsServer, client := testServerAndClient(t, &handler)
+
+ response, err := client.PresentationDefinition(ctx, tlsServer.URL, authorizer, "test")
+
+ require.Error(t, err)
+ assert.EqualError(t, err, "unable to unmarshal response: invalid character '}' looking for beginning of value")
+ assert.Nil(t, response)
+ })
+}
+
+func testServerAndClient(t *testing.T, handler http.Handler) (*httptest.Server, *HTTPClient) {
+ tlsServer := http2.TestTLSServer(t, handler)
+ return tlsServer, &HTTPClient{
+ httpClient: tlsServer.Client(),
+ }
+}
diff --git a/policy/api/v1/client/generated.go b/policy/api/v1/client/generated.go
new file mode 100644
index 0000000000..ad20e5c8cd
--- /dev/null
+++ b/policy/api/v1/client/generated.go
@@ -0,0 +1,455 @@
+// Package client provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen/v2 version v2.0.0 DO NOT EDIT.
+package client
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "github.com/oapi-codegen/runtime"
+)
+
+// AuthorizedRequest The request contains all params involved with the request.
+// It might be the case that the caller mapped credential fields to additional params.
+type AuthorizedRequest struct {
+ // Audience The audience of the access token. This is the identifier (DID) of the authorizer and issuer of the access token.
+ Audience string `json:"audience"`
+
+ // ClientId The client ID of the client that requested the resource (DID).
+ ClientId string `json:"client_id"`
+
+ // PresentationSubmission A presentation submission is a JSON object that maps requirements from the Presentation Definition to the verifiable presentations that were used to request an access token.
+ // Specified at https://identity.foundation/presentation-exchange/spec/v2.0.0/
+ // A JSON schema is available at https://identity.foundation/presentation-exchange/#json-schema
+ PresentationSubmission PresentationSubmission `json:"presentation_submission"`
+
+ // RequestMethod The method of the resource request.
+ RequestMethod string `json:"request_method"`
+
+ // RequestUrl The URL of the resource request.
+ RequestUrl string `json:"request_url"`
+
+ // Scope The scope used in the authorization request.
+ Scope string `json:"scope"`
+
+ // Vps The verifiable presentations that were used to request the access token.
+ // The verifiable presentations could be in JWT format or in JSON format.
+ Vps []interface{} `json:"vps"`
+}
+
+// AuthorizedResponse The response indicates if the access token grants access to the requested resource.
+// If the access token grants access, the response will be 200 with a boolean value set to true.
+// If the access token does not grant access, the response will be 200 with a boolean value set to false.
+type AuthorizedResponse struct {
+ // Authorized Indicates if the access token grants access to the requested resource.
+ Authorized bool `json:"authorized"`
+}
+
+// PresentationDefinitionParams defines parameters for PresentationDefinition.
+type PresentationDefinitionParams struct {
+ // Authorizer URLEncoded DID.
+ Authorizer string `form:"authorizer" json:"authorizer"`
+
+ // Scope This is the scope used in the OpenID4VP authorization request.
+ // It is a space separated list of scopes.
+ Scope string `form:"scope" json:"scope"`
+}
+
+// CheckAuthorizedJSONRequestBody defines body for CheckAuthorized for application/json ContentType.
+type CheckAuthorizedJSONRequestBody = AuthorizedRequest
+
+// RequestEditorFn is the function signature for the RequestEditor callback function
+type RequestEditorFn func(ctx context.Context, req *http.Request) error
+
+// Doer performs HTTP requests.
+//
+// The standard http.Client implements this interface.
+type HttpRequestDoer interface {
+ Do(req *http.Request) (*http.Response, error)
+}
+
+// Client which conforms to the OpenAPI3 specification for this service.
+type Client struct {
+ // The endpoint of the server conforming to this interface, with scheme,
+ // https://api.deepmap.com for example. This can contain a path relative
+ // to the server, such as https://api.deepmap.com/dev-test, and all the
+ // paths in the swagger spec will be appended to the server.
+ Server string
+
+ // Doer for performing requests, typically a *http.Client with any
+ // customized settings, such as certificate chains.
+ Client HttpRequestDoer
+
+ // A list of callbacks for modifying requests which are generated before sending over
+ // the network.
+ RequestEditors []RequestEditorFn
+}
+
+// ClientOption allows setting custom parameters during construction
+type ClientOption func(*Client) error
+
+// Creates a new Client, with reasonable defaults
+func NewClient(server string, opts ...ClientOption) (*Client, error) {
+ // create a client with sane default values
+ client := Client{
+ Server: server,
+ }
+ // mutate client and add all optional params
+ for _, o := range opts {
+ if err := o(&client); err != nil {
+ return nil, err
+ }
+ }
+ // ensure the server URL always has a trailing slash
+ if !strings.HasSuffix(client.Server, "/") {
+ client.Server += "/"
+ }
+ // create httpClient, if not already present
+ if client.Client == nil {
+ client.Client = &http.Client{}
+ }
+ return &client, nil
+}
+
+// WithHTTPClient allows overriding the default Doer, which is
+// automatically created using http.Client. This is useful for tests.
+func WithHTTPClient(doer HttpRequestDoer) ClientOption {
+ return func(c *Client) error {
+ c.Client = doer
+ return nil
+ }
+}
+
+// WithRequestEditorFn allows setting up a callback function, which will be
+// called right before sending the request. This can be used to mutate the request.
+func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
+ return func(c *Client) error {
+ c.RequestEditors = append(c.RequestEditors, fn)
+ return nil
+ }
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+ // CheckAuthorizedWithBody request with any body
+ CheckAuthorizedWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ CheckAuthorized(ctx context.Context, body CheckAuthorizedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+ // PresentationDefinition request
+ PresentationDefinition(ctx context.Context, params *PresentationDefinitionParams, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) CheckAuthorizedWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewCheckAuthorizedRequestWithBody(c.Server, contentType, body)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) CheckAuthorized(ctx context.Context, body CheckAuthorizedJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewCheckAuthorizedRequest(c.Server, body)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+func (c *Client) PresentationDefinition(ctx context.Context, params *PresentationDefinitionParams, reqEditors ...RequestEditorFn) (*http.Response, error) {
+ req, err := NewPresentationDefinitionRequest(c.Server, params)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+ return nil, err
+ }
+ return c.Client.Do(req)
+}
+
+// NewCheckAuthorizedRequest calls the generic CheckAuthorized builder with application/json body
+func NewCheckAuthorizedRequest(server string, body CheckAuthorizedJSONRequestBody) (*http.Request, error) {
+ var bodyReader io.Reader
+ buf, err := json.Marshal(body)
+ if err != nil {
+ return nil, err
+ }
+ bodyReader = bytes.NewReader(buf)
+ return NewCheckAuthorizedRequestWithBody(server, "application/json", bodyReader)
+}
+
+// NewCheckAuthorizedRequestWithBody generates requests for CheckAuthorized with any type of body
+func NewCheckAuthorizedRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/authorized")
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ req, err := http.NewRequest("POST", queryURL.String(), body)
+ if err != nil {
+ return nil, err
+ }
+
+ req.Header.Add("Content-Type", contentType)
+
+ return req, nil
+}
+
+// NewPresentationDefinitionRequest generates requests for PresentationDefinition
+func NewPresentationDefinitionRequest(server string, params *PresentationDefinitionParams) (*http.Request, error) {
+ var err error
+
+ serverURL, err := url.Parse(server)
+ if err != nil {
+ return nil, err
+ }
+
+ operationPath := fmt.Sprintf("/presentation_definition")
+ if operationPath[0] == '/' {
+ operationPath = "." + operationPath
+ }
+
+ queryURL, err := serverURL.Parse(operationPath)
+ if err != nil {
+ return nil, err
+ }
+
+ if params != nil {
+ queryValues := queryURL.Query()
+
+ if queryFrag, err := runtime.StyleParamWithLocation("form", true, "authorizer", runtime.ParamLocationQuery, params.Authorizer); err != nil {
+ return nil, err
+ } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+ return nil, err
+ } else {
+ for k, v := range parsed {
+ for _, v2 := range v {
+ queryValues.Add(k, v2)
+ }
+ }
+ }
+
+ if queryFrag, err := runtime.StyleParamWithLocation("form", true, "scope", runtime.ParamLocationQuery, params.Scope); err != nil {
+ return nil, err
+ } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+ return nil, err
+ } else {
+ for k, v := range parsed {
+ for _, v2 := range v {
+ queryValues.Add(k, v2)
+ }
+ }
+ }
+
+ queryURL.RawQuery = queryValues.Encode()
+ }
+
+ req, err := http.NewRequest("GET", queryURL.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+
+ return req, nil
+}
+
+func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
+ for _, r := range c.RequestEditors {
+ if err := r(ctx, req); err != nil {
+ return err
+ }
+ }
+ for _, r := range additionalEditors {
+ if err := r(ctx, req); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// ClientWithResponses builds on ClientInterface to offer response payloads
+type ClientWithResponses struct {
+ ClientInterface
+}
+
+// NewClientWithResponses creates a new ClientWithResponses, which wraps
+// Client with return type handling
+func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
+ client, err := NewClient(server, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return &ClientWithResponses{client}, nil
+}
+
+// WithBaseURL overrides the baseURL.
+func WithBaseURL(baseURL string) ClientOption {
+ return func(c *Client) error {
+ newBaseURL, err := url.Parse(baseURL)
+ if err != nil {
+ return err
+ }
+ c.Server = newBaseURL.String()
+ return nil
+ }
+}
+
+// ClientWithResponsesInterface is the interface specification for the client with responses above.
+type ClientWithResponsesInterface interface {
+ // CheckAuthorizedWithBodyWithResponse request with any body
+ CheckAuthorizedWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CheckAuthorizedResponse, error)
+
+ CheckAuthorizedWithResponse(ctx context.Context, body CheckAuthorizedJSONRequestBody, reqEditors ...RequestEditorFn) (*CheckAuthorizedResponse, error)
+
+ // PresentationDefinitionWithResponse request
+ PresentationDefinitionWithResponse(ctx context.Context, params *PresentationDefinitionParams, reqEditors ...RequestEditorFn) (*PresentationDefinitionResponse, error)
+}
+
+type CheckAuthorizedResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *AuthorizedResponse
+}
+
+// Status returns HTTPResponse.Status
+func (r CheckAuthorizedResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r CheckAuthorizedResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+type PresentationDefinitionResponse struct {
+ Body []byte
+ HTTPResponse *http.Response
+ JSON200 *PresentationDefinition
+}
+
+// Status returns HTTPResponse.Status
+func (r PresentationDefinitionResponse) Status() string {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.Status
+ }
+ return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PresentationDefinitionResponse) StatusCode() int {
+ if r.HTTPResponse != nil {
+ return r.HTTPResponse.StatusCode
+ }
+ return 0
+}
+
+// CheckAuthorizedWithBodyWithResponse request with arbitrary body returning *CheckAuthorizedResponse
+func (c *ClientWithResponses) CheckAuthorizedWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*CheckAuthorizedResponse, error) {
+ rsp, err := c.CheckAuthorizedWithBody(ctx, contentType, body, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseCheckAuthorizedResponse(rsp)
+}
+
+func (c *ClientWithResponses) CheckAuthorizedWithResponse(ctx context.Context, body CheckAuthorizedJSONRequestBody, reqEditors ...RequestEditorFn) (*CheckAuthorizedResponse, error) {
+ rsp, err := c.CheckAuthorized(ctx, body, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParseCheckAuthorizedResponse(rsp)
+}
+
+// PresentationDefinitionWithResponse request returning *PresentationDefinitionResponse
+func (c *ClientWithResponses) PresentationDefinitionWithResponse(ctx context.Context, params *PresentationDefinitionParams, reqEditors ...RequestEditorFn) (*PresentationDefinitionResponse, error) {
+ rsp, err := c.PresentationDefinition(ctx, params, reqEditors...)
+ if err != nil {
+ return nil, err
+ }
+ return ParsePresentationDefinitionResponse(rsp)
+}
+
+// ParseCheckAuthorizedResponse parses an HTTP response from a CheckAuthorizedWithResponse call
+func ParseCheckAuthorizedResponse(rsp *http.Response) (*CheckAuthorizedResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &CheckAuthorizedResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest AuthorizedResponse
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
+
+// ParsePresentationDefinitionResponse parses an HTTP response from a PresentationDefinitionWithResponse call
+func ParsePresentationDefinitionResponse(rsp *http.Response) (*PresentationDefinitionResponse, error) {
+ bodyBytes, err := io.ReadAll(rsp.Body)
+ defer func() { _ = rsp.Body.Close() }()
+ if err != nil {
+ return nil, err
+ }
+
+ response := &PresentationDefinitionResponse{
+ Body: bodyBytes,
+ HTTPResponse: rsp,
+ }
+
+ switch {
+ case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+ var dest PresentationDefinition
+ if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+ return nil, err
+ }
+ response.JSON200 = &dest
+
+ }
+
+ return response, nil
+}
diff --git a/policy/api/v1/client/types.go b/policy/api/v1/client/types.go
new file mode 100644
index 0000000000..b9aad6779b
--- /dev/null
+++ b/policy/api/v1/client/types.go
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package client
+
+import "github.com/nuts-foundation/nuts-node/vcr/pe"
+
+// PresentationDefinition is a type alias for the PresentationDefinition from the nuts-node/vcr/pe package.
+type PresentationDefinition = pe.PresentationDefinition
+
+// PresentationSubmission is a type alias for the PresentationSubmission from the nuts-node/vcr/pe package.
+type PresentationSubmission = pe.PresentationSubmission