Skip to content

Commit

Permalink
Merge branch 'master' into feature/2491/presentation_definition_endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
woutslakhorst authored Oct 25, 2023
2 parents b9922ba + 9ed1889 commit 1ad5000
Show file tree
Hide file tree
Showing 95 changed files with 4,375 additions and 927 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# golang alpine
FROM golang:1.21.1-alpine as builder
FROM golang:1.21.3-alpine as builder

ARG TARGETARCH
ARG TARGETOS
Expand Down
9 changes: 7 additions & 2 deletions auth/api/auth/v1/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
"net/http"
"net/http/httptest"
"net/url"
"reflect"
"testing"
Expand Down Expand Up @@ -165,8 +166,12 @@ func TestWrapper_GetSignSessionStatus(t *testing.T) {

response, err := ctx.wrapper.GetSignSessionStatus(ctx.audit, sessionObj)

assert.Equal(t, expectedResponse, response)
assert.NoError(t, err)
require.NoError(t, err)
actualResponseJSON := httptest.NewRecorder()
require.NoError(t, response.VisitGetSignSessionStatusResponse(actualResponseJSON))
expectedResponseJSON := httptest.NewRecorder()
require.NoError(t, expectedResponse.VisitGetSignSessionStatusResponse(expectedResponseJSON))
assert.JSONEq(t, string(expectedResponseJSON.Body.Bytes()), string(actualResponseJSON.Body.Bytes()))
})

t.Run("nok - SigningSessionStatus returns error", func(t *testing.T) {
Expand Down
24 changes: 12 additions & 12 deletions auth/api/iam/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ import (
"github.com/nuts-foundation/nuts-node/auth"
"github.com/nuts-foundation/nuts-node/auth/log"
"github.com/nuts-foundation/nuts-node/core"
"github.com/nuts-foundation/nuts-node/storage"
"github.com/nuts-foundation/nuts-node/vcr"
"github.com/nuts-foundation/nuts-node/vdr"
"github.com/nuts-foundation/nuts-node/vdr/resolver"
"html/template"
"net/http"
"strings"
"sync"
)

var _ core.Routable = &Wrapper{}
Expand All @@ -49,25 +49,25 @@ var assets embed.FS

// Wrapper handles OAuth2 flows.
type Wrapper struct {
vcr vcr.VCR
vdr vdr.VDR
auth auth.AuthenticationServices
sessions *SessionManager
templates *template.Template
vcr vcr.VCR
vdr vdr.VDR
auth auth.AuthenticationServices
templates *template.Template
storageEngine storage.Engine
}

func New(authInstance auth.AuthenticationServices, vcrInstance vcr.VCR, vdrInstance vdr.VDR) *Wrapper {
func New(authInstance auth.AuthenticationServices, vcrInstance vcr.VCR, vdrInstance vdr.VDR, storageEngine storage.Engine) *Wrapper {
templates := template.New("oauth2 templates")
_, err := templates.ParseFS(assets, "assets/*.html")
if err != nil {
panic(err)
}
return &Wrapper{
sessions: &SessionManager{sessions: new(sync.Map)},
auth: authInstance,
vcr: vcrInstance,
vdr: vdrInstance,
templates: templates,
storageEngine: storageEngine,
auth: authInstance,
vcr: vcrInstance,
vdr: vdrInstance,
templates: templates,
}
}

Expand Down
8 changes: 6 additions & 2 deletions auth/api/iam/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/nuts-foundation/nuts-node/auth"
"github.com/nuts-foundation/nuts-node/core"
"github.com/nuts-foundation/nuts-node/vcr/pe"
"github.com/nuts-foundation/nuts-node/storage"
"github.com/nuts-foundation/nuts-node/vdr"
"github.com/nuts-foundation/nuts-node/vdr/resolver"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -283,18 +284,21 @@ func newTestClient(t testing.TB) *testCtx {
publicURL, err := url.Parse("https://example.com")
require.NoError(t, err)
ctrl := gomock.NewController(t)
storageEngine := storage.NewTestStorageEngine(t)
authnServices := auth.NewMockAuthenticationServices(ctrl)
authnServices.EXPECT().PublicURL().Return(publicURL).AnyTimes()
resolver := resolver.NewMockDIDResolver(ctrl)
vdr := vdr.NewMockVDR(ctrl)
vdr.EXPECT().Resolver().Return(resolver).AnyTimes()

return &testCtx{
authnServices: authnServices,
resolver: resolver,
vdr: vdr,
client: &Wrapper{
auth: authnServices,
vdr: vdr,
auth: authnServices,
vdr: vdr,
storageEngine: storageEngine,
},
}
}
Expand Down
115 changes: 0 additions & 115 deletions auth/api/iam/authorized_code.go

This file was deleted.

25 changes: 19 additions & 6 deletions auth/api/iam/openid4vp.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/google/uuid"
"github.com/labstack/echo/v4"
ssi "github.com/nuts-foundation/go-did"
"github.com/nuts-foundation/go-did/did"
Expand All @@ -33,8 +34,11 @@ import (
"net/http"
"net/url"
"strings"
"time"
)

const sessionExpiry = 5 * time.Minute

// createPresentationRequest creates a new Authorization Request as specified by OpenID4VP: https://openid.net/specs/openid-4-verifiable-presentations-1_0.html.
// It is sent by a verifier to a wallet, to request one or more verifiable credentials as verifiable presentation from the wallet.
func (r *Wrapper) sendPresentationRequest(ctx context.Context, response http.ResponseWriter, scope string,
Expand Down Expand Up @@ -145,7 +149,12 @@ func (r *Wrapper) handlePresentationRequest(params map[string]string, session *S
}
session.ServerState["openid4vp_credentials"] = credentialIDs

templateParams.SessionID = r.sessions.Create(*session)
sessionID := uuid.NewString()
err = r.storageEngine.GetSessionDatabase().GetStore(sessionExpiry, session.OwnDID.String(), "session").Put(sessionID, *session)
if err != nil {
return nil, err
}
templateParams.SessionID = sessionID

// TODO: Support multiple languages
buf := new(bytes.Buffer)
Expand All @@ -162,12 +171,16 @@ func (r *Wrapper) handlePresentationRequest(params map[string]string, session *S
// handleAuthConsent handles the authorization consent form submission.
func (r *Wrapper) handlePresentationRequestAccept(c echo.Context) error {
// TODO: Needs authentication?
var session *Session
if sessionID := c.FormValue("sessionID"); sessionID != "" {
session = r.sessions.Get(sessionID)
sessionID := c.FormValue("sessionID")
if sessionID == "" {
return errors.New("missing sessionID parameter")
}
if session == nil {
return errors.New("invalid session")

var session Session
sessionStore := r.storageEngine.GetSessionDatabase().GetStore(sessionExpiry, "openid", session.OwnDID.String(), "session")
err := sessionStore.Get(sessionID, &session)
if err != nil {
return fmt.Errorf("invalid session: %w", err)
}

// TODO: Change to loading from wallet
Expand Down
11 changes: 6 additions & 5 deletions auth/api/iam/openid4vp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/nuts-foundation/go-did/did"
"github.com/nuts-foundation/go-did/vc"
"github.com/nuts-foundation/nuts-node/auth"
"github.com/nuts-foundation/nuts-node/storage"
"github.com/nuts-foundation/nuts-node/vcr"
"github.com/nuts-foundation/nuts-node/vcr/credential"
"github.com/nuts-foundation/nuts-node/vcr/holder"
Expand All @@ -42,7 +43,7 @@ var holderDID = did.MustParseDID("did:web:example.com:holder")
var issuerDID = did.MustParseDID("did:web:example.com:issuer")

func TestWrapper_sendPresentationRequest(t *testing.T) {
instance := New(nil, nil, nil)
instance := New(nil, nil, nil, nil)

redirectURI, _ := url.Parse("https://example.com/redirect")
verifierID, _ := url.Parse("https://example.com/verifier")
Expand Down Expand Up @@ -92,7 +93,7 @@ func TestWrapper_handlePresentationRequest(t *testing.T) {
t.Run("with scope", func(t *testing.T) {
ctrl := gomock.NewController(t)
peStore := &pe.DefinitionResolver{}
_ = peStore.LoadFromFile("test/presentation_definition_mapping.json")
require.NoError(t, peStore.LoadFromFile("test/presentation_definition_mapping.json"))
mockVDR := vdr.NewMockVDR(ctrl)
mockVCR := vcr.NewMockVCR(ctrl)
mockWallet := holder.NewMockWallet(ctrl)
Expand All @@ -101,7 +102,7 @@ func TestWrapper_handlePresentationRequest(t *testing.T) {
mockAuth.EXPECT().PresentationDefinitions().Return(peStore)
mockWallet.EXPECT().List(gomock.Any(), holderDID).Return(walletCredentials, nil)
mockVDR.EXPECT().IsOwner(gomock.Any(), holderDID).Return(true, nil)
instance := New(mockAuth, mockVCR, mockVDR)
instance := New(mockAuth, mockVCR, mockVDR, storage.NewTestStorageEngine(t))

params := map[string]string{
"scope": "test",
Expand All @@ -124,7 +125,7 @@ func TestWrapper_handlePresentationRequest(t *testing.T) {
_ = peStore.LoadFromFile("test/presentation_definition_mapping.json")
mockAuth := auth.NewMockAuthenticationServices(ctrl)
mockAuth.EXPECT().PresentationDefinitions().Return(peStore)
instance := New(mockAuth, nil, nil)
instance := New(mockAuth, nil, nil, nil)

params := map[string]string{
"scope": "unsupported",
Expand All @@ -139,7 +140,7 @@ func TestWrapper_handlePresentationRequest(t *testing.T) {
assert.Nil(t, response)
})
t.Run("invalid response_mode", func(t *testing.T) {
instance := New(nil, nil, nil)
instance := New(nil, nil, nil, nil)
params := map[string]string{
"scope": "eOverdracht-overdrachtsbericht",
"response_type": "code",
Expand Down
Loading

0 comments on commit 1ad5000

Please sign in to comment.